setRequestedOrientation,但仍根据传感器改变
setRequestedOrientation, but still change according to sensor
我想在处理屏幕方向方面模拟 youtube 视频观看行为。
用例:
p1。当用户按下最大化 -> activity 总是进入横向
p2。当用户按下最小化 -> activity 总是进入纵向
p3。当用户旋转设备时 -> 即使之前应用了 p1 或 p2,屏幕方向也应相应改变。
目前我使用:
@Override
public void onClick(View view) {
if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
然而,这会永久锁定方向并且失败 p3。
经过一段时间的尝试,我找到了正确的解决方案。
首先 - 问题是 android 在调用 setRequestedOrientation 后锁定屏幕,你不能混合使用两者,唯一的办法就是手动完成所有操作。
方法如下:
class PlayerOrientationListener extends OrientationEventListener {
PlayerOrientationListener() {
super(VideoPlayerActivity.this);
}
@Override
public void onOrientationChanged(int orientation) {
int threshold = 5;
if (Math.abs(orientation - 0) < threshold) orientation = 0;
else if (Math.abs(orientation - 90) < threshold) orientation = 90;
else if (Math.abs(orientation - 180) < threshold) orientation = 180;
else if (Math.abs(orientation - 270) < threshold) orientation = 270;
switch (orientation) {
case 0:
if (!orientationLandscapeLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
orientationPortraitLocked = false;
}
break;
case 90:
if (!orientationPortraitLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
orientationLandscapeLocked = false;
}
break;
case 180:
if (!orientationLandscapeLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
orientationPortraitLocked = false;
}
break;
case 270:
if (!orientationPortraitLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
orientationLandscapeLocked = false;
}
break;
}
}
}
和activity代码:
View.OnClickListener onExpandClick = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
orientationLandscapeLocked = true;
orientationPortraitLocked = false;
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
orientationPortraitLocked = true;
orientationLandscapeLocked = false;
}
}
};
btnExpandVideo.setOnClickListener(onExpandClick);
orientationListener = new PlayerOrientationListener();
orientationListener.enable();
@Yuriy 的回答对我来说非常有用,这里是在 Kotlin 中进行了一些小的修改,以便它可以存在于一个单独的文件中:
class PlayerOrientationListener(val activity: Activity?) : OrientationEventListener(activity) {
companion object {
private const val ROT_THRESHOLD = 5
private const val ROT_0 = 0
private const val ROT_90 = 90
private const val ROT_180 = 180
private const val ROT_270 = 270
}
private var orientationLockedPortrait = false
private var orientationLockedLandscape = false
fun lockLandscape() {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
orientationLockedLandscape = true
orientationLockedPortrait = false
}
fun lockPortrait() {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
orientationLockedPortrait = true
orientationLockedLandscape = false
}
override fun onOrientationChanged(orientation: Int) {
if (orientation == ORIENTATION_UNKNOWN) {
return
}
val rotation: Int =
when {
Math.abs(orientation - ROT_0) < ROT_THRESHOLD -> ROT_0
Math.abs(orientation - ROT_90) < ROT_THRESHOLD -> ROT_90
Math.abs(orientation - ROT_180) < ROT_THRESHOLD -> ROT_180
Math.abs(orientation - ROT_270) < ROT_THRESHOLD -> ROT_270
else -> ORIENTATION_UNKNOWN
}
when (rotation) {
ROT_0 -> if (!orientationLockedLandscape) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
orientationLockedPortrait = false
}
ROT_90 -> if (!orientationLockedPortrait) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
orientationLockedLandscape = false
}
ROT_180 -> if (!orientationLockedLandscape) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
orientationLockedPortrait = false
}
ROT_270 -> if (!orientationLockedPortrait) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
orientationLockedLandscape = false
}
}
}
}
然后在你的片段中,像这样:
val orientationListener = PlayerOrientationListener(activity)
orientationListener.enable()
menuItemMaximize?.setOnMenuItemClickListener {
orientationListener.lockLandscape()
true
}
menuItemMinimize?.setOnMenuItemClickListener {
orientationListener.lockPortrait()
true
}
我想在处理屏幕方向方面模拟 youtube 视频观看行为。
用例:
p1。当用户按下最大化 -> activity 总是进入横向
p2。当用户按下最小化 -> activity 总是进入纵向
p3。当用户旋转设备时 -> 即使之前应用了 p1 或 p2,屏幕方向也应相应改变。
目前我使用:
@Override
public void onClick(View view) {
if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
然而,这会永久锁定方向并且失败 p3。
经过一段时间的尝试,我找到了正确的解决方案。 首先 - 问题是 android 在调用 setRequestedOrientation 后锁定屏幕,你不能混合使用两者,唯一的办法就是手动完成所有操作。
方法如下:
class PlayerOrientationListener extends OrientationEventListener {
PlayerOrientationListener() {
super(VideoPlayerActivity.this);
}
@Override
public void onOrientationChanged(int orientation) {
int threshold = 5;
if (Math.abs(orientation - 0) < threshold) orientation = 0;
else if (Math.abs(orientation - 90) < threshold) orientation = 90;
else if (Math.abs(orientation - 180) < threshold) orientation = 180;
else if (Math.abs(orientation - 270) < threshold) orientation = 270;
switch (orientation) {
case 0:
if (!orientationLandscapeLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
orientationPortraitLocked = false;
}
break;
case 90:
if (!orientationPortraitLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
orientationLandscapeLocked = false;
}
break;
case 180:
if (!orientationLandscapeLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT);
orientationPortraitLocked = false;
}
break;
case 270:
if (!orientationPortraitLocked) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
orientationLandscapeLocked = false;
}
break;
}
}
}
和activity代码:
View.OnClickListener onExpandClick = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
orientationLandscapeLocked = true;
orientationPortraitLocked = false;
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
orientationPortraitLocked = true;
orientationLandscapeLocked = false;
}
}
};
btnExpandVideo.setOnClickListener(onExpandClick);
orientationListener = new PlayerOrientationListener();
orientationListener.enable();
@Yuriy 的回答对我来说非常有用,这里是在 Kotlin 中进行了一些小的修改,以便它可以存在于一个单独的文件中:
class PlayerOrientationListener(val activity: Activity?) : OrientationEventListener(activity) {
companion object {
private const val ROT_THRESHOLD = 5
private const val ROT_0 = 0
private const val ROT_90 = 90
private const val ROT_180 = 180
private const val ROT_270 = 270
}
private var orientationLockedPortrait = false
private var orientationLockedLandscape = false
fun lockLandscape() {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
orientationLockedLandscape = true
orientationLockedPortrait = false
}
fun lockPortrait() {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
orientationLockedPortrait = true
orientationLockedLandscape = false
}
override fun onOrientationChanged(orientation: Int) {
if (orientation == ORIENTATION_UNKNOWN) {
return
}
val rotation: Int =
when {
Math.abs(orientation - ROT_0) < ROT_THRESHOLD -> ROT_0
Math.abs(orientation - ROT_90) < ROT_THRESHOLD -> ROT_90
Math.abs(orientation - ROT_180) < ROT_THRESHOLD -> ROT_180
Math.abs(orientation - ROT_270) < ROT_THRESHOLD -> ROT_270
else -> ORIENTATION_UNKNOWN
}
when (rotation) {
ROT_0 -> if (!orientationLockedLandscape) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
orientationLockedPortrait = false
}
ROT_90 -> if (!orientationLockedPortrait) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
orientationLockedLandscape = false
}
ROT_180 -> if (!orientationLockedLandscape) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
orientationLockedPortrait = false
}
ROT_270 -> if (!orientationLockedPortrait) {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
orientationLockedLandscape = false
}
}
}
}
然后在你的片段中,像这样:
val orientationListener = PlayerOrientationListener(activity)
orientationListener.enable()
menuItemMaximize?.setOnMenuItemClickListener {
orientationListener.lockLandscape()
true
}
menuItemMinimize?.setOnMenuItemClickListener {
orientationListener.lockPortrait()
true
}