Есть ли способ заставить ellipsize =“marquee” всегда прокручиваться?

StackOverflow https://stackoverflow.com/questions/1827751

  •  11-09-2019
  •  | 
  •  

Вопрос

Я хочу использовать эффект выделения в TextView, но текст прокручивается только тогда, когда TextView получает фокус.Это проблема, потому что в моем случае это невозможно.

Я использую:

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

Есть ли способ заставить TextView всегда прокручивать свой текст?Я видел, как это делается в приложении Android Market, где название приложения будет прокручиваться в строке заголовка, даже если оно не получает фокуса, но я не смог найти упоминания об этом в документах API.

Это было полезно?

Решение

Я столкнулся с проблемой, и самое короткое решение, которое я придумал, - это создать новый класс, производный от TextView.Класс должен переопределять три метода Onfocus Изменен, В окне изменен фокус и Сфокусирован чтобы сделать 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 говорит:

Вид может быть выбран или нет.Обратите внимание, что выделение - это не то же самое, что фокусировка.Представления обычно выбираются в контексте AdapterView, такого как ListView или GridView.

т. е.Когда вы прокручиваете элемент в виде списка (например, в приложении Market), только тогда теперь-выбран текст начинает прокручиваться.И поскольку этот конкретный TextView не является фокусируемым или кликабельным, он никогда не потеряет свое состояние выбора.

К сожалению, насколько я знаю, нет способа предварительно установить выбранное состояние из XML-макета.
Но однострочник, приведенный выше, отлично подходит для меня.

Просто поместите эти параметры в свой 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

И как нам определить ширину экрана и ширину текста?


Код

Взяв фрагмент Zarah за отправную точку:

    /**
     * @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, не нарушая возможности включения / фокусировки TextView.Он также непрерывно прокручивается, даже если вид не сфокусирован.

Я не знаю, нужен ли вам все еще ответ, но я нашел простой способ сделать это.

Настройте свою анимацию следующим образом:

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:

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

И это все.:)

Моя анимация начинается с правой стороны за кадром (300 кадров в секунду) и заканчивается с левой стороны за кадром (-300 кадров в секунду) продолжительностью 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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top