Android 指定 requestedOrientation 时检测设备方向
Android detect device orientation when requestedOrientation is specified
我正在构建一个视频流应用程序。它具有 Youtube 风格的布局,纵向布局在顶部显示视频,在底部显示其他内容列表。该应用可以通过旋转设备或单击按钮以横屏方式全屏显示视频。
现在,如果我将 phone 旋转为横向,然后将其旋转回纵向,布局将按预期返回纵向。相反,如果我单击按钮强制进入纵向模式,将设备横向旋转以观看视频,然后将其旋转回纵向,则布局仍然停留在横向。
清单中我的 activity:
<activity
android:name="MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:label="@string/app_name"
android:launchMode="singleTask" />
我的按钮点击:
mChangeOrientButton.setOnClickListener((OnClickListener)(new OnClickListener() {
public final void onClick(View it) {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
}));
我的 onConfigurationChanged 方法(我注意到如果我单击按钮然后旋转 phone,则不再调用此方法,只要 requestedOrientation 保持设置为不同于 UNSPECIFIED 的设置):
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
{
// Set the layout for landscape mode
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// Set the layout for portrait mode
}
}
我尝试将 requestedOrientation 重置为 UNSPECIFIED,如下所示:
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
{
// Set the layout for landscape mode
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// Set the layout for portrait mode
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
但它不起作用,因为方向被强制从纵向变为横向,然后在用户有机会将其旋转为横向之前再次设置为未指定,因此它立即再次变为纵向并且似乎它什么都不做。
好的,我在 this other answer 中找到了解决方案。它对我不起作用,所以我稍微修改了一下:
MainActivity
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private SensorManager mSensorManager;
private Sensor mOrientation;
private boolean mIsForcingOrientation = false;
float value_0 = -10000;
float value_1 = -10000;
private SensorEventListener mOrientationSensorListener = new SensorEventListener() {
int orientation = -1;
@Override
public void onSensorChanged(SensorEvent event) {
int value ;
if(value_0 == event.values[0] && value_1==event.values[1]){
return;
}
if (value_0 < 0 && event.values[0] > 0){
// Setting rotation to 270°: Landscape reverse
value = Surface.ROTATION_270;
} else if (value_0 > 0 && event.values[0] < 0){
// Setting rotation to 90°: Landscape
value = Surface.ROTATION_90;
} else if (value_1 < 0 && event.values[1] > 0){
// Setting rotation to 180°: Portrait reverse
value = Surface.ROTATION_180;
} else if (value_1 > 0 && event.values[1] < 0){
// Setting rotation to 0°: Portrait
value = Surface.ROTATION_0
} else {
value = orientation;
}
if (orientation != value) {
if((requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && (value == Surface.ROTATION_90 || value == Surface.ROTATION_270) ) ||
(requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && (value == Surface.ROTATION_0 || value == Surface.ROTATION_180) ) ){
isForcingOrientation = false;
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
}
value_0=event.values[0];
value_1=event.values[1];
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get sensor manager
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Get the default sensor of specified type
mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mChangeOrientButton.setOnClickListener((OnClickListener)(new OnClickListener() {
public final void onClick(View it) {
mIsForcingOrientation = true;
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
}));
}
@Override
protected void onResume() {
super.onResume();
if (mOrientation != null) {
mSensorManager.registerListener(mOrientationSensorListener, mOrientation,
SensorManager.SENSOR_DELAY_GAME);
}
}
@Override
protected void onPause() {
super.onPause();
if (mOrientation != null) {
mSensorManager.unregisterListener(mOrientationSensorListener);
}
}
}
我正在构建一个视频流应用程序。它具有 Youtube 风格的布局,纵向布局在顶部显示视频,在底部显示其他内容列表。该应用可以通过旋转设备或单击按钮以横屏方式全屏显示视频。
现在,如果我将 phone 旋转为横向,然后将其旋转回纵向,布局将按预期返回纵向。相反,如果我单击按钮强制进入纵向模式,将设备横向旋转以观看视频,然后将其旋转回纵向,则布局仍然停留在横向。
清单中我的 activity:
<activity
android:name="MyActivity"
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
android:label="@string/app_name"
android:launchMode="singleTask" />
我的按钮点击:
mChangeOrientButton.setOnClickListener((OnClickListener)(new OnClickListener() {
public final void onClick(View it) {
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
}));
我的 onConfigurationChanged 方法(我注意到如果我单击按钮然后旋转 phone,则不再调用此方法,只要 requestedOrientation 保持设置为不同于 UNSPECIFIED 的设置):
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
{
// Set the layout for landscape mode
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// Set the layout for portrait mode
}
}
我尝试将 requestedOrientation 重置为 UNSPECIFIED,如下所示:
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
{
// Set the layout for landscape mode
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
// Set the layout for portrait mode
}
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
但它不起作用,因为方向被强制从纵向变为横向,然后在用户有机会将其旋转为横向之前再次设置为未指定,因此它立即再次变为纵向并且似乎它什么都不做。
好的,我在 this other answer 中找到了解决方案。它对我不起作用,所以我稍微修改了一下:
MainActivity
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private SensorManager mSensorManager;
private Sensor mOrientation;
private boolean mIsForcingOrientation = false;
float value_0 = -10000;
float value_1 = -10000;
private SensorEventListener mOrientationSensorListener = new SensorEventListener() {
int orientation = -1;
@Override
public void onSensorChanged(SensorEvent event) {
int value ;
if(value_0 == event.values[0] && value_1==event.values[1]){
return;
}
if (value_0 < 0 && event.values[0] > 0){
// Setting rotation to 270°: Landscape reverse
value = Surface.ROTATION_270;
} else if (value_0 > 0 && event.values[0] < 0){
// Setting rotation to 90°: Landscape
value = Surface.ROTATION_90;
} else if (value_1 < 0 && event.values[1] > 0){
// Setting rotation to 180°: Portrait reverse
value = Surface.ROTATION_180;
} else if (value_1 > 0 && event.values[1] < 0){
// Setting rotation to 0°: Portrait
value = Surface.ROTATION_0
} else {
value = orientation;
}
if (orientation != value) {
if((requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT && (value == Surface.ROTATION_90 || value == Surface.ROTATION_270) ) ||
(requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE && (value == Surface.ROTATION_0 || value == Surface.ROTATION_180) ) ){
isForcingOrientation = false;
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
}
value_0=event.values[0];
value_1=event.values[1];
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get sensor manager
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// Get the default sensor of specified type
mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mChangeOrientButton.setOnClickListener((OnClickListener)(new OnClickListener() {
public final void onClick(View it) {
mIsForcingOrientation = true;
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
}
}));
}
@Override
protected void onResume() {
super.onResume();
if (mOrientation != null) {
mSensorManager.registerListener(mOrientationSensorListener, mOrientation,
SensorManager.SENSOR_DELAY_GAME);
}
}
@Override
protected void onPause() {
super.onPause();
if (mOrientation != null) {
mSensorManager.unregisterListener(mOrientationSensorListener);
}
}
}