【发布时间】:2011-06-01 00:27:03
【问题描述】:
我有一个显示相机预览的活动,因此只需将其设置为横向。在底部(不管设备旋转)我想显示一个文本视图。我正在使用 OrientationEventListener 从其自然位置给出设备的方向。我可以实现一个在纵向默认设备上运行良好的解决方案,但要使其在横向默认设备上也能正常工作,我需要注意在这样的设备上运行。因此问题是如何检查它?
【问题讨论】:
标签: android
我有一个显示相机预览的活动,因此只需将其设置为横向。在底部(不管设备旋转)我想显示一个文本视图。我正在使用 OrientationEventListener 从其自然位置给出设备的方向。我可以实现一个在纵向默认设备上运行良好的解决方案,但要使其在横向默认设备上也能正常工作,我需要注意在这样的设备上运行。因此问题是如何检查它?
【问题讨论】:
标签: android
【讨论】:
这是我一直在使用的:
/**
* returns the natural orientation of the device: Configuration.ORIENTATION_LANDSCAPE or Configuration.ORIENTATION_PORTRAIT .<br/>
* The result should be consistent no matter the orientation of the device
*/
public static int getScreenNaturalOrientation(@NonNull final Context context) {
//based on : http://stackoverflow.com/a/9888357/878126
final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Configuration config = context.getResources().getConfiguration();
final int rotation = windowManager.getDefaultDisplay().getRotation();
if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT))
return Configuration.ORIENTATION_LANDSCAPE;
else
return Configuration.ORIENTATION_PORTRAIT;
}
您也可以像这样获得自然分辨率:
/**
* returns the natural screen size (in pixels). The result should be consistent no matter the orientation of the device
*/
public static
@NonNull
Point getScreenNaturalSize(@NonNull final Context context) {
if (sNaturalScreenSize != null)
return sNaturalScreenSize;
final int screenNaturalOrientation = getScreenNaturalOrientation(context);
final DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
final int currentOrientation = context.getResources().getConfiguration().orientation;
if (currentOrientation == screenNaturalOrientation)
return sNaturalScreenSize = new Point(displayMetrics.widthPixels, displayMetrics.heightPixels);
//noinspection SuspiciousNameCombination
return sNaturalScreenSize = new Point(displayMetrics.heightPixels, displayMetrics.widthPixels);
}
【讨论】:
对于 Xamarin 开发人员,这是 C# 中此检查的一个版本:
var orientation = ContextHelper.Current.Resources.Configuration.Orientation;
if (orientation == Android.Content.Res.Orientation.Undefined)
{
//unknown, you can provide special handling for this case
}
var isLandscape = false;
var rotation = windowManager.DefaultDisplay.Rotation;
switch (rotation)
{
case SurfaceOrientation.Rotation0:
case SurfaceOrientation.Rotation180:
isLandscape = orientation == Android.Content.Res.Orientation.Landscape;
break;
default:
isLandscape = orientation == Android.Content.Res.Orientation.Portrait;
break;
}
【讨论】:
您可以使用旋转和方向来定义。无需使用传感器或任何侦听器,只需调用 isDefaultLandscape 方法即可。
private boolean isDefaultLandscape(final Context context)
{
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int rotation = display.getRotation();
int orientation = context.getResources().getConfiguration().orientation;
switch (rotation)
{
case Surface.ROTATION_180:
case Surface.ROTATION_0:
{
return orientation == Configuration.ORIENTATION_LANDSCAPE;
}
default:
{
return orientation == Configuration.ORIENTATION_PORTRAIT;
}
}
}
【讨论】:
解决这个问题很简单
int orient=this.getResources().getConfiguration().orientation;
如果它返回 1 或 2
1 是纵向 2是风景
【讨论】:
public static boolean isDeviceDefaultOrientationLandscape(Activity a) {
WindowManager windowManager = (WindowManager) a.getSystemService(Context.WINDOW_SERVICE);
Configuration config = a.getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
boolean defaultLandsacpeAndIsInLandscape = (rotation == Surface.ROTATION_0 ||
rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE;
boolean defaultLandscapeAndIsInPortrait = (rotation == Surface.ROTATION_90 ||
rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT;
return defaultLandsacpeAndIsInLandscape || defaultLandscapeAndIsInPortrait;
}
【讨论】:
这个方法可以帮助:--
public int getDeviceDefaultOrientation() {
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Configuration config = getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
if ( ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
return Configuration.ORIENTATION_LANDSCAPE;
} else {
return Configuration.ORIENTATION_PORTRAIT;
}
}
【讨论】:
config.orientation != Configuration.ORIENTATION_UNDEFINED?
orientation 和 getRotation 在某些时间点不同步。
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
感谢上面diyism的出色回答,我还添加了检查实际方向位置的逻辑(横向右侧,纵向,横向左侧,纵向翻转): 代码如下:
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
//The coordinate-system is defined relative to the screen of the phone in its default orientation
int orientation = 0;
float roll=0;
float pitch=0;
switch (getWindowManager().getDefaultDisplay().getRotation()) {
case Surface.ROTATION_0:
roll=event.values[2];
pitch=event.values[1];
break;
case Surface.ROTATION_90:
roll=event.values[1];
pitch=-event.values[2];
break;
case Surface.ROTATION_180:
roll=-event.values[2];
pitch=-event.values[1];
break;
case Surface.ROTATION_270:
roll=-event.values[1];
pitch=event.values[2];
break;
}
if (pitch >= -45 && pitch < 45 && roll >= 45)
orientation = 0;
else if (pitch < -45 && roll >= -45 && roll < 45)
orientation = 1;
else if (pitch >= -45 && pitch < 45 && roll < -45)
orientation = 2;
else if (pitch >= 45 && roll >= -45 && roll < 45 )
orientation = 3;
if (m_nOrientation != orientation) { //orientation changed event
m_Inst.Debug(LOG_TAG,"onSensorChanged: orientation:" + orientation);
m_nOrientation = orientation;
// fire event for new notification, or update your interface here
}
}
这段代码也贴在这里:http://www.pocketmagic.net/?p=2847
【讨论】:
可以使用Display.getOrientation() 或Display.getRotation() 来完成(API 级别>= 8)。
【讨论】:
我的解决方案(在 HTC 渴望和三星 Galaxy Tab 10.1 测试):
private class compass_listener implements SensorEventListener
{public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event)
{float roll=0;
float pitch=0;
switch (((Activity)context).getWindowManager().getDefaultDisplay().getRotation())
{case Surface.ROTATION_0:
roll=event.values[2];
pitch=event.values[1];
break;
case Surface.ROTATION_90:
roll=event.values[1];
pitch=-event.values[2];
break;
case Surface.ROTATION_180:
roll=-event.values[2];
pitch=-event.values[1];
break;
case Surface.ROTATION_270:
roll=-event.values[1];
pitch=event.values[2];
break;
}
JSONObject json=new JSONObject();
try
{json.put("roll", roll);
json.put("pitch", pitch);
json.put("azimuth", event.values[0]);
}
catch (JSONException e)
{throw new RuntimeException(e);
}
java_2_js(webview, "intent_compass_change", json);
}
}
【讨论】:
这是我的解决方案:
public class ActivityOrientationTest extends Activity {
private static final String TAG = "ActivityOrientationTest";
private int mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
private TextView mTextView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView = (TextView)findViewById(R.id.text);
setDefaultOrientation();
}
private void setDefaultOrientation(){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
Display display;
display = getWindow().getWindowManager().getDefaultDisplay();
int rotation = display.getRotation();
int width = 0;
int height = 0;
switch (rotation) {
case Surface.ROTATION_0:
case Surface.ROTATION_180:
Log.i(TAG, "Rotation is: 0 or 180");
width = display.getWidth();
height = display.getHeight();
break;
case Surface.ROTATION_90:
case Surface.ROTATION_270:
Log.i(TAG, "Rotation is: 90 or 270");
width = display.getHeight();
height = display.getWidth();
break;
default:
break;
}
if(width > height){
Log.i(TAG, "Natural Orientation is landscape");
mTextView.setText("Natural Orientation is landscape");
mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
} else {
Log.i(TAG, "Natural Orientation is portrait");
mNaturalOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
mTextView.setText("Natural Orientation is portrait");
}
setRequestedOrientation(mNaturalOrientation);
}
Display.getRotation() 仅在 API 级别 8 或更高级别中受支持,因此如果您需要支持旧设备,则需要调用 Display.getOrientation()。
【讨论】:
经过数小时试图弄清楚这一点。这是不可能的。但是,您可以做的最接近的事情是将方向设置为“NOSENSOR”
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
这会将您的应用程序设置为设备的自然方向。此时您可以使用 DisplayMetrics 类获取显示器的高度和宽度,并计算您是横向还是纵向。在你确定它是横向还是纵向之后,你就可以这样做了
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_XXXXX);
其中 XXXX 是横向或纵向。
如果你有滑出式键盘,这样做可能不起作用。
【讨论】:
SCREEN_ORIENTATION_UNSPECIFIED 允许用户启用自动屏幕旋转或系统USER_ROTATION 设置值更改来覆盖活动方向。
好吧,您可以了解@Urboss 所说的当前方向。当然,您无法以这种方式获得布局(横向/纵向),因此您必须获取屏幕宽度/高度以检查当前位置(无论是否更改,但您已经检查过;))位置是横向或肖像:
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
wPix = dm.widthPixels;
hPix = dm.heightPixels;
(因此,如果旋转为 0 并且您使用上述矩阵获得横向,则您的设备默认为横向。如果旋转为 90 度并且您为纵向,则默认也是横向,依此类推)
【讨论】:
@Urboss,它不能。您需要首先知道设备的默认方向,因为这两种方法都基于它返回更改(我的意思是,如果默认为纵向,则您要查找的结果将是 1 或 ROTATE_90 - 所以它是横向-,但是, 如果默认为横向,则结果为 0)。
据我所知,找到设备的默认方向并非易事:(
任何人都可以对这个主题有所了解吗?
【讨论】: