Android10 屏幕方向适配

问题

假如项目突然有一个支持pad的需求,需要将所有的页面都支持横屏,该怎么做?
常见方案:

  • 将manifest的中活动的screenOrientation属性都固定为unspecified,问题就是手动修改十分麻烦,且项目本身是增量编译的情况下,必须使用耗时的全量编译才行;
  • 使用BaseActivity或者ActivityLifecycleCallbacks中动态去设置(kotlin):
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
    问题在于这种方式在Android10上有问题,横屏跳转到下一个活动,手机会先竖屏展示,然后再自动切成横屏,也就是“跳一下”。

问题解决

目标一:自动化修改manifest文件,使其支持增量编译

思路:在Gradle构建APK的过程中,在总的manifest文件生成(每个Module的manifest文件自动合并后)之后,将所有的screenOrientation都改动成unspecified,这样不管在哪种编译模式下都能将所有页面都改动到:

//在app下的build.gradle文件末尾中添加
//此处是kts脚本,换成groovy脚本照着抄就行,大同小异
//将所有的竖屏修改为unspecified,为了测试,临时把代码放在这里

//项目构建之后
project.afterEvaluate {
    //获取输入,包含了资源输入和manifest输入(输入-transform-输出)
    //其实也可以自己对 process[XXX]Manifest 相关的几个task直接操作
    android.applicationVariants.forEach { variant->
        variant.outputs.forEach { output ->
            val manifestTask = output.processManifestProvider.orNull
            if (manifestTask != null) {
                doLastReplaceManifest(manifestTask)
            } else {
                val taskName = output.processManifestProvider.name
                project.tasks.whenTaskAdded(object : Action {
                    override fun execute(t: Task) {
                        if (t.name == taskName) {
                            doLastReplaceManifest(output.processManifestProvider.get())
                        }
                    }
                })
            }
        }
    }
}

fun doLastReplaceManifest(task: com.android.build.gradle.tasks.ManifestProcessorTask) {
    task.doLast {
        val startTime = System.currentTimeMillis()
        val manifestPath = "${task.manifestOutputDirectory.get().asFile.absolutePath}/AndroidManifest.xml"
        val file = file(manifestPath)
        if (!file.exists()) {
            println("not find manifest file, path=${file.absolutePath}")
            return@doLast
        }
        val str = file.readText()
        file.setWritable(true)
        file.writeText(str.replace(
                "screenOrientation=\"portrait\"",
                "screenOrientation=\"unspecified\""
        ))
        println("replace portrait to unspecified, spent ${System.currentTimeMillis() - startTime}ms")
    }
}

其实方案一有一个问题就是,当需要动态改变屏幕方向的时候就还是会“跳一下”。
例如在上面的基础上再加上下面的动态代码(固定为横屏)
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE

目标二:解决安卓10动态修改屏幕方向“跳一下”问题

在探索时发现,对于一个活动,manifest中它的screenOrientation只是locked的时候,动态去修改屏幕方向,它就不会再“跳一下”。
举个简单例子:

      //manifest.xml
       

     //Activity.kt
    override fun onCreate(savedInstanceState: Bundle?) {
        requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
        super.onCreate(savedInstanceState)
    }

至于自动化的过程,请参照方案一。

转载请注明出处
https://www.jianshu.com/p/a4cc34923806

你可能感兴趣的:(Android10 屏幕方向适配)