热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android中Activity横竖屏切换的那些事

讲解之前需要说明的是 旋转屏幕:在系统的自动旋转屏幕开启的情况下,我们旋转屏幕 手动设置屏幕:我们自己去调用Activity

讲解之前需要说明的是

  • 旋转屏幕:在系统的自动旋转屏幕开启的情况下,我们旋转屏幕
  • 手动设置屏幕:我们自己去调用Activity的 setRequestedOrientation 方法。

设置屏幕的方向

简介

描述
unspecified 默认值。系统自动选择屏幕方向
behind 跟activity堆栈中的下面一个activity的方向一致
landscape 横屏方向,显示的宽比高长
portrait 竖屏方向,显示的高比宽长
sensor 由设备的物理方向传感器决定,如果用户旋转设备,这屏幕就会横竖屏切换
nosensor 忽略物理方向传感器,这样就不会随着用户旋转设备而横竖屏切换了("unspecified"设置除外)
user 用户当前首选的方向
reverseLandscape API 9 以上,反向横屏
reversePortrait API 9 以上,反向竖屏
sensorLandscape API 9 以上,横屏,但是可以根据 物理方向传感器来切换正反向横屏
sensorPortrait API 9 以上,竖屏,但是可以根据 物理方向传感器来切换正反向竖屏
fullSensor API 9 以上,上下左右四个方向,由物理方向传感器决定
locked API 18 以上,锁死当前屏幕的方向

官网文档地址

第一种

我们可以在AndroidManifest 清单文件里面制定Activity的方向


  
    

    
  

这样横竖屏切换的时候不会重新创建Activity

第二种

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

Android:android:configChanges

如果我们不配置configuration ,当 configuration 发生变化的时候,activity会自动处理它。反之,如果我们配置了相应的 configuration,当新的 configuration 发生变化的时候,会回调 Activity 的 onConfigurationChanged() 方法。

下面我们一起来看一下几个常用的值得介绍,其他不常用的hi请自行查阅文档。官网地址:

描述
keyboardHidden 键盘的可访问性发生变化——例如:用户发现了硬件键盘。
orientation 屏幕方向发生变化——用户旋转了屏幕。注意:如果应用程序的目标API级别是13或更高(通过属性minSdkVersion和属性targetSdkVersion声明),你也需要声明配置项screenSize,因为这将在设备选择肖像和屏幕方向时发生改变。
screenLayout 屏幕布局发生变化——这个会导致显示不同的Activity。屏幕方向发生变化——用户旋转了屏幕。注意:如果应用程序的目标API级别是13或更高(通过属性minSdkVersion和属性targetSdkVersion声明),你也需要声明配置项screenSize,因为这将在设备选择肖像和屏幕方向时发生改变。
screenSize 当前可用屏幕大小发生变化。这代表一个当前可用大小的变化,和当前的比率相关,因此当用户选择不同的画面和图像,会发生变化。然而,如果你的程序目标API级别是12或更低,你的Activity总是会自己处理这个配置变化(这个变化不会引起Activity的重启,甚至在Android 3.2或更新的设备上)。在API级别13里加入的。

android:configChanges 常用配置

在Android 3.2以后,如果我们进行下列的配置 ,这样的话横竖屏不会重新创建Activity,但是会调用 onConfigurationChanged()方法


  
    

    
  

在api 3.2 以前,我们只需这样配置即可,android:cOnfigChanges="keyboardHidden|orientation"。


  
    

    
  


小结

当我们进行了上述的配置,

  1. 竖屏 》 横屏 onConfigurationChanged()方法会调用一次
  2. 横屏 》 竖屏 onConfigurationChanged()方法也会调用一次

因此我们通常可以进行相应的处理

public void onConfigurationChanged(Configuration newConfig) { 

  super.onConfigurationChanged(newConfig); 

  if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 
    // 加入横屏要处理的代码 
  } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { 
    // 加入竖屏要处理的代码 
  } 
}

如果我们同时设置了 android:cOnfigChanges="keyboardHidden|orientation|screenSize" 和 android:screenOrientation="portrait",那又会是怎样的呢?

如果我们打开系统的自动旋转屏幕,旋转屏幕,系统不会发生变化,也不会调用 Activity 的 onConfigurationChanged 方法。

当我们手动调用 setRequestedOrientation() 方法去改变屏幕的方向的时候,还是会调用 onConfigurationChanged 方法的

扩展

设置全屏模式

// 去掉ActionBar
requestWindowFeature(Window.FEATURE_NO_TITLE); 
// 设置全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

在实际项目中,我们通常会固定我们应用的屏幕方向,只对一些特定的需要切换屏幕的Activity做处理,那我们如何统一设置屏幕的方向呢?

第一种方法,复制张贴,在AndroidManifest清单文件里面的每一个Activity标签增加如下标签。





