Existe uma maneira de fazer ellipsize = “marquise” sempre rolagem?
Pergunta
Eu quero usar o efeito marquise em um TextView, mas o texto está apenas a ser rolada quando o TextView recebe foco. Isso é um problema, porque no meu caso, não pode.
Eu estou usando:
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
Existe uma maneira de ter o TextView sempre rolar o seu texto? Eu já vi isso sendo feito no aplicativo Android Market, onde o nome do aplicativo irá rolar na barra de título, mesmo se ele não receber o foco, mas eu não poderia encontrar este ser mencionado na documentação da API.
Solução
Eu têm vindo a enfrentar o problema e a solução mais curta que eu vim com é criar uma nova classe derivada de TextView. A classe deve substituir três métodos onFocusChanged , onWindowFocusChanged e IsFocused para fazer a TextView todos focados.
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if(focused)
super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
@Override
public void onWindowFocusChanged(boolean focused) {
if(focused)
super.onWindowFocusChanged(focused);
}
@Override
public boolean isFocused() {
return true;
}
Outras dicas
Eu finalmente subiu contra este problema hoje e assim despediu-se hierarchyviewer
sobre a aplicação Android Market.
Olhando para o título na tela de detalhes de um aplicativo, eles usam um TextView
velho liso. Examinando suas propriedades mostrou que não estava focado, não ser focado e foi geralmente muito comum - exceto para o fato de que foi marcado como selecionado
Uma linha de código mais tarde e eu tinha que trabalhar:)
textView.setSelected(true);
Isso faz sentido, dado o que o Javadoc diz :
Uma visão pode ser selecionada ou não. Note-se que a seleção não é o mesmo como o foco. Visualizações são tipicamente selecionado no contexto de uma AdapterView como ListView ou GridView.
i. Quando se desloca sobre um item em uma lista (como no aplicativo Market), só então é que o agora seleccionado início texto de rolagem. E desde que este TextView
particular não é focada ou clickable, nunca perderá seu estado de seleção.
Infelizmente, tanto quanto eu sei não há nenhuma maneira para pré-definir o estado selecionado a partir do XML layout.
Mas o one-liner acima funciona bem para mim.
Basta colocar esses parâmetros em sua TextView. Ele funciona:)
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit ="marquee_forever"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"
TranslateAnimation
obras de "puxar" a vista em uma direção por uma quantidade especificada. Você pode definir por onde começar esta "puxar" e onde terminar.
TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
fromXDelta definir o deslocamento da posição de partida do movimento no eixo dos X.
fromXDelta = 0 //no offset.
fromXDelta = 300 //the movement starts at 300px to the right.
fromXDelta = -300 //the movement starts at 300px to the left
toXDelta define a posição final de deslocamento do movimento no eixo dos X.
toXDelta = 0 //no offset.
toXDelta = 300 //the movement ends at 300px to the right.
toXDelta = -300 //the movement ends at 300px to the left.
Se a largura do seu texto é maior que o módulo da diferença entre fromXDelta e toXDelta, o texto não será capaz de movimento totalmente e compeltely dentro da tela.
Exemplo
Vamos supor que o nosso tamanho da tela é 320x240 pxs. Temos um TextView com um texto que tem 700px de largura e queremos criar uma animação que "puxa" o texto para que possamos ver o fim da frase.
(screen)
+---------------------------+
|<----------320px---------->|
| |
|+---------------------------<<<< X px >>>>
movement<-----|| some TextView with text that goes out...
|+---------------------------
| unconstrained size 700px |
| |
| |
+---------------------------+
+---------------------------+
| |
| |
<<<< X px >>>>---------------------------+|
movement<----- some TextView with text that goes out... ||
---------------------------+|
| |
| |
| |
+---------------------------+
Primeiro, fromXDelta = 0
conjunto para que o movimento não tem um deslocamento inicial. Agora precisamos descobrir o valor toXDelta. Para conseguir o efeito desejado é preciso "puxar" o texto exatamente a mesma px que se estende para fora da tela. (No esquema é representado por <<<< X px >>>>) Desde o nosso texto tem 700 largura e a área visível é 320px (largura da tela) que estabelecemos:
tXDelta = 700 - 320 = 380
E como é que vamos descobrir a tela Largura eo texto Largura?
Código
Tomando o Zarah trechos como ponto de partida:
/**
* @param view The Textview or any other view we wish to apply the movement
* @param margin A margin to take into the calculation (since the view
* might have any siblings in the same "row")
*
**/
public static Animation scrollingText(View view, float margin){
Context context = view.getContext(); //gets the context of the view
// measures the unconstrained size of the view
// before it is drawn in the layout
view.measure(View.MeasureSpec.UNSPECIFIED,
View.MeasureSpec.UNSPECIFIED);
// takes the unconstrained wisth of the view
float width = view.getMeasuredWidth();
// gets the screen width
float screenWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();
// perfrms the calculation
float toXDelta = width - (screenWidth - margin);
// sets toXDelta to 0 if the text width is smaller that the screen size
if (toXDelta < 0) {toXDelta = 0; } else { toXDelta = 0 - toXDelta;}
// Animation parameters
Animation mAnimation = new TranslateAnimation(0, toXDelta, 0, 0);
mAnimation.setDuration(15000);
mAnimation.setRepeatMode(Animation.RESTART);
mAnimation.setRepeatCount(Animation.INFINITE);
return mAnimation;
}
Pode haver maneiras mais fáceis de executar esta, mas isso funciona para cada ponto de vista que você pode pensar e é reutilizável. É especialmente útil se você quiser animar um TextView em um ListView sem quebrar os habilitados / OnFocus habilidades do textView. Também rola permanentemente, mesmo se a vista não é focado.
Eu não sei se você ainda precisa a resposta, mas eu achei uma maneira fácil de fazer isso.
Configurar sua animação assim:
Animation mAnimation = new TranslateAnimation(START_POS_X, END_POS_X,
START_POS_Y, END_POS_Y);
mAnimation.setDuration(TICKER_DURATION);
mAnimation.setRepeatMode(Animation.RESTART);
mAnimation.setRepeatCount(Animation.INFINITE);
START_POS_X
, END_POS_X
, START_POS_Y
e END_POS_Y
são valores float
, enquanto TICKER_DURATION
é um int
eu declarei com as minhas outras constantes.
Depois, você pode agora aplicar esta animação para o seu TextView:
TextView tickerText = (TextView) findViewById(R.id.ticker);
tickerText.setAnimation(mAnimation);
E é isso. :)
As minhas animação começa no lado direito fora da tela (300f) e termina no lado esquerdo fora da tela (-300f), com uma duração de 15s (15000).
Eu escrevi o seguinte código para um ListView com itens de texto marquise. Ele baseia-se na solução setSelected descrito acima. Basicamente, eu estou estendendo a classe ArrayAdapter e substituir o método getView para selecionar o TextView antes de devolvê-lo:
// Create an ArrayAdapter which selects its TextViews before returning
// them. This would enable marqueeing while still making the list item
// clickable.
class SelectingAdapter extends ArrayAdapter<LibraryItem>
{
public
SelectingAdapter(
Context context,
int resource,
int textViewResourceId,
LibraryItem[] objects
)
{
super(context, resource, textViewResourceId, objects);
}
@Override
public
View getView(int position, View convertView, ViewGroup parent)
{
View view = super.getView(position, convertView, parent);
TextView textview = (TextView) view.findViewById(
R.id.textview_playlist_item_title
);
textview.setSelected(true);
textview.setEnabled(true);
textview.setFocusable(false);
textview.setTextColor(0xffffffff);
return view;
}
}
Esta é a resposta que aparece no topo da minha pesquisa no google, então eu pensei que eu poderia postar uma resposta útil aqui desde que eu luta com a lembrança deste bastante frequência. De qualquer forma, isso funciona para mim e requer atributos XML e A um onFocusChangeListener.
//XML
<TextView
android:id="@+id/blank_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_gravity="center_horizontal|center_vertical"
android:background="#a4868585"
android:textColor="#fff"
android:textSize="15sp"
android:singleLine="true"
android:lines="1"
android:ellipsize="marquee"
android:marqueeRepeatLimit ="marquee_forever"
android:scrollHorizontally="true"
android:focusable="true"
android:focusableInTouchMode="true"
tools:ignore="Deprecated" />
//JAVA
titleText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
titleText.setSelected(true);
}
}
});
// xml
<TextView
android:id="@+id/tvMarque"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:layout_gravity="center_horizontal"
android:fadingEdge="horizontal"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:padding="5dp"
android:textSize="16sp"
android:text=""
android:textColor="@color/colorSyncText"
android:visibility="visible" />
// Em Java
mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
mtvMarque.setSelected(true);
mtvMarque.setSingleLine(true);