Est-il possible de faire ellipsize = “chapiteau” toujours défiler?

Je veux utiliser l’effet de sélection sur un TextView, mais le texte ne défile que lorsque le TextView obtient le focus. C’est un problème, car dans mon cas, ça ne peut pas.

J’utilise:

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

Est-il possible que le TextView fasse toujours défiler son texte? Je l’ai vu dans l’application Android Market, où le nom de l’application défilera dans la barre de titre, même s’il ne reçoit pas le focus, mais je n’ai pas trouvé cela mentionné dans les documents de l’API.

J’ai été confronté au problème et la solution la plus courte que j’ai proposée est de créer une nouvelle classe dérivée de TextView. La classe doit remplacer trois méthodes onFocusChanged , onWindowFocusChanged et isFocused pour que le TextView soit concentré.

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

Je me suis finalement heurté à ce problème aujourd’hui et j’ai donc lancé hierarchyviewer sur l’application Android Market.

En regardant le titre sur l’écran de détail d’une application, ils utilisent un vieux TextView . L’examen de ses propriétés a montré qu’il n’était pas ciblé, qu’il ne pouvait pas être ciblé et qu’il était généralement très ordinaire – sauf qu’il était marqué comme sélectionné .

Une ligne de code plus tard et je l’ai fait fonctionner 🙂

 textView.setSelected(true); 

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

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), alors seulement le texte maintenant sélectionné commence à défiler. Et comme ce TextView particulier TextView peut pas être TextView ou cliqué, il ne perdra jamais son état de sélection.

Malheureusement, pour autant que je sache, il n’y a aucun moyen de prédéfinir l’état sélectionné à partir du XML de mise en page.
Mais le one-liner ci-dessus fonctionne bien pour moi.

Il suffit de mettre ces parameters dans votre TextView. Ça marche 🙂

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

Je ne sais pas si vous avez toujours 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 et END_POS_Y sont des valeurs float , tandis que TICKER_DURATION est un int j’ai déclaré avec mes autres constantes.

Ensuite, 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 de l’écran (-300f), avec une durée de 15s (15000).

TranslateAnimation fonctionne en “tirant” la vue dans une direction d’un montant spécifié. Vous pouvez définir où commencer ce “tirer” et où se terminer.

 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 la position de fin de décalage du mouvement sur l’axe 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 à celle du module de la différence entre fromXDelta et toXDelta, le texte ne pourra pas se déplacer de manière complète et précise dans l’écran.


Exemple

Supposons que notre taille d’écran est de 320×240 px. Nous avons un TextView avec un texte qui a une largeur de 700px 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... || ---------------------------+| | | | | | | +---------------------------+ 

Nous fromXDelta = 0 définir fromXDelta = 0 pour que le mouvement n'ait pas de décalage de départ. Maintenant, nous devons calculer la valeur de toXDelta. Pour obtenir l'effet désiré, nous devons "extraire" le texte exactement le même px que celui qui sort de l'écran. (dans le schéma est représenté par < <<< X px >>>>) Puisque notre texte a 700 largeur, et la zone visible est 320px (largeur de l'écran), nous définissons:

 tXDelta = 700 - 320 = 380 

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


Code

Prenant le snippet de Zarah comme sharepoint 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 y a peut-être des moyens plus faciles de procéder, mais cela fonctionne pour toutes les vues possibles et réutilisables. Il est particulièrement utile si vous souhaitez animer un TextView dans un ListView sans casser les capacités activées / onFocus de textView. Il défile également en continu même si la vue n'est pas mise au point.

J’ai écrit le code suivant pour un ListView avec des éléments de texte marqués. Il est basé sur la solution setSelected décrite ci-dessus. Fondamentalement, je développe la classe ArrayAdapter et remplace la méthode getView pour sélectionner le TextView avant de le renvoyer:

  // 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 { 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; } } 

Ceci est la réponse qui apparaît en haut de ma recherche google, alors j’ai pensé que je pourrais poster une réponse utile ici, car j’ai du mal à me souvenir de cela assez souvent. Quoi qu’il en soit, cela fonctionne pour moi et nécessite des atsortingbuts XML et A un onFocusChangeListener.

 //XML  //JAVA titleText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { titleText.setSelected(true); } } });