观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

版权声明

本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11180701.html

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

需要了解横竖屏切换关键知识

  1.在Android设备的横竖屏幕,每一次切换横竖屏其实是在重新创建Activity,Activity会重新走一遍生命周期.从onCreate 到 onDestroy

  2.在Activity类里的变量也会重新创建,这点需要注意!

判断屏幕方向,方式一

判断屏幕是否竖屏

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT){
            L.e("触发竖屏");
        }
    }

判断屏幕是否横屏

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
            L.e("触发横屏");
        }
    }

判断屏幕是否是未知方向

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_UNDEFINED){
            L.e("未定义方向");
        }
    }

判断屏幕方向,方式二

这个方式其实是监听activity的配置变化时的回调

 在activity里重写onConfigurationChanged方法

 @Override
    public void onConfigurationChanged(Configuration newConfig) {
        L.e("newConfig.orientation="+newConfig.orientation);
        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
            L.e("触发竖屏");

        }
        if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
            L.e("触发横屏");
        }
        super.onConfigurationChanged(newConfig);
    }

注意!,这个方法没想象这么简单.这个方法回调的条件:   这个方法要求,切换横竖屏不在重新创建activity,就是activity不会再次onCreate,才会回调这个方法.所以正常情况下,你无法在横竖屏后触发这个回调.

为了触发这个回调,我们需要在AndroidManifest.xml给目标Activity添加属性 android:configChanges="orientation|screenSize":

<activity android:name=".test.TestActivity"
          android:configChanges="orientation|screenSize"/>

configChanges这个属性控制着,我们activity在某些情况下是不需要重新创建activity的,这里的不重新创建意味着activity的生命周期将保持不变,不会重新走任何一个生命周期包括onResume.

这里设置方向orientation和尺寸screenSize,就会让方向与尺寸改变时不会重新创建activity.当然还有以下几种情况:

  • “mcc“ 移动国家号码,由三位数字组成,每个国家都有自己独立的MCC,可以识别手机用户所属国家。
  • “mnc“ 移动网号,在一个国家或者地区中,用于区分手机用户的服务商。
  • “locale“ 所在地区发生变化。
  • “touchscreen“ 触摸屏已经改变。(这不应该常发生。)
  • “keyboard“ 键盘模式发生变化,例如:用户接入外部键盘输入。
  • “keyboardHidden“ 用户打开手机硬件键盘
  • “navigation“ 导航型发生了变化。(这不应该常发生。)
  • “orientation“ 设备旋转,横向显示和竖向显示模式切换。
  • “fontScale“ 全局字体大小缩放发生改变

判断屏幕方向,方式三

 这个方法其实是最强的,因为它是监听了方向传感器的值.所以它能监听获取任意方向.

 我们只要new一个OrientationEventListener,开启就行了.注意它不是接口类,是一个抽象类.

private OrientationEventListener mOrientationEventListener;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        mOrientationEventListener = new OrientationEventListener(this) {            @Override
            public void onOrientationChanged(int orientation) {
                L.e("onOrientationChanged: " + orientation);
                if (orientation > 350 || orientation < 20) { //0度  90 正竖屏

                } else if (orientation > 70 && orientation < 110) { //90度 右横屏

                } else if (orientation > 160 && orientation < 200) { //180度 倒竖屏

                } else if (orientation > 250 && orientation < 290) { //270度 左横屏

                }

            }
        };
        if (mOrientationEventListener.canDetectOrientation()) {
            Log.v(TAG, "可以检测方向");
            mOrientationEventListener.enable();//开启
        } else {
            Log.v(TAG, "无法检测方向");
            mOrientationEventListener.disable();
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mOrientationEventListener.disable();//注销
    }

最后注意,在退出时需要注销关闭监听.

另外还有一个更合适在方向监听上使用的,配置参数 SensorManager.SENSOR_DELAY_NORMAL:

mOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) { //
            @Override
            public void onOrientationChanged(int orientation) {
                L.e("onOrientationChanged: " + orientation);
              
            }
        };

SensorManager.SENSOR_DELAY_NORMAL 的意思是,让传感器延迟,更适合在方向的监听使用.所以如果你只需要方向上面的监听推荐添加这个参数创建OrientationEventListener.

这样设置延迟的好处是排除一些中间的波动值,返回的值会更加稳定,这样你可以在判断方向时,不会出现在边界值上反反复复切来切去的问题.

设置当前屏幕方向

在AndroidManifest.xml的Activity里设置Activity

 

android:screenOrientation="portrait"

在activity里写以下任意一个属性

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//设置屏幕为横屏, 设置后会锁定方向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//设置屏幕为竖屏, 设置后会锁定方向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);//方向未定义, 设置后放弃锁定方向

