Android:如何在不重新启动活动的情况下手动更改屏幕方向?

10

我需要制作一个播放视频的应用程序,并在视频上添加一个全屏按钮。该按钮用于手动切换视频显示的横向和纵向。我们不想要自动旋转检测,因此清单文件设置如下。

<activity
    android:name=".VideoActivity"
    android:screenOrientation="portrait"
    android:configChanges="keyboardHidden"/>

我使用了 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); 或者 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); 来手动设置方向。虽然它可以工作,但是它会重新启动 Activity - onCreate() 方法会被调用。因此,视频播放会意外地从头开始。我无法使其像使用 onConfigurationChanged() (自动旋转检测方法)一样平滑。

那么如何在不重新启动 Activity 的情况下进行手动屏幕方向更改呢?

谢谢。


你做不到。这是系统的工作方式。它必须重新执行大量的工作,然后摧毁活动并重新创建它。 - Stefan de Bruijn
请参阅此内容:https://dev59.com/-msz5IYBdhLWcg3wOlSh - Iram Bukhari
6个回答

7

手动更改方向:

<activity
    android:name=".VideoDetails"
    android:configChanges="orientation"/>

public class VideoDetails extends Activity {
    ...
    onStart() {
        setRequestedOrientation(orientation);
    }
    onConfigurationChanged(Configuration newConfig){
        // do stuff for orientation change.
    }
    onClick() {
        setRequestedOrientation(orientation);
    }
}

自动方向检测:

<activity
    android:name=".VideoDetails"
    android:configChanges="orientation"/>

public class VideoDetails extends Activity {
    ...
    onConfigurationChanged(Configuration newConfig){
        // do stuff for orientation change.
    }
}

2
你可以查看标题为自行处理配置更改的链接:http://developer.android.com/guide/topics/resources/runtime-changes.html
<activity android:name=".MyActivity"
      android:configChanges="orientation|keyboardHidden"
      android:label="@string/app_name">

现在,当这些配置之一发生更改时,MyActivity不会重新启动。相反,MyActivity会接收到一个onConfigurationChanged()的调用。该方法会传递一个Configuration对象,指定新的设备配置。
 android:configChanges="orientation|screenSize" (andorid 3.2 and above screen size also changes. add this)

假设你的视频长度为10分钟。视频播放到5分钟时,方向发生改变,你知道它已经播放到了5分钟。
你可以在onSaveInstanceState()中保存实际的视频进度,并从Bundle中在onRestoreInstanceState()中获取保存的数据,之后你可以使用进度数据继续播放,或者如果没有保存数据,则从头开始播放。
当方向改变时,活动将被销毁并重新创建。如果你想保存数据并保留它们,你可以按照以下方式保存大量数据。
 @Override
 public Object onRetainNonConfigurationInstance() {
 final MyDataObject data = collectMyLoadedData();
 return data;
 }


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final MyDataObject data = (MyDataObject) getLastNonConfigurationInstance();
if (data == null) {
    data = loadMyData();
}

}

对于小数据集
 @Override
 public void onSaveInstanceState(Bundle savedInstanceState) {
 super.onSaveInstanceState(savedInstanceState);
 // Save UI state changes to the savedInstanceState.
 // This bundle will be passed to onCreate if the process is
 // killed and restarted.
 savedInstanceState.putString("NICK_NAME", Name);//save nick name
 }

 @Override
 public void onRestoreInstanceState(Bundle savedInstanceState) {
 super.onRestoreInstanceState(savedInstanceState);
 // Restore UI state from the savedInstanceState.
 // This bundle has also been passed to onCreate.
 Name = savedInstanceState.getString("NICK_NAME");//restore nick name
 }

检查方向。
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);

// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
    Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
    Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}

在Android中使用VideoView。在这种情况下,视频也是从服务器流传输的。请查看已接受的答案(commonsware答案)。这正是我建议的。”

谢谢您。您使用 onSaveInstanceState()onRestoreInstanceState() 的方法是其中一种解决方案。但是,我关心的是视频播放的流畅性,因为我的应用程序从服务器播放视频流。重新连接和视频寻址时间会导致视频播放不连续。 - tim
@user1835097,请查看最后一个链接。该用户还从服务器流式传输视频。请查看被采纳的答案。 - Raghunandan

1

首先,在Activity的清单节点中添加android:configChanges节点。

android:configChanges="keyboardHidden|orientation"

查看更多信息,请访问this链接。


谢谢。您的方法似乎可以通过系统自动检测方向变化来防止活动重新启动。但我不想要自动检测,我需要手动设置。 - tim
@user1835097,你可以通过重写Activity.onConfigurationChanged来实现。 - Janmejoy
@user1835097,请查看此链接:http://c0deattack.wordpress.com/2010/12/25/dealing-with-screen-orientation-changes-manually/。 - Janmejoy

0
添加标签。
"android:configChanges="keyboard|keyboardHidden|orientation|screenSize|navigation" for your activity in Manifest.xml,

覆盖该方法

public void onConfigurationChanged(Configuration newConfig) {}

如果您需要在屏幕方向更改时更改布局,请查看此链接{{link1:replace layout on orientation change}}


0

在屏幕方向改变后,应用程序重新启动是不可避免的。

将与视频状态相关的变量保留在应用程序中,以便活动不会在开始时重新启动播放。

这段代码来自我制作的一个示例应用程序,用于测试此答案。

public class MyApplication extends Application {
int counter;
@Override
public void onCreate() {
    super.onCreate();
    counter = 0;
    }
}   

在你的清单文件中添加应用程序

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:name="com.example.orientationchange.MyApplication" >
    <activity
 ...

在 Activity 中使用:

public class MainActivity extends Activity {

TextView output;
MyApplication app ;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    app = (MyApplication) getApplication();
    setContentView(R.layout.activity_main);
    output = (TextView) findViewById(R.id.output);
    //A counter thread used to test the solution.
    new CounterTask().execute( 100 );
}
 ...

现在旋转不会清除状态变量。

您可以选择使用首选项来更加注重代码的解决方案以保留状态。首选项还将记住应用程序的状态,从而使应用程序在销毁时(onDestroy())被清除。


0

我寻找解决方案已经很久了,对我来说,在清单中定义方向为锁定是有效的:

<activity
    android:name=".VideoActivity"
    android:screenOrientation="locked"
    android:configChanges="keyboardHidden"/>

这可以防止Activity在调用setRequestedOrientation()时重新创建


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