JessYanCoding / AndroidAutoSize

🔥 A low-cost Android screen adaptation solution (今日头条屏幕适配方案终极版,一个极低成本的 Android 屏幕适配方案).
Apache License 2.0
13.47k stars 1.96k forks source link

横竖屏切换 布局异常~问题所在及解决方案 (升级版) #418

Closed Fly-Felix closed 2 years ago

Fly-Felix commented 2 years ago

当刚开始在使用这个适配方案时,运行起来看起来非常好,基本上不用修改什么就能达到适配效果,但在一次app前台后台横屏竖屏切换操作后,布局和文字会变的特别大或特别小,显然是有问题的,得治

在发生问题之后我先是百度一下,解决了,运行时横竖屏幕方向不一致时适配问题,再来在官方这里寻找旋转后适配失效问题,幸运的是我找到了:#388 ,根据大佬的描述意思就是 ScreenUtils.getScreenSize()这个方法在旋转屏幕抓取到的size还旋转之前的size,加了500ms延迟之后获取size就正常了,使用了大佬提供的解决方案之后好多了,不过有时还是会出现问题,于是开始调试发现大佬的代码好像有一点点小问题,以下是问题代码:

`

                //获取当前屏幕的宽高
                int[] screenSize = ScreenUtils.getScreenSize(sAppContext);

                if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                    //竖屏
                    AutoSizeConfig.getInstance().setScreenWidth(screenSize[0]);
                    AutoSizeConfig.getInstance().setScreenHeight(screenSize[1]);

                } else {
                    //横屏下需要 转换 宽高的值
                    AutoSizeConfig.getInstance().setScreenWidth(screenSize[1]);
                    AutoSizeConfig.getInstance().setScreenHeight(screenSize[0]);

                }

` 在延迟获取之后既然screenSize都正常了为什么还要给setScreenWidth和setScreenHeight取反操作,screenSize[0]代表宽度screenSize[1]代表高度,在screenSize正常时: 横屏:screenSize[0]=1024,screenSize[1]=600 竖屏:screenSize[0]=600,screenSize[1]=1024

所以在加了500ms延迟获取screenSize之后完全不需要故意取反设置宽度和高度,在按照自己的想法修改一番之后最后的问题也解决了

经虚拟机和真机横竖屏旋转和切换第三方来回测试均无发现适配失效问题,最后我给出以下代码:

`

class App : Application() {

private var mHandler = Handler(Looper.getMainLooper())

private var mCurrentActivity: Activity? = null

private var mAutoSizeRunnable: Runnable? = null

override fun onCreate() {
    super.onCreate()

    //屏幕适配监听器
    AutoSizeConfig.getInstance().setOnAdaptListener(object : onAdaptListener {

        override fun onAdaptBefore(target: Any?, activity: Activity?) {
            if (activity == null) {
                return
            }

            //使用以下代码, 可以解决横竖屏切换时的屏幕适配问题
            //首先设置最新的屏幕尺寸,ScreenUtils.getScreenSize(activity) 的参数一定要不要传 Application !!!
            AutoSizeConfig.getInstance().screenWidth =
                ScreenUtils.getScreenSize(activity)[0];
            AutoSizeConfig.getInstance().screenHeight =
                ScreenUtils.getScreenSize(activity)[1];
            //根据屏幕方向,设置设计尺寸
            if (activity.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                //设置横屏设计尺寸
                AutoSizeConfig.getInstance()
                    .setDesignWidthInDp(1024)
                    .setDesignHeightInDp(600);
            } else {
                //设置竖屏设计尺寸
                AutoSizeConfig.getInstance()
                    .setDesignWidthInDp(600)
                    .setDesignHeightInDp(1024)

            }
        }

        override fun onAdaptAfter(target: Any?, activity: Activity?) {
        }
    });

    registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            mCurrentActivity = activity
        }

        override fun onActivityStarted(activity: Activity) {
            mCurrentActivity = activity
        }

        override fun onActivityResumed(activity: Activity) {
            mCurrentActivity = activity
        }

        override fun onActivityPaused(activity: Activity) {
            mCurrentActivity = activity
        }

        override fun onActivityStopped(activity: Activity) {
            mCurrentActivity = activity
        }

        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
            mCurrentActivity = activity
        }

        override fun onActivityDestroyed(activity: Activity) {
            mCurrentActivity = null
        }
    })

    registerComponentCallbacks(object : ComponentCallbacks {
        override fun onConfigurationChanged(newConfig: Configuration) {
            if (mCurrentActivity == null) {
                return
            }
            if (mAutoSizeRunnable != null) {
                mHandler.removeCallbacks(mAutoSizeRunnable!!)
            }
            mAutoSizeRunnable = Runnable {
                //获取当前屏幕的宽高
                val screenSize = ScreenUtils.getScreenSize(mCurrentActivity);
                //横屏
                AutoSizeConfig.getInstance().screenWidth = screenSize[0]
                AutoSizeConfig.getInstance().screenHeight = screenSize[1]

                if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    //设置横屏设计尺寸
                    AutoSizeConfig.getInstance()
                        .setDesignWidthInDp(1024)
                        .setDesignHeightInDp(600)
                } else {
                    //设置竖屏设计尺寸
                    AutoSizeConfig.getInstance()
                        .setDesignWidthInDp(600)
                        .setDesignHeightInDp(1024)
                }
                //重新设置 dpi
                if (mCurrentActivity != null) {
                    AutoSize.autoConvertDensityOfGlobal(mCurrentActivity)
                }
            }
            mHandler.postDelayed(mAutoSizeRunnable!!, 500)
        }

        override fun onLowMemory() {

        }
    })
}
}

`