注意,这里的锁定方向意思是指,用户将无法自己改变这个activity的方向. 包括自动切换屏幕的方向传感器.

  • SCREEN_ORIENTATION_UNSPECIFIED  & “unspecified” 默认值。由系统选择方向。在不同设备上,系统使用的政策以及基于政策在特定上下文所做的选择可能有所差异。
  • SCREEN_ORIENTATION_LANDSCAPE & “landscape” 横向方向(显示的宽度大于高度)。
  • SCREEN_ORIENTATION_PORTRAIT &   “portrait” 纵向方向(显示的高度大于宽度)。
  • SCREEN_ORIENTATION_USER & “user” 用户当前的首选方向。
  • SCREEN_ORIENTATION_BEHIND & “behind” 与 Activity 栈中紧接着它的 Activity 的方向相同。
  • SCREEN_ORIENTATION_SENSOR & “sensor” 方向由设备方向传感器决定。显示方向取决于用户如何手持设备,它会在用户旋转设备时发生变化。 但一些设备默认情况下不会旋转到所有四种可能的方向。要允许全部四种方向,请使用 "fullSensor"。
  • SCREEN_ORIENTATION_NOSENSOR  &  “nosensor” 决定方向时不考虑物理方向传感器。传感器会被忽略,因此显示不会随用户对设备的移动而旋转。 除了这个区别,系统在选择方向时使用的政策与“unspecified”设置相同。 
  • SCREEN_ORIENTATION_SENSOR_LANDSCAPE & “sensorLandscape” 横向方向,但根据设备传感器,可以是正常或反向的横向方向。API 级别 9 中的新增配置。
  • SCREEN_ORIENTATION_SENSOR_PORTRAIT &  “sensorPortrait” 纵向方向,但根据设备传感器,可以是正常或反向的纵向方向。API 级别 9 中的新增配置。
  • SCREEN_ORIENTATION_REVERSE_LANDSCAPE &  “reverseLandscape” 与正常横向方向相反的横向方向。API 级别 9 中的新增配置。
  • SCREEN_ORIENTATION_REVERSE_PORTRAIT 反转竖向 &  “reversePortrait” 与正常纵向方向相反的纵向方向。API 级别 9 中的新增配置。 
  • SCREEN_ORIENTATION_FULL_SENSOR &  “fullSensor” 方向由 4 种方向中任一方向的设备方向传感器决定。这与 "sensor" 类似,不同的是它允许所有 4 种可能的屏幕方向,无论设备正常情况下采用什么方向(例如,一些设备正常情况下不使用反向纵向或反向横向,但它支持这些方向)。 API 级别 9 中的新增配置。
  • SCREEN_ORIENTATION_USER_LANDSCAPE &  “userLandscape” 横向方向,但根据设备传感器和用户的传感器首选项,可以是正常或反向的横向方向。 如果用户锁定了基于传感器的旋转,其行为与 landscape 相同,否则,其行为与 sensorLandscape 相同。API 级别 18 中的新增配置。
  • SCREEN_ORIENTATION_USER_PORTRAIT &  “userPortrait” 纵向方向,但根据设备传感器和用户的传感器首选项,可以是正常或反向的纵向方向。 如果用户锁定了基于传感器的旋转,其行为与 portrait 相同,否则,其行为与 sensorPortrait 相同。API 级别 18 中的新增配置。 
  • SCREEN_ORIENTATION_FULL_USER &  "fullUser" 如果用户锁定了基于传感器的旋转,其行为与 user 相同,否则,其行为与 fullSensor 相同,允许所有 4 种可能的屏幕方向。 API 级别 18 中的新增配置。
  • SCREEN_ORIENTATION_LOCKED &  “locked” 将方向锁定在其当前的任意旋转方向。API 级别 18 中的新增配置。

实现按需求打包横竖屏APP

在一些项目里,我们可以使用一个项目分别打包出横屏app与竖屏app. 现在已经知道在Activity里切换横竖屏会导致Activity实例重新生成一份.这会导致一些资源初始化混乱. 所以,我们还是应该在AndroidManifest.xml里一键配置横竖屏.方法如下:

首先在build.gradle里添加一个常量, 这样我们就可以按需求设置竖屏portrait或者横屏landscape

    defaultConfig {
    
        manifestPlaceholders = [ SCREEN_ORIENTATION: "portrait"]
    }

然后在AndroidManifest.xml 添加它

  <activity
            android:name=".function.systemsettings.SetLanguageActivity"
            android:screenOrientation="${SCREEN_ORIENTATION}" />

 

end

posted on 2019-07-13 15:11  观心静  阅读(9725)  评论(0编辑  收藏  举报