横竖屏适配最好的方式还是判断设备是平板或手机,进入app时固定展示横屏或者竖屏,设置android:screenOrientation="locked"禁止在app内切换横竖屏。无论什么框架都能适用,且不需要考虑什么兼容。
为了方便横竖屏切换需使用ViewModel和DataBinding双向绑定来控制界面控件的数据和状态,将界面文案、点击事件、是否可见等等存放在ViewModel中,否则需要在Bundle存取大量数据来保证横竖屏切换后界面状态和数据。
横竖屏涉及到Activity和Fragment的复用重建、旧Fragment的关联状态、生命周期的管理避免如网络请求开启线程导致Activity无法释放及请求完成继续操作界面但界面已经销毁导致闪退、界面展示如按钮状态输入文本的内容保存、横屏界面布局和竖屏界面的切换。需要有大局观来考虑各种问题,实现比较复杂。
方法一:保留Activity横竖屏切换重建,Fragment重建,使用mvvm框架实现双向绑定,使得切换后界面显示数据保持一致。缺点就是每次横竖屏切换都会生成新对象,需要做好内存管理。
方法二:Activity不旋转,一个Fragment在同一个布局文件中写两套布局即有横屏又有竖屏界面,区分横竖屏展示。在Fragment的onConfigurationChanged方法中实现横竖屏布局的隐藏和展示。布局中控件状态和文案通过vm来控制,让两个布局中对应控件有相同状态。也可拆分为多个部分,根据横竖屏动态改变控件在布局中的位置。优点是横竖屏共用一个Activity/Fragment对象,缺点是一个xml文件实现两个布局可能内容比较多有上千行。
<activity
android:name="com.slaoren.mvvmexamp.ui.MvvmDemo2Activity"
android:configChanges="orientation|screenSize" 设置不重建activity
android:screenOrientation="user" />
//MvvmDemo2Activity展示的Fragment
class MvvmConfigurationChangedFragment:BaseFragment<FragmentConfigurationChangedBinding, DemoViewModel>() {
override fun getLayoutId(): Int {
return R.layout.fragment_configuration_changed
}
override fun setView() {
mBinding.vm = mViewModel
//首次进入可以根据横竖屏判断展示什么界面,这里直接展示竖屏
mBinding.clPortrait.visibility = View.VISIBLE
mBinding.clLandscape.visibility = View.GONE
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
//横竖屏切换后在此方法中判断展示什么界面
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(requireContext(), "竖屏", Toast.LENGTH_SHORT).show()
mBinding.clPortrait.visibility = View.VISIBLE
mBinding.clLandscape.visibility = View.GONE
}else{
Toast.makeText(requireContext(), "横屏", Toast.LENGTH_SHORT).show()
mBinding.clPortrait.visibility =