平常我们遇到的横竖屏切换最大的问题就是,屏幕切换后,原来界面中的东西会被清空,也就是Activity被重新创建。那么这时候就需要你做一些设置了,最简单的就是在AndroidMainfest.xml中设置activity中的android:screenOrientation属性值来实现。
(一)简单了解横竖屏的属性
既然通过属性进行控制横竖屏,那么我们就先来讲讲有哪些属性,分别代表什么意思。(其实也是为了自己以后方便查阅)
"unspecified":默认值 由系统来判断显示方向。这个和设备有关,不同设备会有不同的显示方向。
"landscape":横屏显示。
"portrait":竖屏显示。
"user":用户当前首选的方向。
"behind":和该Activity下面的那个Activity的方向一致(在Activity堆栈中的)。
"sensor":由物理的感应器来决定。如果用户旋转设备,这时屏幕会横竖屏切换。
"nosensor":忽略物理感应器,这样就不会随者用户旋转设备而横竖屏切换了。
比如进行了以下设置:
android:screenOrientation="portrait"
则无论手机如何旋转,拥有这个属性的activity都始终竖屏显示。
android:screenOrientation="landscape"
则无论手机如何旋转,拥有这个属性的activity都始终横屏显示。
当然你也可以在代码中进行横竖屏的设置:
设置为竖屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
设置为横屏
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
(二)如何阻止Activity被重建
下面就是我们最关心的,如何防止屏幕横竖屏切换而导致的Activty被重建。即当前界面中的数据不会因为屏幕的切换而消失。其实Android已经为我们提供了解决方案,就是通过onConfigrationChanged拦截横竖屏变换,从而进行必要的重新布局和切换操作。
首选,在AndroidManifest.xml文件中为相应的Activity设置android:configChanges属性,从而让Activity避免重建流程。
Android3.2以前的SDK可以使用如下配置:
android:configChanges="orientation|keyboardHidden"
Android3.2以后的SDK必须在原来基础上添加screenSize属性:
android:configChanges="orientation|keyboardHidden|screenSize"
onConfigurationChanged()方法
在Activity中可以重写这个方法,当屏幕方向发生改变时的回调方法
/**
* 系统配置发生改变时回调的方法
* 包括系统语言、横竖屏切换、字体大小、键盘等
* */
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(TAG, "onConfigurationChanged: "+newConfig.orientation);
}
当然这个方法被调用的前提是,已经在AndroidManifest.xml文件中设置了configChanges属性“orientation”。需要注意的是,onConfigurationChanged函数中只能获得横竖屏切换后的参数。顺便说以下,这个方法其实在很多时候都会被回调,比如:切换系统语言、切换字体大小、接入键盘等。
(三)效果展示
(四)对于setRequestedOrientation函数的用法说明
手动调用setRequestedOrientation之后,假如会引发横竖屏切换(即请求得横竖屏要求与当前得横竖屏状态不一致),那么会立即调用onConfigurationchanged函数;假如不会引发横竖屏切换(请求前后一致),那么就不会调用onConfigurationchanged函数。
onConfigurationchanged函数得调用可以在Activity得任何地方,即也可以在它自身中调用,但是一旦通过这种设置完成横竖屏切换之后,那么后面不论屏幕如何翻转变化,都不会再触发横竖屏切换了,也就是等同于再AndroidManifest.xml中设置了android:screenOrientation属性为横屏或者竖屏。如要回复,则必须重新调用setRequestedOrientation方法。
(五)现场保护Fragment
1.保持Fragment对象
主要用到了两个方法:
getSupportFragmentManager().findFragmentByTag()
setRetainInstance(true)
Fragment类:
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: "+savedInstanceState);
//保存fragment必须要加这条语句
setRetainInstance(true);
}
Activity类:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm=getSupportFragmentManager();
scoreFragment=fm.findFragmentByTag("scoreFragment");
//如果fragment为空,则创建一个fragment
if (scoreFragment==null){
scoreFragment=new ScoreFragment();
fm.beginTransaction().replace(android.R.id.content,scoreFragment,"scoreFragment")
.commit();
}
Log.d(TAG, "onCreate: ");
}
2.保存和恢复Fragment的状态
调用回调函数onSaveInstanceState()将要保存的数据存入bundle中,然后在onCreate中进行提取数据,Activity类中的操作不变
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SCORE,score);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate: "+savedInstanceState);
//保存fragment必须要加这条语句
//setRetainInstance(true);
//如果savedInstanceState不为空,则将保存的值取出来
if (savedInstanceState!=null){
this.score=savedInstanceState.getInt(SCORE);
}
}