Ich möchte den Marquee-Effekt für eine TextView verwenden, der Text wird jedoch nur gescrollt, wenn die TextView den Fokus erhält. Das ist ein Problem, weil es in meinem Fall nicht geht.
Ich benutze:
Android:ellipsize="Marquee"
Android:marqueeRepeatLimit="Marquee_forever"
Gibt es eine Möglichkeit, die Textansicht immer durchlaufen zu lassen? Ich habe gesehen, wie dies in der Android Market-App durchgeführt wurde, wo der App-Name in der Titelleiste angezeigt wird, auch wenn er keinen Fokus erhält. In den API-Dokumenten wurde dies nicht erwähnt.
Ich bin mit dem Problem konfrontiert und die kürzeste Lösung, die ich gefunden habe, ist das Erstellen einer neuen, von TextView abgeleiteten Klasse .. Die Klasse sollte die drei Methoden onFocusChanged, onWindowFocusChanged und isFocused überschreiben. ], um das TextView zu fokussieren.
@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;
}
Ich bin heute endlich auf dieses Problem gestoßen und habe hierarchyviewer
in der Android Market-Anwendung angeheizt.
Wenn Sie den Titel auf dem Detailbildschirm einer App betrachten, verwenden Sie ein einfaches altes TextView
. Die Untersuchung seiner Eigenschaften zeigte, dass es nicht fokussiert war, konnte nicht fokussiert werden und war im Allgemeinen sehr gewöhnlich - mit Ausnahme der Tatsache, dass es als selected markiert war.
Eine Zeile Code später und ich hatte es funktioniert :)
textView.setSelected(true);
Dies ist sinnvoll, wenn man bedenkt, was der Javadoc sagt :
Eine Ansicht kann ausgewählt werden oder nicht. Beachten Sie, dass die Auswahl nicht mit dem Fokus identisch ist. Ansichten werden normalerweise im Kontext einer AdapterView wie ListView oder GridView ausgewählt.
wenn Sie in einer Listenansicht über ein Element blättern (wie in der Market-App), beginnt der Text jetzt ausgewählt zu blättern. Und da dieses bestimmte TextView
nicht fokussierbar oder anklickbar ist, verliert es niemals seinen Auswahlstatus.
Meines Wissens gibt es leider keine Möglichkeit, den ausgewählten Status aus dem Layout-XML vorzugeben.
Aber der Ein-Liner oben funktioniert gut für mich.
Geben Sie diese Parameter einfach in Ihre TextView ein. Es klappt :)
Android:singleLine="true"
Android:ellipsize="Marquee"
Android:marqueeRepeatLimit ="Marquee_forever"
Android:scrollHorizontally="true"
Android:focusable="true"
Android:focusableInTouchMode="true"
TranslateAnimation
arbeitet, indem Sie die Ansicht um einen bestimmten Betrag in eine Richtung "ziehen". Sie können festlegen, wo dieses "Ziehen" beginnen soll und wo Sie enden sollen.
TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
fromXDelta legt den Versatz der Startposition der Bewegung in der X-Achse fest.
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 definiert die Endposition der Verschiebung in der X-Achse.
toXDelta = 0 //no offset.
toXDelta = 300 //the movement ends at 300px to the right.
toXDelta = -300 //the movement ends at 300px to the left.
Wenn die Breite Ihres Texts größer ist als das Modul der Differenz zwischen XDelta und XDelta, kann der Text nicht vollständig innerhalb des Bildschirms verschoben werden.
Nehmen wir an, unsere Bildschirmgröße beträgt 320x240 px. Wir haben eine Textansicht mit einem Text, der 700px breit ist, und wir möchten eine Animation erstellen, die den Text "zieht", damit wir das Ende der Phrase sehen können.
(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... ||
---------------------------+|
| |
| |
| |
+---------------------------+
Zuerst setzen wir fromXDelta = 0
so, dass die Bewegung keinen Startversatz hat. Nun müssen wir den toXDelta-Wert berechnen. Um den gewünschten Effekt zu erzielen, müssen wir den Text genau so weit "ziehen", wie er aus dem Bildschirm herausragt. (In dem Schema wird dargestellt durch <<<< X px >>>>) Da unser Text eine Breite von 700 hat und der sichtbare Bereich 320px (Bildschirmbreite) ist, setzen wir:
tXDelta = 700 - 320 = 380
Und wie bestimmen wir die Bildschirmbreite und die Textbreite?
Ausgehend vom Zarah-Snippet:
/**
* @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;
}
Es gibt möglicherweise einfachere Möglichkeiten, dies auszuführen, aber dies funktioniert für jede Ansicht, die Sie sich vorstellen können, und ist wiederverwendbar. Dies ist besonders nützlich, wenn Sie eine TextView in einer ListView animieren möchten, ohne die aktivierten/onFocus-Fähigkeiten der TextView zu beschädigen. Es scrollt auch dann kontinuierlich, wenn die Ansicht nicht scharfgestellt ist.
Ich weiß nicht, ob Sie die Antwort noch brauchen, aber ich habe einen einfachen Weg gefunden, dies zu tun.
Richten Sie Ihre Animation so ein:
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
und END_POS_Y
sind float
-Werte, während TICKER_DURATION
eine int
ist, die ich mit meinen anderen Konstanten deklariert habe.
Dann können Sie diese Animation nun auf Ihre TextView anwenden:
TextView tickerText = (TextView) findViewById(R.id.ticker);
tickerText.setAnimation(mAnimation);
Und das ist es. :)
Meine Animation beginnt auf der rechten Seite außerhalb des Bildschirms (300f) und endet auf der linken Seite außerhalb des Bildschirms (-300f) mit einer Dauer von 15 Sekunden (15000).
Ich habe den folgenden Code für eine ListView mit Marquee-Textelementen geschrieben. Sie basiert auf der oben beschriebenen setSelected-Lösung. Grundsätzlich erweitere ich die ArrayAdapter-Klasse und überschreibe die getView-Methode, um die TextView auszuwählen, bevor sie zurückgegeben wird:
// 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;
}
}
Dies ist die Antwort, die ganz oben in meiner Google-Suche angezeigt wird. Ich dachte, ich könnte hier eine nützliche Antwort posten, da ich mich ziemlich oft damit beschäftige, daran zu denken ..
//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" />
// In Java
mtvMarque.setEllipsize(TextUtils.TruncateAt.Marquee);
mtvMarque.setSelected(true);
mtvMarque.setSingleLine(true);