屏幕旋转的适配问题以及遇到的一些坑

原文地址:http://www.jianshu.com/p/19393bb08e4f

在手机APP开发的时候,一般默认会适配竖屏,游戏开发除外。但是在Android平板电脑开发中,屏幕旋转的问题比较退出,可以这样说,平板电脑的最初用意就是横屏使用的,比较方便,用户会经常旋转我们的屏幕。

这里主要针对平板开发中的一些问题做一些总结。

###1、防止屏幕旋转之后,Activity的销毁问题。

为了适配屏幕,Activity默认在屏幕旋转之后会销毁并且重建,但是这种情况会造成用户输入数据的丢失(需要开发者手动去保存和恢复,会带来一定的工作量),Activity毕竟是重量级的组件,它的销毁和重建会使得性能的下降,因此我们需要防止Activity的销毁和重建。

####做法

在清单文件中为Activity添加一些配置,configChanges属性添加orientation|screenSize:

<activity
        android:name=".ui.activity.MainActivity"
        android:configChanges="orientation|screenSize"
        android:launchMode="singleTask"
        android:windowSoftInputMode="stateAlwaysHidden">
复制代码

通过上述的配置可以防止Activity的销毁和重建。

###2、View屏幕旋转适配

除了制作横屏和竖屏两份布局文件的方法之外,如果我们的View是动态添加到Window的,屏幕旋转之后,我们的界面以及View需要做一些变动以适应屏幕。

我们可以复写Activity的onConfigurationChanged方法,并且在里面修改一些东西。

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

    //一些适配操作
}
复制代码

这里举个例子,如说我们的ListView右边有一个字母索引控件,这个控件是直接new出来并且是直接覆盖在ListView上面的。当屏幕旋转之后,这个字母索引控件的位置需要刷新(重新布局以及绘制)。因为这个控件是在我们的ListView的右侧,并且竖直方向居中。这时候我们就需要动态获取屏幕上的ListView的宽高,然后才能计算出字母控件应该布局的位置。

####但是这里我们会遇到一些坑

直接通过View的getWidth方法或者先measure然后通过getMeasuredWidth方法获取到的宽都是错误的,获取到的是屏幕旋转之前的值,如下面的代码所示。但是我需要的是ListView实时的宽高值,这时候我们只能手动去计算。例如我们要获取ListView的高度,那么我们可以先拿到Window的总高度,然后减去状态栏、Toolbar的高度来获取(这里只是一个例子,具体做法需要具体分析)。

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

    //一些适配操作
    WindowManager wm = getWindowManager();//Activity可以直接获取WindowManager
    //  WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    final int windowWidth = wm.getDefaultDisplay().getWidth();
    final int windowHeight = wm.getDefaultDisplay().getHeight();

    //手动去计算ListView的宽高
    final int mListViewWidth = windowWidth;
    final int mListViewHeight = windowHeight - statusbarHeight - toolbarHeight;

    //下面获取ListView的宽高是有问题的
    //  mListView.measure(0, 0);
    //  mListView.getMeasuredWidth();
    //  mListView.getMeasuredHeight();

    //  mListView.getWidth();
    //  mListView.getHeight();

	//	。。。其他适配操作
}
复制代码

###屏幕旋转的不确定性问题

最近又遇到屏幕旋转相关的新的问题,因此记录下来。我们知道,在Activity、View、Fragment等旋转的时候,如果你在清单文件中配置不重新创建的话,就会调用onConfigurationChanged方法。

但是问题来了,这个问题有一些不确定性因素,比如说当你的页面或者View被遮挡住(Stop)的时候就不会回调onConfigurationChanged这个方法。这比较略坑,会带来一些UI的偶发性问题。

解决办法就是我们自定义一个广播接受者专门用来接受onConfigurationChanged这个广播,这样子就可以确保,无论什么情况下,系统ConfigurationChanged的时候你的代码都会被执行。

自定义的ConfigurationChangeReceiver如下,这里提供一个静态方法方便注册。

public abstract class ConfigurationChangeReceiver extends BroadcastReceiver {

    private static final String TAG = ConfigurationChangeReceiver.class.getSimpleName();

    public static IntentFilter getIntentFilter() {
	IntentFilter filter = new IntentFilter();
	filter.addAction("android.intent.action.CONFIGURATION_CHANGED");
	return filter;
    }
}
复制代码

接下类在Activity或者Fragment中的正确位置注册(onAttachedToWindow、onDetachedFromWindow):

private void initConfigurationChangeReceiver() {
    mConfigurationChangeReceiver = new ConfigurationChangeReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //你的屏幕适配代码
        }
    };
    this.registerReceiver(mConfigurationChangeReceiver, ConfigurationChangeReceiver.getIntentFilter());
}
复制代码

记得反注册,防止内存泄漏哦。

private void unRegisterConfigurationChangeReceiver() {
    if (mConfigurationChangeReceiver != null) {
        this.unregisterReceiver(mConfigurationChangeReceiver);
    }
}
复制代码

如果觉得我的文字对你有所帮助的话,欢迎关注我的公众号:

我的群欢迎大家进来探讨各种技术与非技术的话题,有兴趣的朋友们加我私人微信huannan88,我拉你进群交(♂)流(♀)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值