Android 横竖屏处理的知识小结
Android手机一般都支持横竖屏旋转,系统也会提供一个设置,控制允不允许旋转。这里对如何在App中控制界面的旋转方向做一个小结。
界面旋转方向的决定因素
决定一个界面显示为横屏/竖屏的因素有几个:
- 系统的设置项,一般可以设置为只允许竖屏或可旋转切换。
- 设备的物理传感器感应到的设备方向。
- 不同App里的代码对横竖屏的设置。
需要注意的一点是,这三个因素没有固定的优先级。所以即使系统的设置项中设置了固定为竖屏,App里的代码也可以将界面设置为横屏,当然影响的范围仅限于App内部界面。
代码中设置横竖屏的方法
我们有2种方法设置横竖屏:
在AndroidManifest.xml文件中,对
在Java中调用Activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE),具体的值和作用见下文。
如果在xml中设置,则在初始化界面时就已经确定好其方向。而在如果Java中设置,则可以做到根据不同情况动态设置。
设置横竖屏时传入的值和作用
以下列出在AndroidManifest.xml中
- unspecified:默认值,不做任何指定,由系统来决定显示方向。这将由上一个activity来决定,或者当activity处于栈底时由用户设置的方向来决定。
- landscape:保持横屏。
- portrait:保持竖屏。
- user:用户当前设置的orientation值。
- behide:保持和上一个Activity的方向一致。
- sensor:完全根据物理传感器的方向来决定。注意用这个值时会忽略用户在系统设置中的旋转开关状态。(注意一般机器即使用这个值也不会支持竖屏旋转180度)
- nosensor:忽略物理传感器的方向。这将导致用户旋转手机时不会切换横竖屏。
- sensorLandscape:保持横屏,但可以根据物理传感器来决定横屏的方向。
- sensorPortrait:保持竖屏,但可以根据物理传感器来决定竖屏的方向。
- reverseLandscape:保持横屏,但方向与使用landscape时相反。
- reversePortrait:保持竖屏,但方向与使用portrait时相反。
- fullSensor:与sensor大致相同,区别在于这个属性会允许4个方向都可以旋转。
- userLandscape:保持横屏,但可以在用户允许旋转的情况下,根据物理传感器来决定横屏的方向。(注意与sensorLandscape对比)
- userPortrait:保持竖屏,但可以在用户允许旋转的情况下,根据物理传感器来决定竖屏的方向。(注意与sensorPortrait对比)
- fullUser:与user大致相同,区别在于如果用户允许旋转,这个属性允许4个方向都可以旋转。
- locked:屏幕方向会锁定在当前方向,不能再旋转。
该属性的值有很多,但一般比较常用的几个值也就几个:unspecified(允许旋转)、landscape(固定为横屏)、portrait(固定为竖屏)。而且一般我们只需要在AndroidManifest.xml中指定好固定的值就可以了。除非你对横竖屏切换有自己的一套逻辑,才需要在不同的逻辑下进行不同的设置。
横竖屏切换时引起的Activity重新创建
默认情况下,横竖屏切换会引起当前Activity销毁然后重新创建。所以我们可以在Activity重新创建时根据当前横竖屏状态做一些差异化。最常见的就是根据横竖屏采用不同的layoutxml。
在res目录下建立layout-land和layout-port目录,在不同目录下分别放一个同名的layoutxml文件,然后在代码里正常使用这个layout文件,系统就会在横竖屏切换并重新创建Activity时自动使用对应的layout文件。如:
@Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); }
如果不想通过创建多个layout文件来区分横竖屏布局,也可以用Java代码来做一些差异化,只要使用以下判断即可获取当前横竖屏的信息。
@Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout); //获取横竖屏信息 intorientation=getResources().getConfiguration().orientation; if(orientation==Configuration.ORIENTATION_LANDSCAPE){ //针对横屏做一些处理 }elseif(orientation==Configuration.ORIENTATION_PORTRAIT){ //针对竖屏做一些处理 } }
有一个点需要注意,关于Activity的生命周期被重新调用,有的资料说:
当不设置Activity的android:configChanges属性时,切到横屏时会重新执行一次生命周期,而切到竖屏时会执行两次。
如果设置了android:configChanges="orientation"属性,则都只会执行一次。
但是个人实验没有验证出这个说法。保险起见,可以加上android:configChanges="orientation"属性,确保生命周期只调用一次。
阻止横竖屏切换时Activity重启
虽然我们可以用上面的方法对横竖屏做不同的布局,但是横竖屏切换导致的Activity重新创建还会引起用户当前状态、数据的丢失。例如EditText中输入到一半的文字在Activity重新创建后会丢失。所以如果有办法能在旋转屏幕时不重新创建Activity,应该是更好的一种选择。
我们可以在AndroidManifest.xml中为相应的
Android3.2(APILevel13)以前的SDK可以使用如下配置
android:configChanges="orientation|keyboardHidden"
而Android3.2以后的SDK则需要设置为
android:configChanges="keyboardHidden|orientation|screenSize"
这样一来,横竖屏切换时Activity将不会重新创建。
横竖屏切换时的回调
一旦我们按照上述方法设置了android:configChanges属性,那么横竖屏切换时Activity将不会重新创建,那么当屏幕旋转时,我们在代码上怎么感知呢?可以通过OverrideActivity和View的onConfigurationChanged方法。
@Override publicvoidonConfigurationChanged(ConfigurationnewConfig){ super.onConfigurationChanged(newConfig); if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){ //针对横屏做一些处理 }elseif(newConfig.orientation==Configuration.ORIENTATION_PORTRAIT){ //针对竖屏做一些处理 } }
判断当前屏幕方向
有了上面的横竖屏切换的回调,我们就可以及时感知到屏幕的状态变化。但因为竖屏、横屏都有两个不同的方向,所以Android系统又提供了方法给我们获取当前屏幕精确的旋转方向。
Displaydisplay=activity.getWindowManager().getDefaultDisplay(); introtation=display.getRotation(); // //rotation的值表示了当前屏幕的旋转角度,可能的值有: //Surface.ROTATION_0、Surface.ROTATION_90、 //Surface.ROTATION_180、Surface.ROTATION_270。 //
这样我们就可以判断当前屏幕的方向了。
举个例子,以下方法获取当前屏幕的旋转方向,然后将旋转方向锁定,使用户不能再旋转。
publicstaticvoidlockScreenOrientation(Activityactivity){ Displaydisplay=activity.getWindowManager().getDefaultDisplay(); switch(display.getRotation()){ caseSurface.ROTATION_90: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; caseSurface.ROTATION_180: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; caseSurface.ROTATION_270: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; default: activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } }
总结
- android:screenOrientation属性可以控制Activity的方向,常用的值有unspecified(默认,可旋转)、landscape(保持横屏)、portrait(保持竖屏)。
- 触发横竖屏切换时,如果希望Activity销毁并重新创建,则可以设置Activity的android:configChanges="orientation"。
- 触发横竖屏切换时,如果不希望Activity销毁并重新创建,可以设置Activity的android:configChanges="keyboardHidden|orientation|screenSize"。此后横竖屏切换时,可以在Activity.onConfigurationChanged或View.onConfigurationChanged方法中处理切换后的事情。
- 在任何时候可以用getResources().getConfiguration().orientation获取屏幕的横竖屏状态。
- 在任何时候可以用activity.getWindowManager().getDefaultDisplay().getRotation()获取屏幕的旋转角度。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。