TextView перезапускает Marquee при изменении другого TextView в том же LinearLayout

У меня есть LinearLayout и внутри 2 TextView оба имеют шатер, и когда я обновляю текст сначала, а затем второй TextView перезапускает шатер.

            <LinearLayout
                android:id="@+id/panel"
                android:layout_width="320dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="2dp"
                android:layout_marginRight="2dp"
                android:gravity="center_vertical"
                android:orientation="vertical" >

                <TextView
                    android:id="@+id/first"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:ellipsize="marquee"
                    android:gravity="bottom|center_horizontal"
                    android:marqueeRepeatLimit="marquee_forever"
                    android:singleLine="true" />

                <TextView
                    android:id="@+id/second"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:ellipsize="marquee"
                    android:gravity="top|center_horizontal"
                    android:marqueeRepeatLimit="marquee_forever"
                    android:singleLine="true"
                      />
            </LinearLayout>

Я обнаружил, что если для R.id.first и R.id.second установить layout_width="320dp", эффекта не произойдет. Но я хочу установить android:layout_width="match_parent" есть обходной путь?

Я нашел аналогичную проблему, но без решения: Android, перезапуск RelativeLayout Marquee-TextView при изменении ImageView в том же RelativeLayout


person LunaVulpo    schedule 08.08.2012    source источник


Ответы (3)


У меня была аналогичная проблема, и решение заключается в том, чтобы установить фиксированный размер для Textview.

Так почему бы не сделать это программно? В моем случае это решило проблему. Вот мое решение в деталях:

Макет немного сложный с большим количеством изменяющихся значений. Вот интересная часть:

макет.xml:

<!-- The height and visibility values change programatically -->
<RelativeLayout 
    android:layout_width="fill_parent"
    android:layout_height="30dp" 
    android:layout_alignParentBottom="true"
    android:visibility="gone" >

    <FrameLayout>
        ...
        // some code
        ...
    </FrameLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="fill_parent" />

        <!-- My scrolling textview. see below. -->
        <!-- The size will be set when -->
        <!-- the layout will be draw, -->
        <!-- after the Activity.onCreate(). -->
        <!-- I removed ALL THE UNECESSARY (I mean  -->
        <!-- scrollHorizontally, focusable and focusableInTouchMode. -->
        <!-- You don't need it !!!!) -->
        <fr.cmoatoto.android.widget.ScrollingTextView 
            android:id="@+id/text"
            android:layout_width="0dp"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:marqueeRepeatLimit="marquee_forever" />

        <ImageView
            ...
            // some code
            ... />
    </LinearLayout>
</RelativeLayout>

ScrollingTextView был определен в этом ответе.

Вот оно снова:

ПрокруткаTextView.java:

public class ScrollingTextView extends TextView {

    public ScrollingTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public ScrollingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollingTextView(Context context) {
        super(context);
    }

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

И, наконец, Активность. Как я уже говорил, вам нужно установить фиксированную ширину и высоту, поэтому мы сделаем это программно с прослушивателем в onCreate() :

Моя активность.java:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.layout);


    TextView textView = ((TextView) findViewById(R.id.home_trafic_text));
    textView.setText(getString(R.string.loading));
    textView.setEnabled(true); // Thanks to Romain Guy
    textView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
        @Override
        public void onLayoutChange(View v, int left, int top, int right,
                int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
            LayoutParams params = v.getLayoutParams();
            params.width = right - left;
            params.height = bottom - top;
            params.weight = 0;
            v.removeOnLayoutChangeListener(this);
            v.setLayoutParams(params);
        }
    });
}

Будьте осторожны, если вам нужно изменить ориентацию или что-то в этом роде, но у меня это работает очень хорошо!

----РЕДАКТИРОВАНИЕ ДЛЯ PRE-API-11---

Поскольку OnLayoutChangeListener существует только из Api v11, есть обходной путь (он работает, но я думаю, что он менее хорош):

Удалите OnLayoutChangeListener из своей деятельности:

Моя активность.java:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.layout);

    TextView textView = ((TextView) findViewById(R.id.home_trafic_text));
    textView.setText(getString(R.string.loading));
    textView.setEnabled(true); // Thanks to Romain Guy
}

и добавьте onSizeChanged в свой ScrollingTextView :

ПрокруткаTextView.java:

public class ScrollingTextView extends TextView {

    ...
    // Same code as before
    ...

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    LayoutParams params = (LayoutParams) getLayoutParams();
        params.width = w;
        params.height = h;
        params.weight = 0;
        setLayoutParams(params);
    }
}

Я надеюсь, что это помогает !

person CmoaToto    schedule 12.12.2012
comment
Я потерял свое утро и нашел это. Идеально! - person leegor; 20.03.2020

Вы должны запретить помещать обе бегущие строки в одну и ту же ViewGroup. В вашем случае вы можете обернуть каждое выделение TextView с помощью LinearLayout (это не сработает при использовании RelativeLayout).

person Patrick Chan    schedule 05.02.2014
comment
Лучший ответ. Самый простой и логичный способ решения проблемы. Это должен быть принятый ответ. - person Hamza Khurshid; 16.05.2020
comment
Это полностью работает. Я просто вставил TextView в LinearLayout. - person Mateus Pires; 07.08.2020

простое исправление .. :) не нужно сильно беспокоиться ... просто исправьте ширину textview как 800dp или слишком большую ширину. это решит проблему сброса

person user2114068    schedule 25.02.2016
comment
Вы спасли мою жизнь. Просто установите ширину TextView с определенным числом dp вместо использования wrap_content. - person duybinh0208; 21.12.2019