97 votes

Existe-t-il un moyen de faire en sorte que ellipsize="marquee" défile toujours ?

Je veux utiliser l'effet de marquage sur un TextView, mais le texte ne défile que lorsque le TextView reçoit le focus. C'est un problème, car dans mon cas, ce n'est pas possible.

J'utilise :

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

Existe-t-il un moyen de faire en sorte que le TextView fasse toujours défiler son texte ? J'ai vu cela dans l'application Android Market, où le nom de l'application défile dans la barre de titre, même si elle ne reçoit pas le focus, mais je n'ai pas trouvé de mention de cela dans les documents de l'API.

0 votes

Pour que le marquage fonctionne, le TextView doit être sélectionné, pas focalisé. La mise au point permet la sélection mais pas l'inverse.

1 votes

Essayez alwaysMarqueeTextView stackoverflow.com/a/28806003/3496570

0 votes

Je changerais la bonne réponse pour celle-ci stackoverflow.com/a/3700651/4548520

122voto

Christopher Orr Points 58514

J'ai finalement été confronté à ce problème aujourd'hui et j'ai donc mis le feu. hierarchyviewer sur l'application Android Market.

Si l'on regarde le titre de l'écran de détail d'une application, on constate qu'elle utilise un bon vieil outil d'aide à la décision. TextView . L'examen de ses propriétés a montré qu'il n'était pas focalisé, ne pouvait pas être mis au point et était généralement très ordinaire - à l'exception du fait qu'il était marqué comme sélectionné .

Une ligne de code plus tard, je l'ai fait fonctionner :)

textView.setSelected(true);

Cela a du sens, étant donné ce que la Javadoc dit :

Une vue peut être sélectionnée ou non. Notez que la sélection n'est pas la même chose que le focus. Les vues sont généralement sélectionnées dans le contexte d'un AdapterView comme ListView ou GridView.

Par exemple, lorsque vous faites défiler un élément dans une vue de liste (comme dans l'application Market), ce n'est qu'à ce moment-là que l'option maintenant sélectionné le texte commence à défiler. Et comme ce texte particulier TextView n'est pas focalisable ou cliquable, il ne perdra jamais son état de sélection.

Malheureusement, pour autant que je sache, il n'existe aucun moyen de prédéfinir l'état de sélection à partir du XML de mise en page.
Mais la ligne unique ci-dessus fonctionne bien pour moi.

0 votes

Je me demandais juste : est-ce que cela fonctionnerait également pour les TextViews qui sont focalisables, mais qui devraient toujours défiler lorsqu'ils ne sont pas focalisés ? En d'autres termes, l'état de sélection reste-t-il inchangé même lorsque l'état de focalisation change ?

0 votes

Je pense que oui. Je ne vois pas pourquoi un changement d'orientation sur une base TextView (c'est-à-dire qui n'est pas intégré dans un élément "sélectionnable" tel qu'une page d'accueil). ListView ) changerait l'état sélectionné.

0 votes

Cela fonctionne bien pour moi aussi. Je vous remercie pour votre réponse. Est-il possible de changer la façon de répéter ? !

76voto

Vinayak Points 575

Il suffit de mettre ces paramètres dans votre TextView. Cela fonctionne :)

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

1 votes

Si ce fil de réponse n'est pas déjà mort, ceci devrait être la réponse acceptée, à mon avis. J'ai ajouté ceci à ma définition XML pour la vue texte, et cela a fonctionné du premier coup. J'ai essayé d'autres suggestions, et celle-ci est la plus simple. -- De plus, l'ajout de "Android:marqueeRepeatLimit="marquee_forever" permet de faire défiler le texte indéfiniment.

19 votes

L'utilisation de cette fonction interrompt la sélection du focus d'une rangée de ListView si le TextView se trouve à l'intérieur.

0 votes

Fonctionne parfaitement. Solution simple et élégante. Merci !

65voto

hnviet Points 1107

J'ai été confronté à ce problème et la solution la plus courte que j'ai trouvée est de créer une nouvelle classe dérivée de TextView. Cette classe doit surcharger trois méthodes onFocusChanged , onWindowFocusChanged y isFocused pour que le TextView soit entièrement focalisé.

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

