防止在 Android 上屏幕旋转

353

我有一个活动,因为我正在启动AsyncTask,所以希望防止其旋转屏幕,屏幕旋转会使其重新启动。

有没有一种方法可以告诉这个活动,“即使用户使劲晃动手机,也不要旋转屏幕”?


3
如何在Android中禁用屏幕旋转? 您可以在AndroidManifest.xml文件中的Activity标签中添加以下属性来禁用屏幕旋转:android:screenOrientation="portrait"这将使活动仅以竖直方向显示,并防止其随设备旋转而旋转。如果要禁用横向旋转,将“portrait”更改为“landscape”。但是,请注意,如果您的应用需要在不同方向下提供不同的布局或行为,则不应使用此方法。 - Dan Lew
11
你可以处理屏幕方向的变化以及异步任务。阻止屏幕方向的变化只是一种懒惰的解决方法。而且很容易在屏幕方向改变时保持异步任务的存活状态 :) - Romain Guy
http://clamernotes.blogspot.com/2011/04/disable-screen-rotation-at-runtime-on.html - lexis
73
罗曼,提供一些解决方案或代码会更有帮助,而不仅仅是断言“有一个解决方案,而且它并不难”。 - Peter vdL
7
你可以使用 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); 这行代码来锁定屏幕方向。 - mcy
17个回答

529
添加。
android:screenOrientation="portrait" 
或者
 android:screenOrientation="landscape" 

在清单文件中添加<activity>元素/元素组,即可完成。


104
请注意,这只是在你的应用程序中隐藏错误,使用户更不可能遇到它。但是他们仍然会出现。任何配置更改都可能导致您的活动重新启动。您确实需要正确编写活动以处理异步任务在重新启动时的情况。 - hackbod
1
在某种情况下,这对我没有起作用。 我已经在打开应用程序之前将屏幕设为横向。 当我打开应用程序时,屏幕旋转到纵向,并导致第二个调用asynctask。 - user522559
2
你需要将设置调整为“在竖屏模式下打开”“始终保持竖屏模式”。只做其中一个是没有意义的。 - Carol
1
@hackbod,不管怎样,这是“android app prevent screen rotation”的谷歌搜索排名第一的结果,我的需求与异步任务无关。 - chiliNUT
7
我们应该如何正确书写我们的活动以应对这个问题? - user41805
显示剩余6条评论

133
您可以按照以下逻辑来防止屏幕自动旋转,同时您的AsyncTask正在运行:
  1. 使用getRequestedOrientation()将当前屏幕方向存储在您的活动中。
  2. 使用setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR)禁用自动屏幕方向。
  3. 运行/执行您的AsyncTask
  4. 在您的AsyncTask结束时,使用setRequestedOrientation(oldOrientation)恢复先前的方向状态。
请注意,有几种方式可以在AsyncTask内部访问运行在UI线程上的Activity属性。 您可以将AsyncTask实现为内部类,或者您可以使用消息Handler来提醒您的Activity类。

9
比所选答案好多了。 - Matej
4
很好的想法 :) 你不需要存储当前屏幕方向,可以使用ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED。 - fligant
这太不可思议了,@emre,谢谢!它看起来“好得难以置信!”请注意有关此问题的大量讨论:https://dev59.com/t2865IYBdhLWcg3wa980 ... Android专家,这里有什么缺点吗?!再次感谢..非常感谢。 - Fattie
4
糟糕!!如果设备恰好处于横屏模式,这个根本不起作用。该死!太烂了 :O - Fattie
@Emre,这段代码在某些情况下无法正常工作。例如,如果用户在您的AsyncTask开始和结束之间更改了方向,则会保存和恢复错误的方向。 - Pacerier

35

The easiest way I found to do this was to put

this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

在onCreate中,紧接着

setContentView(R.layout.activity_main);

so...

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

按预期工作 - Amir

28
在您的清单文件中,对于每个要锁定屏幕旋转的 Activity,请添加以下内容:如果您想在横向模式下锁定屏幕旋转:

在您的清单文件中,对于每个要锁定屏幕旋转的 Activity,请添加以下内容:如果您想在横向模式下锁定屏幕旋转:

<activity
        ...
        ...
        android:screenOrientation="landscape">

或者如果您想将其锁定在垂直模式:

<activity
            ...
            ...
            android:screenOrientation="portrait">

8

不必进入AndroidManifest,你可以尝试这样做:

screenOrientation = getResources().getConfiguration().orientation;
getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
... AsyncTask

screenOrientation = getResources().getConfiguration().orientation;


@Override
protected void onPostExecute(String things) {
    context.setRequestedOrientation(PlayListFragment.screenOrientation);
    or 
    context.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}

唯一的缺点是,它需要API级别在18或更高。所以基本上这是矛头所在。


这部分代码禁用了主屏幕和最近应用程序按钮,即使使用 SCREEN_ORIENTATION_FULL_SENSOR 解锁后,它仍处于禁用状态。在安卓 N 版本中。 - kAmol

6

Activity.java

@Override     
 public void onConfigurationChanged(Configuration newConfig) {       
        try {     
            super.onConfigurationChanged(newConfig);      
            if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {      
                // land      
            } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {      
               // port       
            }    
        } catch (Exception ex) {       
     }   

AndroidManifest.xml

 <application android:icon="@drawable/icon" android:label="@string/app_name">
  <activity android:name="QRCodeActivity" android:label="@string/app_name"
  android:screenOrientation="landscape" >
   <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
  </activity>

 </application>

4
在您的AndroidManifest.xml文件中使用"portrait"用户可能会感觉是个好的解决方案。但它会强制某些设备(最适合横屏的设备)进入纵向模式,导致无法获得正确的方向。在最新的Android版本中,您将会遇到错误。因此,我的建议是最好使用"nosensor"
<activity
        ...
        ...
        android:screenOrientation="nosensor">

3
请将以下内容添加到您的AndroidManifest.xml文件中:

[ app > src > main > AndroidManifest.xml ]

<activity android:name=".MainActivity"
          android:configChanges="orientation"
          android:screenOrientation="portrait"/>

例子:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.zzzzzz.yyyyy">

   <uses-permission android:name="A-PERMISSION" />

   <application>
      <activity android:name=".MainActivity"
                android:screenOrientation="portrait"
                android:configChanges="orientation">
      </activity>
   </application>

</manifest>

2

添加:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
        ...
        ...
        ...
}

2
在AndroidManifest.xml中,ACTIVITY标签上的以下属性是您所需要的:
android:configChanges="orientation"

因此,完整的活动节点将是:
<activity android:name="Activity1"
          android:icon="@drawable/icon"
          android:label="App Name"
          android:excludeFromRecents="true"
          android:configChanges="orientation">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接