为实现播放器全屏竖屏切换,还可锁住横屏,解锁后又可以跟随传感器变化。
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
借鉴阿里云播放器源码