View.layout() works until next UI update

2019-06-02 12:32发布

My launching activity consists of Linear layout with two buttons. Both buttons have listeners: the first one (b) moves itself upon click: 30px to the left and 30px back upon the next click. The second one (b2) changes its text upon click. Here is the code:

public class TestActivity extends Activity {
public final String TAG="TestActivity";
boolean toTop=true;
boolean setInitialText=false;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main); 
    Button b=(Button)findViewById(R.id.button);
    Button b2=(Button)findViewById(R.id.button2);
    b.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            int modifier;
            if(toTop) modifier=-30; 
            else modifier=30;
            v.layout(v.getLeft()+modifier,v.getTop(),v.getRight()+modifier,v.getBottom());
            toTop=!toTop;
        }
    });

    b2.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            String currentText;
            if(setInitialText)currentText="Press to change text";
            else currentText="Press to change back";
            ((Button)v).setText(currentText);
            setInitialText=!setInitialText;
        }
    });
}
}

XML layout-file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Press to begin animation" />

<Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Press to change text" />

My problem: when b is moved to the left and I press b2, b moves to its initial position. Why? I don't want it to move back and didn't specify it anywhere.

It looks like View.layout looses its effect. Why it happens? I tested that in other situations and it seems that any UI update makes all invoked View.layout methods loose their effect.

In my main project there is a ListView which is populated with images from background - all view moves loose effect when new image appears. Besides, if I add EditText and try to enter something (as user), view moves loose their effect as well. Can anyone explain to me what's going on and why do views move back?

2条回答
Rolldiameter
2楼-- · 2019-06-02 13:20

Looks like parent layout repositions it's siblings after you set a new text for the button2, because as describe in xml, button2 wraps it's content by width and height.

As you changed button's content, it requests it's parent layout to get a new position for it. In this case parent layout will recalculate position values for all of it's siblings. That's why button1 also comes back to it's previous position.

Keep in mind, that you also set the gravity value for parent layout as center, that means that when layout will position it's siblings it will position them in it's center.

Try to experiment with some ohter layout classes like FrameLayout, which has absolute manner of positioning it's siblings and RelativeLayout which and also try your case getting rid of layout's gravity.

查看更多
Emotional °昔
3楼-- · 2019-06-02 13:22

Here says that this issue may be solved, using view.setLayoutParams() instead of view.layout()

查看更多
登录 后发表回答