0 votes

Parfait - c'est exactement la solution que je cherchais.

7 votes

Vous devez également surcharger la méthode onWindowFocusChanged si vous voulez que le marquee ne s'arrête pas lorsque les menus apparaissent.

7 votes

D'ailleurs, nous avons eu des problèmes avec cette solution, puisqu'elle perturbe les tableaux d'état : si vous changez les tableaux avec focus-in/focus-out, alors cette solution ne fonctionnera pas. Il nous a fallu près d'une heure de débogage avant de réaliser que ce hack était à l'origine du problème.

13voto

Tivie Points 4581

TranslateAnimation fonctionne en "tirant" la vue dans une direction d'une quantité spécifiée. Vous pouvez définir le point de départ et le point d'arrivée de cette "traction".

TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);

fromXDelta définit le décalage de la position de départ du mouvement sur l'axe 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 définit le décalage de la position finale du mouvement dans l'axe des 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 largeur de votre texte est supérieure au module de la différence entre fromXDelta et toXDelta, le texte ne pourra pas se déplacer totalement et obligatoirement dans l'écran.


Exemple

Supposons que la taille de notre écran soit de 320x240 pxs. Nous avons un TextView avec un texte de 700px de large et nous souhaitons créer une animation qui "tire" le texte pour que nous puissions voir la fin de la phrase.

                                       (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... ||
                             ---------------------------+|
                             |                           |
                             |                           |
                             |                           |
                             +---------------------------+

Tout d'abord, nous définissons fromXDelta = 0 afin que le mouvement n'ait pas de décalage de départ. Nous devons maintenant déterminer la valeur toXDelta. Pour obtenir l'effet désiré, nous devons "tirer" le texte exactement du même px qu'il s'étend hors de l'écran. (dans le schéma, cela est représenté par <<<< X px >>>>) Comme notre texte a une largeur de 700, et que la zone visible est de 320px (largeur de l'écran), nous définissons :

tXDelta = 700 - 320 = 380

Et comment calculer la largeur de l'écran et la largeur du texte ?


Code

En prenant la bribe de Zarah comme point de départ :

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

Il existe peut-être des méthodes plus simples, mais celle-ci fonctionne pour toutes les vues auxquelles vous pouvez penser et est réutilisable. Elle est particulièrement utile si vous voulez animer un TextView dans une ListView sans rompre les capacités enabled/onFocus du textView. Elle permet également un défilement continu même si la vue n'est pas focalisée.

0 votes

Est-ce que ma réponse ci-dessus (c'est-à-dire ajouter une ligne de code : textView.setSelected(true); ) ne fonctionne pas dans votre situation ?

0 votes

Malheureusement non. J'avais une ListView remplie de plusieurs TextViews dans chaque ligne (d'où la crise de l'espace =P). Chaque ligne de la TextView est cliquable et fait apparaître un menu contextuel. Le fait de mettre setSelected à true semble casser le menu contextuel.

0 votes

C'est ça ? C'est peut-être un peu exagéré dans la plupart des cas. Pour moi, pour la raison décrite ci-dessus, c'était la seule solution. (c'est réutilisable, btw !) =P

12voto

Zarah Points 3050

Je ne sais pas si vous avez encore besoin de la réponse, mais j'ai trouvé un moyen facile de le faire.

Configurez votre animation comme suit :

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 sont float tandis que TICKER_DURATION est un int J'ai déclaré avec mes autres constantes.

Vous pouvez maintenant appliquer cette animation à votre TextView :

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

Et c'est tout. :)

Mon animation commence sur le côté droit hors écran (300f) et se termine sur le côté gauche hors écran(-300f), avec une durée de 15s (15000).

1 votes

Cela ne semble pas très simple. Mais je ne pense pas qu'il ait encore besoin de la réponse ; voir la réponse acceptée ci-dessus.. :)

2 votes

Mais je pense que cette solution est plus simple que de créer une nouvelle classe :D En l'état, vous pouvez également réutiliser l'objet d'animation pour d'autres vues que vous souhaitez animer ;)

0 votes

Cela fonctionne pourtant bien, mais que dois-je faire pour afficher de longs textes ? ! Maintenant mon texte sera juste coupé

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X