【Android】android开发---实现屏幕旋转的两种方法
16lz
2022-05-22
前言
为实现播放器全屏竖屏切换,还可锁住横屏,解锁后又可以跟随传感器变化。
正文
方法一:通过控制android:screenOrientation属性控制横竖屏
1.使用 SCREEN_ORIENTATION_SENSOR 参数设置其可以跟随传感器
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
2.当全屏时点击锁住,使用 SCREEN_ORIENTATION_LOCKED 锁住屏幕
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
3.点击解锁,再设置为跟随传感器
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
这时候就有一个新的问题给大家,如果要实现点击播放器放大按钮,变成全屏,全屏后还可以跟随传感器变化,大家会怎么做?
你可能会想使用 SCREEN_ORIENTATION_LANDSCAPE 使其横屏,接着设置为跟随传感器 ,也就是以下两行代码。
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
可是结果总是这么不尽如人意。点击"开启旋转"会发现旋转成横屏后会自动又旋回竖屏(因为传感器是读取你现在的手机状态),显而易见,这种体验很不好。
所以我们就有了方法二
方法二:通过监听屏幕旋转角度控制横竖屏
前期配置:
AndroidManifest.xml
android:configChanges="orientation|screenSize">
使其不会重新调用onCreate方法,而是调用onConfigurationChanged,避免出现奇怪的问题。
基础类:
别看代码多,直接拷去用就好
package com.aliyun.vodplayerview.utils;import android.content.Context;import android.hardware.SensorManager;import android.view.OrientationEventListener;/* * Copyright (C) 2010-2018 Alibaba Group Holding Limited. *//** * 屏幕方向监听类 */public class OrientationWatchDog { private static final String TAG = OrientationWatchDog.class.getSimpleName(); private Context mContext; //系统的屏幕方向改变监听 private OrientationEventListener mLandOrientationListener; //对外的设置的监听 private OnOrientationListener mOrientationListener; //上次屏幕的方向 private Orientation mLastOrientation = Orientation.Port; /** * 屏幕方向 */ private enum Orientation { /** * 竖屏 */ Port, /** * 横屏 */ Land } public OrientationWatchDog(Context context) { mContext = context.getApplicationContext(); } /** * 开始监听 */ public void startWatch() { VcPlayerLog.e(TAG, "startWatch"); if (mLandOrientationListener == null) { mLandOrientationListener = new OrientationEventListener(mContext, SensorManager.SENSOR_DELAY_NORMAL) { @Override public void onOrientationChanged(int orientation) { //这里的|| 和&& 不能弄错!! //根据手机的方向角度计算。在90和180度上下10度的时候认为横屏了。 //竖屏类似。 boolean isLand = (orientation < 100 && orientation > 80) || (orientation < 280 && orientation > 260); boolean isPort = (orientation < 10 || orientation > 350) || (orientation < 190 && orientation > 170); if (isLand) { if (mOrientationListener != null) { mOrientationListener.changedToLandScape(mLastOrientation == Orientation.Port); } mLastOrientation = Orientation.Land; } else if (isPort) { if (mOrientationListener != null) { mOrientationListener.changedToPortrait(mLastOrientation == Orientation.Land); } mLastOrientation = Orientation.Port; } } }; } mLandOrientationListener.enable(); } /** * 结束监听 */ public void stopWatch() { if (mLandOrientationListener != null) { mLandOrientationListener.disable(); } } /** * 销毁监听 */ public void destroy() { stopWatch(); mLandOrientationListener = null; } /** * 屏幕方向变化事件 */ public interface OnOrientationListener { /** * 变为Land * * @param fromPort 是否是从竖屏变过来的 */ void changedToLandScape(boolean fromPort); /** * 变为Port * * @param fromLand 是否是从横屏变过来的 */ void changedToPortrait(boolean fromLand); } /** * 设置屏幕方向变化事件 * * @param l 事件监听 */ public void setOnOrientationListener(OnOrientationListener l) { mOrientationListener = l; }}
使用方法:
1.实现OnOrientationListener接口,将旋转时需要实现的操作放进去
界面:
MainAcitivity:
package com.eddie.screenorientationdemo;import android.content.pm.ActivityInfo;import android.content.res.Configuration;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.TextView;import com.eddie.screenorientation.OrientationWatchDog;public class MainActivity extends AppCompatActivity implements OrientationWatchDog.OnOrientationListener { TextView mTvStartSpan; TextView mTvStopSpan; /** * 监听类 */ private OrientationWatchDog mOrientationWatchDog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTvStartSpan = findViewById(R.id.tv_start_span); mTvStopSpan = findViewById(R.id.tv_stop_span); initOrientationWatchdog(); mTvStartSpan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mOrientationWatchDog != null) { mOrientationWatchDog.startWatch(); } } }); mTvStopSpan.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mOrientationWatchDog != null) { mOrientationWatchDog.stopWatch(); } } }); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); } @Override public void changedToLandScape(boolean fromPort) { //如果不是从竖屏变过来,也就是一直是横屏的时候,就不用操作了 if (!fromPort) { return; } this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } @Override public void changedToPortrait(boolean fromLand) { //如果没有转到过横屏,就不让他转了。防止竖屏的时候点横屏之后,又立即转回来的现象 if (!fromLand) { return; } this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } /** * 初始化屏幕方向监听器。用来监听屏幕方向。结果通过OrientationListener回调出去。 */ private void initOrientationWatchdog() { mOrientationWatchDog = new OrientationWatchDog(this); mOrientationWatchDog.setOnOrientationListener(this); }}
2.初始化监听器
/** * 初始化屏幕方向旋转。用来监听屏幕方向。结果通过OrientationListener回调出去。 */ private void initOrientationWatchdog() { final Context context = getContext(); mOrientationWatchDog = new OrientationWatchDog(context); mOrientationWatchDog.setOnOrientationListener(new InnerOrientationListener(this)); }
3.在你需要跟随传感器变化的地方,开启监听器
if (mOrientationWatchDog != null) { mOrientationWatchDog.startWatch();}
4.别忘了在不使用的时候关闭监听器
if (mOrientationWatchDog != null) { mOrientationWatchDog.stopWatch();}
源码: github
借鉴阿里云播放器源码
更多相关文章
- Android(安卓)加速度传感器(G-Sensor)
- Android(安卓)屏幕的旋转 onConfigurationChanged方法
- Android-基本控件(SeekBar 可拖动 滚动条的使用)
- android 当环境配置发生变化 例如语言 屏幕变化
- Android监听来电和去电的实现方法
- Android初级教程小案例之单选框RadioGroup与复选框CheckBox
- Android(安卓)电子罗盘--指南针(方向传感器的应用)
- Android打开WLAN开关的广播状态监听
- Android软键盘弹出,界面整体上移的问题