最近在做播放器的时候遇到一个问题,在屏幕方向改变之后需要切换播放器全屏/非全屏的时候,在重写了onConfigurationChanged方法并在manifest.xml配置文件中添加

  1. android:screenOrientation="sensor"
  2. android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"

之后,在屏幕方向改变之后确实切换了播放器的方向,但是在我的程序中,需要一个播放器控制按钮,当用户点击按钮时手动切换播放器方向(即播放器全屏/小屏状态切换)和屏幕方向改变时自动切换两个功能并存;最开始想的是直接使用setRequestedOrientation()设置屏幕方向应该就OK了,但是发现这样做是行不通的.之后了解到因为setRequestedOrientation设置屏幕方向之后,比如说setRequestedOrientation(portrait)方法,就设定了屏幕方向是portrait,和在清单文件中配置android:screenOrientation="portrait"是同等的效果;也即不再响应屏幕方向改变,只支持portrait方向;

  言归正转,说我的处理方法,android给我们提供了OrientationEventListener,从字面意思就知道是干什么用的;这个监听器有一个onOrientationChanged(int rotation)方法会将当前屏幕旋转的度数返回给用户;

  先看持接口中方法返回的旋转度数的计算方法;

  

  上图中金色区域就是手机,角度就是绿线和红线之间的角度,顺时针旋转手机,角度增大,角度范围0-360;手机平放的角度为-1;

  下面分别是横屏和竖屏的界面,按钮即用于切换屏幕方向;

 

  再看看具体实现:

1.声明变量

    private OrientationEventListener mOrientationListener; // 屏幕方向改变监听器
private boolean mIsLand = false; // 是否是横屏
private boolean mClick = false; // 是否点击
private boolean mClickLand = true; // 点击进入横屏
private boolean mClickPort = true; // 点击进入竖屏

2.初始化监听器

    /**
* 开启监听器
*/
private final void startListener() {
mOrientationListener = new OrientationEventListener(this) {
@Override
public void onOrientationChanged(int rotation) {
// 设置竖屏
if (((rotation >= 0) && (rotation <= 30)) || (rotation >= 330)) {
if (mClick) {
if (mIsLand && !mClickLand) {
return;
} else {
mClickPort = true;
mClick = false;
mIsLand = false;
}
} else {
if (mIsLand) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mIsLand = false;
mClick = false;
}
}
}
// 设置横屏
else if (((rotation >= 230) && (rotation <= 310))) {
if (mClick) {
if (!mIsLand && !mClickPort) {
return;
} else {
mClickLand = true;
mClick = false;
mIsLand = true;
}
} else {
if (!mIsLand) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mIsLand = true;
mClick = false;
}
}
}
}
};
mOrientationListener.enable();
}

3.设置按钮点击切换屏幕方向响应事件

        mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mClick = true;
if (!mIsLand) {
if (onClickOrientationListener != null) {
onClickOrientationListener.landscape();
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mIsLand = true;
mClickLand = false;
} else {
if (onClickOrientationListener != null) {
onClickOrientationListener.portrait();
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
mIsLand = false;
mClickPort = false;
}
}
});

4.上面用到一个接口OnClickOrientationListener,里面包含两个方法,分别用于用户点击切换横屏/竖屏时的回调;

interface OnClickOrientationListener {
  public void landscape();
  public void portrait();
}

  代码贴完了, 简单说说思路,点击的时候,直接切换屏幕方向,切换之后,需要当手机屏幕也旋转到所切换的方向之后,才又开始监听手机屏幕旋转事件,这样就实现了setRequestedOrientation之后仍然可以通过旋转手机切换屏幕的功能;

  举个例子:
-->手机当前是竖屏状态,Activity也是竖屏状态
-->用户点击切换按钮
-->Activity切换为横屏,手机为竖屏;此时通过设置flag,使OrientationListener监听到竖屏时不再处理事件,waiting...
-->直到当用户把手机旋转为横屏状态之后,更改flag,使OrientationListener监听到竖屏时处理相应的事件
-->当用户再次旋转手机切换为竖屏之后,Activity即可自动切换为竖屏;

横屏点击切换竖屏理论同上;

  第三步,用户点击切换按钮之后进入横屏,此时就不响应监听到的竖屏处理事件,并且要等待到第四步用户把手机旋转为横屏状态之后再响应竖屏监听;这样定义似乎不太合理,但从用户的角度看,不可能用户点击了要进入横屏,却仍然把手机给竖屏方向拿着;

  最后,当不需要监听屏幕方向的时候,需要调用OrientationListener.disable()关闭监听器;

