Я хочу использовать эффект выделения в TextView, но текст прокручивается только тогда, когда TextView получает фокус. Это проблема, потому что в моем случае это невозможно.
Я использую:
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
Есть ли способ, чтобы TextView всегда прокручивал свой текст? Я видел, как это делается в приложении Android Market, где имя приложения будет прокручиваться в строке заголовка, даже если оно не получает фокус, но я не мог найти упоминания об этом в документации API.
Ответы:
Я столкнулся с проблемой, и самое короткое решение, которое я придумал, - создать новый класс, производный от TextView. Класс должен переопределить три метода onFocusChanged , onWindowFocusChanged и isFocused, чтобы сфокусировать весь TextView.
@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; }
источник
Сегодня я наконец столкнулся с этой проблемой, и поэтому загорелся
hierarchyviewer
приложением Android Market.Глядя на заголовок на подробном экране приложения, они используют старый добрый
TextView
. Изучение его свойств показало, что он не сфокусирован, не может быть сфокусирован и в целом был очень обычным - за исключением того факта, что он был отмечен как выбранный .Одна строчка кода позже, и у меня все заработало :)
textView.setSelected(true);
Это имеет смысл, учитывая то, что говорит Javadoc :
т.е. когда вы прокручиваете элемент в виде списка (например, в приложении "Маркет"), только после этого начинает прокручиваться выбранный текст. И поскольку этот конкретный
TextView
объект не может быть выбран для фокусировки или кликабельна, он никогда не потеряет свое состояние выбора.К сожалению, насколько мне известно, невозможно предварительно установить выбранное состояние из XML макета.
Но однострочный вышеупомянутый мне подходит.
источник
TextView
(то есть не встроенном во что-то «выбираемое» вроде aListView
) изменило бы выбранное состояние.TextView
документацию и посмотритеandroid:marqueeRepeatLimit
.Просто поместите эти параметры в свой TextView. Оно работает :)
android:singleLine="true" android:ellipsize="marquee" android:marqueeRepeatLimit ="marquee_forever" android:scrollHorizontally="true" android:focusable="true" android:focusableInTouchMode="true"
источник
TranslateAnimation
работает, «подтягивая» вид в одном направлении на указанную величину. Вы можете указать, где начинать это «вытягивание», а где заканчивать.TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta);
fromXDelta задает смещение начальной позиции движения по оси 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 определяет конечную позицию смещения движения по оси 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.
Если ширина вашего текста больше, чем модуль разницы между fromXDelta и toXDelta, текст не сможет полностью перемещаться по экрану.
пример
Предположим, у нас размер экрана 320x240 пикселей. У нас есть TextView с текстом шириной 700 пикселей, и мы хотим создать анимацию, которая «вытягивает» текст, чтобы мы могли видеть конец фразы.
(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... || ---------------------------+| | | | | | | +---------------------------+
Сначала мы устанавливаем
fromXDelta = 0
так, чтобы движение не имело начального смещения. Теперь нам нужно вычислить значение toXDelta. Чтобы добиться желаемого эффекта, нам нужно «вытянуть» текст на столько же пикселей, сколько он занимает за пределы экрана. (на схеме обозначено <<<< X px >>>>) Поскольку наш текст имеет ширину 700, а видимая область - 320 пикселей (ширина экрана), мы устанавливаем:tXDelta = 700 - 320 = 380
А как нам определить ширину экрана и ширину текста?
Код
Взяв фрагмент Зара в качестве отправной точки:
/** * @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; }
Могут быть более простые способы сделать это, но это работает для всех представлений, которые вы можете придумать, и его можно использовать повторно. Это особенно полезно, если вы хотите анимировать TextView в ListView, не нарушая возможности enabled / onFocus для textView. Он также непрерывно прокручивается, даже если вид не сфокусирован.
источник
textView.setSelected(true);
не работает в вашей ситуации?Не знаю, нужен ли вам ответ, но я нашел простой способ сделать это.
Настройте свою анимацию так:
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
ИEND_POS_Y
являютсяfloat
ценности, в то время какTICKER_DURATION
этоint
я заявил с моими другими константами.Затем вы можете применить эту анимацию к своему TextView:
Вот и все. :)
Моя анимация начинается с правой стороны вне экрана (300f) и заканчивается с левой стороны вне экрана (-300f) с продолжительностью 15 секунд (15000).
источник
Я написал следующий код для ListView с выделенными текстовыми элементами. Он основан на решении setSelected, описанном выше. По сути, я расширяю класс ArrayAdapter и переопределяю метод getView, чтобы выбрать TextView перед его возвратом:
// 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; } }
источник
Это ответ, который появляется в верхней части моего поиска в Google, поэтому я подумал, что могу опубликовать здесь полезный ответ, поскольку мне трудно вспомнить это довольно часто. В любом случае это работает для меня и требует атрибутов XML и 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" />
// В Java
mtvMarque.setEllipsize(TextUtils.TruncateAt.MARQUEE); mtvMarque.setSelected(true); mtvMarque.setSingleLine(true);
источник