GHMike commented 2 years ago

鸿蒙系统的好像还是有问题

Fly-Felix commented 2 years ago

目前我还没在鸿蒙系统上尝试过,你可以详细的说一下你遇到的问题吗?我可以按照你说的去试试

Fly-Felix commented 2 years ago

鸿蒙系统的好像还是有问题

我刚刚用HUAWEI Mate 30 鸿蒙2.0.0.236版本切换横屏竖屏旋转测试没有发生问题

Fly-Felix commented 2 years ago

AndroidManifest.xml配置如下,你可以按照你的尺寸配置,再加上我上面给的Application代码,其它地方不要再多写什么,应该没什么问题,Application里面的代码一点都不能少,获取activity的方式可以修改,其它代码最好不要修改 <meta-data android:name="design_width_in_dp" android:value="1024" /> <meta-data android:name="design_height_in_dp" android:value="600" />

GHMike commented 2 years ago

我的横竖屏切换是竖屏页面进入横屏页面,横屏页面有很多个列表,然后来回进入退出横屏页面,横屏页面就会变形

Fly-Felix commented 2 years ago

这个问题就是在GitHub提到的最后一个问题,之前我在安卓系统上也遇到了,我后来修改之后解决了,Github给的就是修改过后的代码,如果你还是有这个问题,那你试试把500ms改成1000ms试试

---原始邮件--- 发件人: @.> 发送时间: 2022年8月5日(周五) 下午5:42 收件人: @.>; 抄送: @.>;"State @.>; 主题: Re: [JessYanCoding/AndroidAutoSize] 横竖屏切换 布局异常~问题所在及解决方案 (升级版) (Issue #418)

我的横竖屏切换是竖屏页面进入横屏页面,横屏页面有很多个列表,然后来回进入退出横屏页面,横屏页面就会变形

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you modified the open/close state.Message ID: @.***>

ysj40540 commented 1 year ago

我也遇到一个列表页面变形 适配失败, 步骤是华为小米部分手机息屏 然后页面Onresume刷新列表就变形了,你怎么解决的呢

wuyihao99 commented 1 year ago

我这里使用直接崩溃了,从activity返回的时候先执行的onActivityResumed,然后才是onActivityDestroyed,这样ScreenUtils.getScreenSize(mCurrentActivity)就是null的

Fly-Felix commented 1 year ago

我这里使用直接崩溃了,从activity返回的时候先执行的onActivityResumed,然后才是onActivityDestroyed,这样ScreenUtils.getScreenSize(mCurrentActivity)就是null的

在Runnable的地方增加一个空指针判断 mAutoSizeRunnable = Runnable { if (mCurrentActivity != null) { //...... } }

wuyihao99 commented 1 year ago

我这里使用直接崩溃了,从activity返回的时候先执行的onActivityResumed,然后才是onActivityDestroyed,这样ScreenUtils.getScreenSize(mCurrentActivity)就是null的

在Runnable的地方增加一个空指针判断 mAutoSizeRunnable = Runnable { if (mCurrentActivity != null) { //...... } }

我认为只需要在onActivityResumed 赋值就行,activity回退过程 onPause(B)->onRestart(A)->onStart(A)->onResume(A)->oStop(B)

Fly-Felix commented 1 year ago

我这里使用直接崩溃了,从activity返回的时候先执行的onActivityResumed,然后才是onActivityDestroyed,这样ScreenUtils.getScreenSize(mCurrentActivity)就是null的

在Runnable的地方增加一个空指针判断 mAutoSizeRunnable = Runnable { if (mCurrentActivity != null) { //...... } }

我认为只需要在onActivityResumed 赋值就行,activity回退过程 onPause(B)->onRestart(A)->onStart(A)->onResume(A)->oStop(B)

当时好像还遇到了一些其他问题,具体是什么问题我忘记了,可以试试看

TonyChou commented 1 month ago

初始化的时候使用ScreenSizeFactory 实时获取屏幕宽高不就得了,然后在onConfigurationChanged里面重新autoConvertDensityOfCustomAdapt一下就能解决横竖屏字体混乱的问题 AutoSizeConfig.getInstance().setScreenSizeFactory(new AutoSizeConfig.IScreenSizeFactory() {

                @Override
                public int screenWidth(int i) {

                }

                @Override
                public int screenHeight(int i) {

                }
            })

override fun onConfigurationChanged(newConfig: Configuration) {
    AutoSize.autoConvertDensityOfCustomAdapt(this, this)
    super.onConfigurationChanged(newConfig)
    LogUtils.i(TAG, "onConfigurationChanged:$localClassName")
}
ysj40540 commented 1 month ago

初始化的时候使用ScreenSizeFactory 实时获取屏幕宽高不就得了,然后在onConfigurationChanged里面重新autoConvertDensityOfCustomAdapt一下就能解决横竖屏字体混乱的问题 AutoSizeConfig.getInstance().setScreenSizeFactory(new AutoSizeConfig.IScreenSizeFactory() {

                @Override
                public int screenWidth(int i) {

                }

                @Override
                public int screenHeight(int i) {

                }
            })

override fun onConfigurationChanged(newConfig: Configuration) {
    AutoSize.autoConvertDensityOfCustomAdapt(this, this)
    super.onConfigurationChanged(newConfig)
    LogUtils.i(TAG, "onConfigurationChanged:$localClassName")
}

mark