我正在开发一个基于Android的移动应用程序,minSdkVersion=15
。我想支持平板电脑的两个方向,只支持智能手机的纵向。一切都像魅力一样工作,但我遇到了一个小错误,让我发疯。 当智能手机处于横向模式并且我尝试触发新的活动时,它会以横向模式打开一段时间,然后自动旋转为纵向。 我的每个活动都扩展了一个 GeneralActivity 类:
public class GeneralActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If smartphone lock orientation to portrait
if (!Helper.isTablet(this.getApplicationContext())){
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
}
我检测具有此功能的平板电脑:
public class Helper {
public static boolean isTablet(Context context){
Configuration config = context.getResources().getConfiguration()
return config.smallestScreenWidthDp >= 600;
}
}
我选择不在清单中指定android:screenOrientation
.xml因为这样我就可以支持平板电脑的所有界面方向。 我错过了什么吗?
编辑
我决定应用乔纳森回答中建议的最佳实践,但我描述的问题仍然存在。这是我在github上的回购:https://github.com/giacmarangoni/Android-Orientation-Test
我通过使用以下方法找到了解决此问题的正确方法:
android:screenOrientation="locked"
在清单中声明的具有此问题的每个活动中。
并继续以编程方式使用setRequestedOrientation()
来定义 onCreate() 方法中的横向还是纵向,
顺便说一句,在您的 GitHub 项目中,我只是更改了清单,添加了这样的方向locked
它终于起作用了:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.giacomomarangoni.orientationtest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="locked">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".OtherActivity"
android:screenOrientation="locked">
</activity>
</application>
</manifest>
希望它也能帮助你:)
我在Android N&O上遇到了同样的问题,并找到了解决方案。
我仍然在onCreate方法中使用setRequestOrientation,但是我已经为清单中的每个活动添加了以下内容:
android:screenOrientation="behind"
这可确保活动以与上一个活动相同的方向启动。之后的 setRequestOrientation 将覆盖它,但如果它与以前的活动相同,则作为用户,您不会看到任何更改。
这是使用资源和大小限定符的好方法。
把这个布尔资源放在res/值中作为布尔值.xml或者其他什么(文件名在这里无关紧要):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">true</bool>
</resources>
把这个放在res/values-sw600dp和res/values-xlarge中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="portrait_only">false</bool>
</resources>
有关在 Android Studio 中添加这些目录和文件的帮助,请参阅此补充解答。
然后,在活动的onCreate方法中,您可以执行以下操作:
if(getResources().getBoolean(R.bool.portrait_only)){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
在最小宽度方向上超过 600 dp 的设备,或在 Android 3.2 之前的设备(基本上是平板电脑)上超大的设备将像正常一样运行,基于传感器和用户锁定的旋转等。
来源:原答案
我有这个解决方案为我工作。 在清单中声明屏幕方向纵向
<activity android:name=".activities.MainActivity"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
然后在onCreate
的基本活动中调用 super.onCreate(如果设备是平板电脑)之前,将方向设置为未指定。
@Override
protected void onCreate(Bundle savedInstanceState) {
if (!getResources().getBoolean(R.bool.portrait_only)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
super.onCreate(savedInstanceState);
}
从文档中:
未指定: 未指定首选项:让系统决定最佳方向。这将是下面活动选择的方向,或者用户的首选方向(如果此活动是任务的底部)。如果用户通过设置显式关闭基于传感器的方向,则基于传感器的设备旋转将被忽略。如果不是,默认情况下将考虑基于传感器的方向,并且方向将根据用户旋转设备的方式而改变。
这对我有用,到目前为止,我还没有发现任何缺点。我只在模拟器中对此进行了测试,似乎该应用程序并没有像手机上的其他解决方案那样纵向启动,然后旋转。无论如何,我宁愿手机比平板电脑工作得更好,因为它们被更多地使用。
如果您发现此解决方案不起作用的任何内容,请与我联系!
我在Android N设备上也遇到了同样的问题。因此,为了支持平板电脑的两个方向和手机的纵向,我做了以下技巧:
-
为清单中的每个活动设置纵向。看起来很糟糕,但在这种情况下,屏幕不会自动旋转:
android:screenOrientation="portrait"
-
在基本活动集中:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (isTablet(){ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); } } protected boolean isTablet() { return getResources().getBoolean(R.bool.tablet); }
在您的基本活动中,您可以放置如下内容:
/* Device types. */
static int MOBILE_DEVICE = 0;
static int SEVEN_INCH_TABLET = 1;
static int TEN_INCH_TABLET = 2;
private static int deviceType = MOBILE_DEVICE;
private boolean deviceTypeDetermined = false;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
protected void onCreate(Bundle savedInstanceState) {
if ( ! deviceTypeDetermined) setDeviceType();
/* Screen rotation only for tablets. */
if (getDeviceType() < SEVEN_INCH_TABLET) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
lockScreenOrientation();
......
}
// ---------------------------------------------------------------------------------------------
static int getDeviceType() {
return deviceType;
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
private void setDeviceTypeDetermined() {
this.deviceTypeDetermined = true;
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
private void setDeviceType() {
/*
Let's invest on what kind of screen our APP is invited...
We only make a difference in 10", 7" tablets and the rest...
*/
Display mDisplay = getWindowManager().getDefaultDisplay();
Point mScreenResolution = new Point();
mDisplay.getRealSize(mScreenResolution);
int mWidthPixels = mScreenResolution.x;
int mHeightPixels = mScreenResolution.y;
DisplayMetrics mMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
float mWidthDpi = mMetrics.xdpi;
float mHeightDpi = mMetrics.ydpi;
float mWidthInches = mWidthPixels / mWidthDpi;
float mHeightInches = mHeightPixels / mHeightDpi;
double mDiagonalInches = Math.sqrt(
(mWidthInches * mWidthInches)
+ (mHeightInches * mHeightInches));
if (mDiagonalInches >= 9) {
/*
A tablet with 8" x 5" is called a 10", but it is in fact
9.43398". Interesting that this kind of things happens in
the world of informatics.... ;)
*/
MyBaseAppCompatActivity.deviceType = TEN_INCH_TABLET;
}
else if (mDiagonalInches >= 7) {
MyBaseAppCompatActivity.deviceType = SEVEN_INCH_TABLET;
}
else
{
MyBaseAppCompatActivity.deviceType = MOBILE_DEVICE;
}
setDeviceTypeDetermined();
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
void lockScreenOrientation() {
/* Screen rotation only for tablets. */
if (deviceType < SEVEN_INCH_TABLET ) return;
setRequestedOrientation(getResources().getConfiguration().orientation);
}
// ---------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------
void unlockScreenOrientation() {
/* Screen rotation only for tablets. */
if (deviceType < SEVEN_INCH_TABLET ) return;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
// ---------------------------------------------------------------------------------------------
在 onCreate 中的活动中:
// ---------------------------------------------------------------------------------------------
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
protected void onCreate(Bundle savedInstanceState) {
// -----------------------------------------------------------------------------------------
super.onCreate(savedInstanceState);
if (getDeviceType() >= SEVEN_INCH_TABLET) unlockScreenOrientation();
setContentView(R.layout.main_activity);
.........
// ---------------------------------------------------------------------------------------------
在 menifest 文件的所有活动标签中添加此行...
android:screenOrientation="portrait"