背景:app中在横竖屏切换的时候需要对布局做一些调整,但是xml布局文件中布局已经写死(其实也可以用两套布局layout来实现,但这里不讨论这种方法),所以需要结合onConfigurationChange方法在代码中对布局的属性参数做一些修改,对于如何做的修改写此文作为记录

总述:修改布局主要有下面三步

1.通过控件对象获取对应的布局参数对象

2.用参数对象设置需要的属性调整布局

3.将此参数对象设置回原先的控件对象

下面举例分步解释:

先贴示例布局

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <TextView
        android:id="@+id/xxx1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/xxx2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/xxx3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</RelativeLayout>

我们使用上面布局中xxx1和xxx2控件来作为例子讲解,在activity中获取这两个控件对象

private TextView textView1,textView2;
textView1 = (TextView) findViewById(R.id.xxx1);
textView2 = (TextView) findViewById(R.id.xxx2);

onConfigurationChanged方法中做具体布局修改的操作

1.通过控件对象获取对应的布局参数对象:一般是new出来LinearLyout.LayoutParams、ReletiveLayout.LyoutParam两种其中一种并且将需要设置的控件的LayoutParam作为参数传入,是用LinearLyout.LayoutParams还是ReletiveLayout.LyoutParam由你需要设置的控件的父控件决定,注意是其父控件决定,所以如果需要获取textView1和textView2的布局参数对象的话通过布局可以看出textView1是LinearLyout.LayoutParams,而textView2是ReletiveLayout.LyoutParam,故获取代码如下:

LinearLayout.LayoutParams paramTextView1 = new LinearLayout.LayoutParams(textView1.getLayoutParams());
RelativeLayout.LayoutParams paramTextView2 = new RelativeLayout.LayoutParams(textView2.getLayoutParams());

这样,通过上面的两行代码即可获取到布局参数对象paramTextView1和paramTextView2,还有另外一种写法直接通过控件获取到布局参数对象后直接强转,如下:

LinearLayout.LayoutParams paramTextView1 = (LinearLayout.LayoutParams) textView1.getLayoutParams();
RelativeLayout.LayoutParams paramTextView2 = (RelativeLayout.LayoutParams) textView2.getLayoutParams();

上面这两种方式应该都可以。

2.用参数对象设置需要的属性调整布局:1中已经获取到布局参数对象,下面通过此对象设置需要的属性

    最基本的控件宽高设置,有三种设置的值1.充满父控件2.自适应内容3.直接设置具体值(注意这里设置的值均为px单位)    

paramTextView1.width = LinearLayout.LayoutParams.MATCH_PARENT;//充满父控件
paramTextView1.width = LinearLayout.LayoutParams.WRAP_CONTENT;//自适应内容
paramTextView1.width = DisplayUtils.dp2px(this, 10);//直接设置具体值

其他的设置的参数下面源码给出,其中DispalyUtils是一个工具类其中的静态方法dp2px负责把dp值转化为px值,下面源码也会给出

3.最后将此参数对象设置回原先的控件对象使布局修改生效:

textView1.setLayoutParams(paramTextView1);


部分代码源码

public class DisplayUtils {

    public static Point getScreenResolution(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point screenResolution = new Point();
        if (android.os.Build.VERSION.SDK_INT >= 13) {
            display.getSize(screenResolution);
        } else {
            screenResolution.set(display.getWidth(), display.getHeight());
        }
        return screenResolution;
    }

    public static int dp2px(Context context, float dpValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
    }
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    int config = newConfig.orientation;
    if(config == Configuration.ORIENTATION_PORTRAIT) {
        //textView1-----------------------------------------------------------------------------
        //获取布局参数对象
        LinearLayout.LayoutParams paramTextView1 = new LinearLayout.LayoutParams(textView1.getLayoutParams());
        
        //通过布局参数对象修改控件参数
        //修改控件宽
        paramTextView1.width = LinearLayout.LayoutParams.MATCH_PARENT;//充满父控件
        paramTextView1.width = LinearLayout.LayoutParams.WRAP_CONTENT;//自适应内容
        paramTextView1.width = DisplayUtils.dp2px(this, 10);//直接设置具体值
        //修改控件高
        paramTextView1.height = LinearLayout.LayoutParams.MATCH_PARENT;//充满父控件
        paramTextView1.height = LinearLayout.LayoutParams.WRAP_CONTENT;//自适应内容
        paramTextView1.height = DisplayUtils.dp2px(this, 10);//直接设置具体值
        //修改控件gravity
        paramTextView1.gravity = Gravity.CENTER;//居中
        paramTextView1.gravity = Gravity.CENTER_HORIZONTAL;//水平居中
        paramTextView1.gravity = Gravity.CENTER_VERTICAL;//垂直居中
        paramTextView1.gravity = Gravity.NO_GRAVITY;//不设置gravity属性
        //一次性设置左,上,右,下四个方位的margin均为10dp
        paramTextView1.setMargins(DisplayUtils.dp2px(this, 10), DisplayUtils.dp2px(this, 10), DisplayUtils.dp2px(this, 10), DisplayUtils.dp2px(this, 10));
        //设置左margin为10dp
        paramTextView1.leftMargin = DisplayUtils.dp2px(this, 10);
        //设置左margin为10dp
        paramTextView1.rightMargin = DisplayUtils.dp2px(this, 10);
        //设置左margin为10dp
        paramTextView1.topMargin = DisplayUtils.dp2px(this, 10);
        //设置左margin为10dp
        paramTextView1.bottomMargin = DisplayUtils.dp2px(this, 10);

        //将布局参数对象设置到控件对象中
        textView1.setLayoutParams(paramTextView1);


        //textView2-----------------------------------------------------------------------------
        //获取布局参数对象
        RelativeLayout.LayoutParams paramTextView2 = new RelativeLayout.LayoutParams(textView2.getLayoutParams());

        //通过布局参数对象修改控件参数
        //修改控件宽
        paramTextView1.width = RelativeLayout.LayoutParams.MATCH_PARENT;
        paramTextView1.width = RelativeLayout.LayoutParams.WRAP_CONTENT;
        paramTextView1.width = DisplayUtils.dp2px(this, 10);
        //修改控件高
        paramTextView1.height = RelativeLayout.LayoutParams.MATCH_PARENT;
        paramTextView1.height = RelativeLayout.LayoutParams.WRAP_CONTENT;
        paramTextView1.height = DisplayUtils.dp2px(this, 10);
        //修改控件位置为水平居中
        paramTextView2.addRule(RelativeLayout.CENTER_HORIZONTAL);
        //修改控件位置为id为xxx3的控件上方
        paramTextView2.addRule(RelativeLayout.ABOVE, R.id.xxx3);

        //将布局参数对象设置到控件对象中
        textView2.setLayoutParams(paramTextView2);
    }else if(config == Configuration.ORIENTATION_LANDSCAPE){
        // TODO: 18/2/22  
    }
}