Search code examples
androidandroid-linearlayoutmarquee

TextView restarts Marquee when changing another TextView in same LinearLayout


I have LinearLayout and inside 2 TextView both have marquee and when I update text in first then second TextView restarts marquee.

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

I found that if for R.id.first and R.id.second i set layout_width="320dp" the effect don't occurs. But I want to set android:layout_width="match_parent" there is some workaround?

I found similar problem but without solution: Android, RelativeLayout restarts Marquee-TextView when changing ImageView in same RelativeLayout


Solution

  • I had a similar problem and the solution IS to set fixed size for the Textview.

    So why not do it progammatically? In my case, it solved the problem. Here is my solution in details :

    The layout is a bit complex with a lot of changing values. Here is the interesting part :

    layout.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>
    

    The ScrollingTextView has been defined in this answer

    Here it is again :

    ScrollingTextView.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;
        }
    }
    

    And finally the Activity. As I said before, You need to set fixed width and height so we will do it programmatically with a listener in the onCreate() :

    MyActivity.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);
            }
        });
    }
    

    Be careful if you need to change orientation or things like that but it works pretty well for me !

    ----EDIT FOR PRE-API-11---

    Because OnLayoutChangeListener exists only from Api v11, there is a workaround (It works but I think it is less good) :

    Remove the OnLayoutChangeListener from your activity :

    MyActivity.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
    }
    

    and add a onSizeChanged in your ScrollingTextView :

    ScrollingTextView.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);
        }
    }
    

    I hope it helps !