小记录一下相关知识01/07/2014

    private int getScreenRotation() {
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
try {
Method m = display.getClass().getDeclaredMethod("getRotation");
return (Integer) m.invoke(display);
} catch (Exception e) {
return Surface.ROTATION_0;
}
} private int getScreenOrientation() {
switch (getScreenRotation()) {
case Surface.ROTATION_0:
return ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
case Surface.ROTATION_90:
return ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
case Surface.ROTATION_180:
return (Build.VERSION.SDK_INT >= 8 ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
: ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
case Surface.ROTATION_270:
return (Build.VERSION.SDK_INT >= 8 ? ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
: ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
default:
return 0;
}
}

Android 解决setRequestedOrientation之后手机屏幕的旋转不触发onConfigurationChanged方法的更多相关文章

  1. Android程序对不同手机屏幕分辨率自适应的方法

    相信各位Android开发爱好者都知道,由于OEM之间的竞争,各种Android操作系统的手机简直就是琳琅满目,屏幕分辨率的差异可想而知.目前比较主流的有WVGA=800x480,HVGA=480x3 ...

  2. Android针对不同的手机屏幕大小设计图片资源与编码

    注:本文转载于:http://blog.csdn.net/welovesunflower/article/details/7930248 一些术语 Screen Size 屏幕尺寸: 实际的物理尺寸, ...

  3. Android应用不随手机屏幕旋转的方法

    在主配置文件里面.在需要设置的activity项后面加上 android:screenOrientation="portrait",这个activity就保持竖屏显示了:在每个ac ...

  4. Android中如何让手机屏幕不待机

    在Android中,申请WakeLock可以让你的进程持续执行即使手机进入睡眠模式,比较实用的是比如后台有网络功能,可以保证操作持续进行. 方法: 在操作之前加入 PowerManager pm = ...

  5. android 解决 多品牌手机拍照问题,尤其是小米手机

    先上个图吧 .点击头像弹出下面对话框,然后直接上代码. 头像是自定义控件实现的圆形头像,当然就目前而言 想要实现 圆形头像的资料太多了,随便找个就行 <com.kuibu.jucai.widge ...

  6. iOS学习之自定义视图时,在屏幕发生旋转时触发重新布局方法

    如果要对自定义的视图在屏幕旋转时重新布局,则在自定义视图中定义以下触发方法: -(void)layoutSubviews { [super layoutSubviews]; //1.获取到屏幕旋转的方 ...

  7. Android手机屏幕投射到电脑神器Vysor

    做android开发的,经常要把手机屏幕投射到电脑,用来演示.普遍的解决方案是360或者豌豆荚的演示功能,缺点是延迟非常厉害,大概有3秒左右,非常影响演示效果.以下介绍Vysor,几乎0延迟,能与手机 ...

  8. 【WP开发】在手机屏幕点亮时播放声音

    今天说的内容有点流氓,请诸君在开发应用时谨慎使用. 那么,这活儿到底有多流氓呢? 先介绍一下要实现的功能:当用户按电源键(也可以是双击屏幕)点亮手机的屏幕时播放一下短音乐,而且应用程序可以不在前台运行 ...

  9. 解决Android手机 屏幕横竖屏切换

    Android中当屏幕横竖屏切换时,Activity的生命周期是重新加载(说明当前的Activity给销毁了,但又重新执行加载),怎么使屏幕横竖屏切换时,当前的Activity不销毁呢? 1. 在An ...

随机推荐

  1. 百度地图标注及结合ECharts图谱数据可视化

    本示例中根据企业位置经纬度,在页面右侧百度地图中标注企业名称.同时页面左侧ECharts图谱饼状图用于统计企业行业与注册资本.当右侧百度地图缩放拖拽,左侧ECharts图谱根据右侧地图上出现的企业动态 ...

  2. linux部署MantisBT(三)部署MantisBT

    三.部署MantisBT 1.下载MantisBT https://www.mantisbt.org/download.php 2.将MantisBT安装包放在/apache/htdocs下并重命名为 ...

  3. python函数参数默认值及重要警告

    最有用的形式是对一个或多个参数指定一个默认值.这样创建的函数,可以用比定义时允许的更少的参数调用,比如: def ask_ok(prompt, retries=4, reminder='Please ...

  4. 博客美化—添加萌萌的live2D看板娘(不能再简单了)

    看着很多博客都有live2D的萌萌哒看板娘,我闲着有空说干就干. 从参考博客的附件中下载资源文件 waifu.css waifu-tips.js live2d.js flat-ui.min.css// ...

  5. [SHELL]shell中的数学运算

    一,expr  太麻烦,看的脑壳疼 二,使用方括号 !!!! bash shell用这种方法只支持整数运算,z shell倒是支持浮点型运算 var_1= var_2= var_3= my_var_1 ...

  6. 【20180807模拟测试】T2 box

    [问题描述] 有个桌子长 R 宽 C,被分为 R*C 个小方格.其中,一些方格上有箱子,一些方格上有按 钮,一些方格上有障碍物,一些方格上是空地.现在有个任务,需要把所有箱子推到这些按 钮上面.箱子有 ...

  7. Python数据分析实战-Boston Public Schools GEO数据分析-Part1

    项目目标: Boston Public Schools Geo数据是来自于Boston地区的公共学校的数据,具体描述了学校的坐标,名字,类型等.基于此数据,我们可以学习一些基本的Python数据分析的 ...

  8. 如何在etherscan提交代币官方信息

    https://ethlinkersupport.zendesk.com/hc/zh-cn/articles/360001334992-%E5%A6%82%E4%BD%95%E5%9C%A8ether ...

  9. 从SDN鼻祖Nicira到VMware NSX 网络虚拟化平台的简单探讨

    以前的大二层技术,一般是在物理网络底层使用IS-IS路由技术,再在此基础之上,实现数据中心网络的二层扩展,如公有的Trill.SPB技术和Cisco私有的OTV.Fabricpath技术:前沿一些的网 ...

  10. Python中变量名里面的下划线

    1 变量名前后都有两个下划线(__X__),表示是系统级变量: 2 变量名前只有一个下划线(_X),表示该变量不是由from module import *导入进来的: 3 变量名前有两个下划线(__ ...