Есть ли способ сделать эллипсис = "шатер" всегда прокручивать?

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

Я использую:

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

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

Ответ 1

Я столкнулся с проблемой, и самое короткое решение, которое я придумал, - создать новый класс, полученный из 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;
}

Ответ 2

Наконец-то я столкнулся с этой проблемой и так активировал hierarchyviewer в приложении Android Market.

Посмотрев заголовок на экране подробных сведений о приложении, они используют простой старый TextView. Изучение его свойств показало, что оно не фокусировалось, не могло быть сфокусировано и, как правило, было очень обычным делом; за исключением того, что он был отмечен как выбранный.

Одна строка кода позже, и я работал над ней:)

textView.setSelected(true);

Это имеет смысл, учитывая, что Javadoc говорит:

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

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

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

Ответ 3

Просто поместите эти параметры в свой TextView. Он работает:)

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

Ответ 4

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.

Если ширина вашего текста больше, чем модуль разности между XDelta и 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. Для достижения желаемого эффекта нам нужно "вытащить" текст тех же самых px, что и он, из экрана. (в схеме представлено < < X px px → → ) Поскольку наш текст имеет ширину 700, а видимая область - 320 пикселей (ширина экрана), мы устанавливаем:

tXDelta = 700 - 320 = 380

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


код

Взятие 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;
}

Там могут быть более простые способы выполнения этого, но это работает для каждого вида, о котором вы можете думать и которое можно использовать повторно. Это особенно полезно, если вы хотите анимировать TextView в ListView, не нарушая возможности enabled/onFocus для textView. Он также непрерывно прокручивается, даже если представление не сфокусировано.

Ответ 5

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

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

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);

И что это.:)

Моя анимация начинается с правой стороны за пределами экрана (300f) и заканчивается на левой стороне за пределами экрана (-300f) с длительностью 15 с (15000).

Ответ 6

Я написал следующий код для ListView с элементами текста marquee. Он основан на решении 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;

        }
    }

Ответ 7

Это ответ, который появляется в верхней части моего поиска в Google, поэтому я подумал, что могу опубликовать полезный ответ здесь, так как я борюсь с запоминанием этого довольно часто. Во всяком случае, это работает для меня и требует атрибутов XML и A 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);
            }
        }
    });

Ответ 8

//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);