AutoLayout进阶——适配旋转,分屏,分屏后大小调整。

本文基于上一篇文章《AutoLayout适配问题解决方案》

前言:

没事看看APP适配,然后发现绝大部分APP都屏蔽了旋转功能。但是,在分屏情况下,屏蔽旋转功能的属性是失效的,开启了分屏之后的旋转,直接导致了某些VIew拉伸,变形甚至移除屏幕找不到了。
正常情况下APP不能旋转,或者适配旋转时,会适配多个布局文件。在能分屏的情况下,以不能旋转的APP:M为例,在分屏并横屏时一半按钮被挡住了。AutoLayout适配差不多能解决这种问题。
AutoLayout进阶——适配旋转,分屏,分屏后大小调整。_第1张图片
AutoLayout进阶——适配旋转,分屏,分屏后大小调整。_第2张图片

一、适用条件

AutoLayout核心思路和逻辑在前一篇文章。AutoLayout适配的屏幕变化,会随着屏幕宽度的变化发生大小改变,用autolayout做纯旋转适配难度很大,而且多布局能很好解决这个问题。分屏旋转屏幕时的屏幕宽度变化不大,因此解决分屏旋转问题正适合。主要应用对象是老板要分屏功能,但是又没有旋转适配或者旋转适配比较麻烦的APP。

二、使用情况

1:使用了分屏功能,如果分屏后activity销毁重建。

如果activity销毁重建,那么用了AutoLayout布局,什么都不需要做就能很好适配。这种情况与不同大小的屏幕尺寸一个道理。

2:使用了分屏功能,绝大部分情况下都是需要保证分屏后activity不能销毁重建。

Activity需要设置属性
android:configChanges="screenLayout|orientation|screenSize|smallestScreenSize"

需要重写屏幕变化方法

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        updateLayoutparams(newConfig);
    }

    @Override
    public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) {
        super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig);
        updateLayoutparams(newConfig);
    }
    
    private void updateLayoutparams(Configuration newConfig) {
        //重新计算尺寸
        int wid = DisplayUtil.dp2px(this, newConfig.screenWidthDp);
        int hei = DisplayUtil.dp2px(this, newConfig.screenHeightDp);
        AutoLayoutConifg.getInstance().initScreen(wid,
                hei,
                DisplayUtil.getMetaDataWid(this),
                DisplayUtil.getMetaDataHei(this));
    }

调用updateLayoutparams方法,将屏幕参数传入,用以改变设计图尺寸。改变屏幕设计图尺寸,进而通过屏幕宽高和设计图的比例适配屏幕是AutoLayout的核心思想。
加入在代码中生成了View或者设置了Layoutparams,那么由于activity没有销毁重建,在屏幕旋转后大小并没有计算,需要保存代码中生成或者修改属性的VIew,并在屏幕变化时重新调用。

private List codeViewList;
private TextView changeViewAttr;


@Override
    protected void onCreate(Bundle savedInstanceState) {
    ………………
    codeViewList = new ArrayList<>();
    codeAddView = new TextView(this);
    updateSingleViewLayoutparams(codeAddView);
    codeViewList.add(codeAddView);
    ………………
    }
      
private void updateLayoutparams(Configuration newConfig) {
        //重新计算尺寸
        int wid = DisplayUtil.dp2px(this, newConfig.screenWidthDp);
        int hei = DisplayUtil.dp2px(this, newConfig.screenHeightDp);
        AutoLayoutConifg.getInstance().initScreen(wid,
                hei,
                DisplayUtil.getMetaDataWid(this),
                DisplayUtil.getMetaDataHei(this));

        //代码中生成view或者改变view的params,需要重新设置layoutparams
        for (View view : codeViewList) {
            updateSingleViewLayoutparams(view);
        }
    }

    private void updateSingleViewLayoutparams(View view) {
        if (view.equals(changeViewAttr)) {
            //此处需要注意,原本是谁的layoutparams就用谁的,如果用了ViewGroup的可能会出现属性丢失
            AutoLinearLayout.LayoutParams layoutParams = new AutoLinearLayout.LayoutParams(
                    (AutoLinearLayout.LayoutParams) changeViewAttr.getLayoutParams());
            layoutParams.width = (int) (600 * DisplayUtil.getRateWid());
            changeViewAttr.setLayoutParams(layoutParams);
        } else if (view.equals(codeAddView)) {
            AutoLinearLayout.LayoutParams layoutParams = new AutoLinearLayout.LayoutParams((int) (540 * DisplayUtil.getRateWid()),
                    (int) (540 * DisplayUtil.getRateHei()));
            layoutParams.leftMargin = (int) (270 * DisplayUtil.getRateWid());
            layoutParams.bottomMargin = (int) (270 * DisplayUtil.getRateHei());
            layoutParams.topMargin = (int) (270 * DisplayUtil.getRateHei());
            codeAddView.setLayoutParams(layoutParams);
            //代码中设置文字,需要转换
            codeAddView.setTextSize(DisplayUtil.px2sp(this, 50 * DisplayUtil.getRateWid()));
        } else if (view.equals(changeSelfViewAttr)) {
            AutoLinearLayout.LayoutParams layoutParams = new AutoLinearLayout.LayoutParams(
                    (AutoLinearLayout.LayoutParams) changeSelfViewAttr.getLayoutParams());
            //自定义view的改变大小不需要乘比例
            layoutParams.width = 600;
            layoutParams.height = 600;
            changeSelfViewAttr.setLayoutParams(layoutParams);
        }
    }

3:如果不想用多布局,又想用适配旋转的情况。

如果你老板和客户可以忍受图片文字放大的情况,那么这种情况就不存在。
在这个设置设计图和屏幕尺寸的方法中,可以将屏幕大小适当缩小,比如将屏幕宽高设置为原来的三分之二。这种方法就退化为与普通dp差异不大的适配方案。
同时这种方案问题也有很多需要UI配合,比如View之间的间距是不定的,需要过渡元素更长;正常情况下,设计图1080宽度,xml文件写1080px与mathparent意义相同,但此处也不适用。总之此种情况仅适用于临时顶替一下。

        int wid = DisplayUtil.dp2px(this, newConfig.screenWidthDp);
        int hei = DisplayUtil.dp2px(this, newConfig.screenHeightDp);
        AutoLayoutConifg.getInstance().initScreen(wid,
                hei,
                DisplayUtil.getMetaDataWid(this),
                DisplayUtil.getMetaDataHei(this));

三、总结

对于屏幕尺寸变化适配情况。
一,不允许旋转,不允许分屏,那么完全就考虑一种布局。
二,允许旋转,不允许分屏,那么多布局是最好的选择。
三,不允许旋转,允许分屏,那么Autolayout的适配方案适合你。
四,允许旋转,允许分屏,那么有结合具体页面,用多布局和Autolayout适配也能很好解决这个问题。

Demo下载:AutolayoutDemo
本文地址: https://blog.csdn.net/qq_39154578/article/details/84778547
原GitHub:https://github.com/hongyangAndroid/AndroidAutoLayout
更新后地址:https://github.com/kukugtu/autolayout
原创作品,转载请注明 Author:Kukugtu。

你可能感兴趣的:(Android,屏幕旋转,分屏,布局)