第二种方法,刚开始我直接在 AppTheme 里面 设置 android:screenOrientation,但是没有效果,刚开始我也很纳闷,后面查阅了官网文档,描述如下,才解决了疑问.

Specify the orientation an activity should be run in. If not specified, it will run in the current preferred orientation of the screen. This attribute is supported by the element.


即这种方法不可取

第三种方法,在BaseActivity里面动态设置

public class BaseActivity extends AppCompatActivity {


  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
  }

}

同时列出这三种方法,最主要的目的不是为了告诉大家有这几种方法可以统一设置屏幕的方向,最重要的是告诉大家一种思想吧。通常在xml 文件可以设置的,在java 代码也可以设置。

利用系统的加载机制自动帮我们加载相应的布局

如果大家在资源目录res 中添加了 layout-land(横向布局文件夹) 和 layout-port (竖想布局文件夹),重启Activity模式的横竖屏切换,

可能有人会有这样的疑问,当我们设置了Activity的方向为竖屏或者横屏的时候,旋转屏幕并不会重新调用Activity的各个生命周期,那我们要怎样检测呢?

其实很简单,那就是利用我们的传感器,然后根据旋转的方向做相应的处理

//注册重力感应器 屏幕旋转
mSm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSm.registerListener(mOrientationSensorListener, mSensor, SensorManager.SENSOR_DELAY_UI);
public class OrientationSensorListener implements SensorEventListener {
  private static final int _DATA_X = 0;
  private static final int _DATA_Y = 1;
  private static final int _DATA_Z = 2;

  public static final int ORIENTATION_UNKNOWN = -1;
  private boolean sensor_flag = true;

  public static final String TAG = "xujun";

  int mLastAngle=-1;
  AngleChangleListener mAngleChangleListener;

  public OrientationSensorListener(AngleChangleListener angleChangleListener){
    mAngleChangleListener=angleChangleListener;
  }

  @Override
  public void onAccuracyChanged(Sensor arg0, int arg1) {
    // TODO Auto-generated method stub

  }


  @Override
  public void onSensorChanged(SensorEvent event) {

    float[] values = event.values;

    int orientation = ORIENTATION_UNKNOWN;
    float X = -values[_DATA_X];
    float Y = -values[_DATA_Y];
    float Z = -values[_DATA_Z];

    /**
     * 这一段据说是 android源码里面拿出来的计算 屏幕旋转的 不懂 先留着 万一以后懂了呢
     */
    float magnitude = X * X + Y * Y;
    // Don't trust the angle if the magnitude is small compared to the y value
    if (magnitude * 4 >= Z * Z) {
      //屏幕旋转时
      float OneEightyOverPi= 57.29577957855f;
      float angle = (float) Math.atan2(-Y, X) * OneEightyOverPi;
      orientation = 90 - (int) Math.round(angle);
      // normalize to 0 - 359 range
      while (orientation >= 360) {
        orientation -= 360;
      }
      while (orientation <0) {
        orientation += 360;
      }
    }

    if (orientation > 225 && orientation <315) { //横屏
      sensor_flag = false;
    } else if ((orientation > 315 && orientation <360) || (orientation > 0 &&
        orientation <45)) { //竖屏
      sensor_flag = true;
    }
//    Log.i(TAG, "onSensorChanged: orientation=" + orientation+"  mLastAngle="+mLastAngle);
    if(mLastAngle!=orientation && mAngleChangleListener!=null){
      mAngleChangleListener.onChange(orientation);
      mLastAngle=orientation;
    }

  }
}

设备旋转时保存Activity的交互状态

大家先看一下Activity的生命周期,我们知道如果我们不配置Activity的方向或者Activity的 android:configchang 属性的时候,每次旋转屏幕,Activity都会重新被创建出来。那我们要如何保存我们当前的状态呢。

其实我们可以考虑在 onPause() 或者在 onStop() 里面保存我们相应的数据,再在onCreate() 方法里面判断 savedInstanceState 是否有缓存我们的数据即可。 至于选择在onPause() 还是 onStop() 保存数据,得看具体的需求分析。 onPause() 在界面失去焦点的时候会回调, onStop() 方法在界面完全不可见的时候会回调。

private static final String KEY_INDEX = "index";
private int mCurrentIndex = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
  if (savedInstanceState != null) {
    mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);
  }
}

@Override
protected void onPause(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putInt(KEY_INDEX, mCurrentIndex);
}

Demo 下载地址:ScreenDemo_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文是关于自学Android的笔记,包括查看类的源码的方法,活动注册的必要性以及布局练习的重要性。通过学习本文,读者可以了解到在自学Android过程中的一些关键点和注意事项。 ... [详细]
  • [转载]从零开始学习OpenGL ES之四 – 光效
    继续我们的iPhoneOpenGLES之旅,我们将讨论光效。目前,我们没有加入任何光效。幸运的是,OpenGL在没有设置光效的情况下仍然可 ... [详细]
author-avatar
lanxians
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有