Pregunta

Quiero usar el efecto de marquesina en una TextView, pero el texto sólo se está desplazando cuando el TextView obtiene foco. Eso es un problema, ya que en mi caso, no se puede.

Estoy utilizando:

  android:ellipsize="marquee"
  android:marqueeRepeatLimit="marquee_forever"

¿Hay una manera de tener el TextView siempre desplazarse de su texto? He visto que esto se hace en la aplicación Android Market, donde el nombre de la aplicación se desplazará en la barra de título, incluso si no recibe atención, pero no pude encontrar esto se menciona en los documentos de la API.

¿Fue útil?

Solución

He tenido que hacer frente al problema y la solución más corta que he llegado con es crear una nueva clase derivada de Vista de Texto. La clase debe anular tres métodos OnFocusChanged , onWindowFocusChanged y IsFocused para hacer el TextView todo enfocado.

@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;
}

Otros consejos

Finalmente ocurrió en contra de este problema hoy en día y por lo dispararon hasta hierarchyviewer en la aplicación Android Market.

Mirando el título en la pantalla de detalles de una aplicación, que utilizan una TextView simple y llano. Examinar sus propiedades demostraron que no se centró, podría no se centrará y en general era muy común -. Excepto por el hecho de que fue marcado como seleccionado

Una línea de código más tarde y tuve que trabajar:)

textView.setSelected(true);

Esto tiene sentido, teniendo en cuenta lo el Javadoc dice :

  

Una vista puede ser seleccionado o no. Tenga en cuenta que la selección no es lo mismo que el foco. Vistas se seleccionan típicamente en el contexto de un AdapterView como ListView o GridView.

es decir. Cuando se desplaza sobre un elemento en una vista de lista (como en la aplicación Market), sólo entonces el texto ahora como Iniciar el desplazamiento. Y puesto que este TextView particular no es enfocable o puede hacer clic, que nunca pierde su estado de selección.

Por desgracia, por lo que yo sé que no hay manera de pre-establecer el estado seleccionado del XML diseño.
Sin embargo, la sola línea anterior funciona bien para mí.

Sólo hay que poner estos parámetros en su Vista de Texto. Funciona:)

    android:singleLine="true" 
    android:ellipsize="marquee"
    android:marqueeRepeatLimit ="marquee_forever"
    android:scrollHorizontally="true"
    android:focusable="true"
    android:focusableInTouchMode="true" 

TranslateAnimation funciona "tirando" de la vista en una dirección por una cantidad especificada. Se puede establecer por dónde empezar este "tirar" y dónde terminar.

TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);

fromXDelta establece el desplazamiento de la posición de partida del movimiento en el eje 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 la posición final de desplazamiento del movimiento en el eje 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.

Si la anchura de su texto es mayor que el módulo de la diferencia entre fromXDelta y toXDelta, el texto no será capaz de mover y totalmente compeltely dentro de la pantalla.


Ejemplo

Vamos a suponer que nuestro tamaño de la pantalla es de 320x240 pxs. Tenemos un TextView con un texto que tiene 700px de anchura y deseamos crear una animación que "tira" el texto para que podamos ver el final de la 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... ||
                             ---------------------------+|
                             |                           |
                             |                           |
                             |                           |
                             +---------------------------+

En primer lugar, establecer fromXDelta = 0 para que el movimiento no tiene un desplazamiento inicial. Ahora tenemos que calcular el valor toXDelta. Para lograr el efecto deseado es necesario "tirar" el texto del mismo px exacta que se extiende por fuera de la pantalla. (En el esquema está representado por <<<< >>>> X px) Desde nuestro texto tiene 700 el ancho y el área visible es de 320 píxeles (ancho de la pantalla) nos propusimos:

tXDelta = 700 - 320 = 380

Y ¿Cómo calculamos la pantalla Ancho y el texto Anchura?


Código

Tomando el Zarah de fragmentos como punto 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;
}

Puede haber maneras más fáciles de realizar esto, pero esto funciona para cada vista se puede imaginar y es reutilizable. Es especialmente útil si lo desea animar un TextView en un ListView sin romper las habilidades / OnFocus habilitados de la TextView. También se desplaza de forma continua, incluso si la vista no está enfocado.

No sé si todavía necesita la respuesta, pero he encontrado una manera fácil de hacer esto.

Configurar la animación de esta manera:

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 y END_POS_Y son valores float, mientras TICKER_DURATION es un int declaré con mis otras constantes.

A continuación, puede ahora aplicar esta animación al TextView:

TextView tickerText = (TextView) findViewById(R.id.ticker);
tickerText.setAnimation(mAnimation);

Y eso es todo. :)

Mi animación comienza en el lado derecho fuera de la pantalla (300f) y termina en el lado izquierdo fuera de la pantalla (-300f), con una duración de 15 s (15000).

he escrito el siguiente código para un ListView con elementos de texto de marquesina. Se basa en la solución setSelected descrito anteriormente. Básicamente, yo estoy extendiendo la clase ArrayAdapter y reemplazar el método getView para seleccionar la Vista de Texto antes de devolverlo:

    // 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 es la respuesta que aparece en la parte superior de mi búsqueda de google, así que pensé que podría publicar una respuesta útil aquí, ya que lucha con recordar esto con bastante frecuencia. De todos modos, esto funciona para mí y requiere atributos XML y A un 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" />

En Java //

        mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mtvMarque.setSelected(true);
        mtvMarque.setSingleLine(true);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top