Android 当某些片段可见时启用显示方向更改,当其他片段可见时禁用显示方向更改

Android 当某些片段可见时启用显示方向更改,当其他片段可见时禁用显示方向更改,android,android-fragments,Android,Android Fragments,我在我的应用程序中使用片段。大多数片段应该只有一个方向-portait。所以我强迫持有者活动始终处于纵向模式 但是我的一个片段应该同时具有纵向和横向模式。如何仅为一个片段启用方向更改?或者我需要将其作为一个单独的活动来处理方向,而不依赖于其他片段?您必须手动执行 1) 将此行添加到您的活动标签android:configChanges=“方向|屏幕大小” 2) 覆盖框架或活动中的配置更改回调 @Override public void onConfigurationChanged(Configu

我在我的应用程序中使用片段。大多数片段应该只有一个方向-portait。所以我强迫持有者活动始终处于纵向模式


但是我的一个片段应该同时具有纵向和横向模式。如何仅为一个片段启用方向更改?或者我需要将其作为一个单独的活动来处理方向,而不依赖于其他片段?

您必须手动执行

1) 将此行添加到您的活动标签android:configChanges=“方向|屏幕大小”

2) 覆盖框架或活动中的配置更改回调

@Override
public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig); 

   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();
    }

//Your fragment animation layout changing code

}

我找到了这个问题的解决方案: 在每个片段中重写setUserVisibleHint()

在肖像中,只有碎片:

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
Activity a = getActivity();
if(a != null) a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}

在你的AndroidManifest.xml中,在你想修复为纵向的片段中添加android:screenOrientation=“纵向”,不要在你不想修复方向的片段中添加此语句。例如:

<activity
android:name="com.example.myapp.MainActivity"
android:screenOrientation="portrait"/>

选择要显示的片段时,请使用活动方法

public class MyActivity extends Activity {
  // ...

  public void chooseFragment(int x) {
    Fragment newFragment;
    if (x == 1) {
      // FragmentOne can be any orientation
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
      newFragment = new FragmentOne();
    }
    else {
      // FragmentTwo can be only portrait orientation
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
      newFragment = new FragmentTwo();
    }
    getSupportFragmentManager().beginTransaction()
      .replace(R.id.fragment_container, newFragment)
      .commit();
  }

  // ...
}

我知道这是旧的,但我会加上我的两分钱,以防它帮助别人,因为它仍然是当前的问题

注意:一天后,我发布了这个答案,因为我发现API低于26存在问题。经过广泛的测试,以下是我的最终答案。 此解决方案在API 21及更高版本中有效(经过测试)

我的案例可能与贴出的问题不完全相同,因此我将详细说明我有什么,以及我是如何解决的

  • 一个活动包含多个片段
  • 只有一个片段需要能够是纵向和横向的,因为它具有相应的不同布局版本。其余部分必须保持纵向,并且当应用程序位于前景时,屏幕不得旋转
  • 我用过科特林。对于Java来说应该几乎是一样的
  • 在您拥有的每个片段中,都需要覆盖
    onResume()
    。 在其中,您可以指定要“强制”的方向

    在我的例子中,我只希望在纵向和横向方向中显示一个片段,所以我设置了
    requestedOrientation=ActivityInfo.SCREEN\u orientation\u UNSPECIFIED
    (如果未设置,则为默认值),但是由于我们将在其余片段中更改
    请求方向
    ,我们也必须在此处设置它

        override fun onResume() {
    
        super.onResume()
    
        activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
    
        //The rest of your code (if you have something else here).
    
        }
    
    在剩下的片段中,我想“强制”纵向定位,因此我使用了以下方法:

        override fun onResume() {
    
        super.onResume()
    
        activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    
        //The rest of your code (if you have something else here).
    
        }
    
    这就是你所需要的一切,让它工作!以下内容是可选的,但可能会很有用,就像对我一样

    可选1:

    如果您有许多片段,并且不想在每个片段中修改/添加
    onResume()
    ,您可以创建
    Fragment()
    的子类(例如,肖像片段),只需覆盖
    onResume()
    。然后,您可以从中派生出您想要拥有此功能的所有片段

    open class PortraitFragment : Fragment() {
    
        override fun onResume() {
            super.onResume()
    
            activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
    
    }
    
    可选2:

    根据您的布局,您可能还需要添加此项。
    我之所以使用它,是因为我的布局没有为多窗口模式做好准备

    在清单中添加android:resizeableActivity=“false”:

    
    
    以及如何在除一个片段外的所有片段中禁用方向更改?将行添加到清单后,将不会触发片段的重新创建。在要创建新视图的片段中,您应该手动删除当前视图并创建新视图。我认为您混淆了活动和片段。如果这样做有效,它将不再有效,而且
    setUserVisibleHint
    已被弃用
        <activity android:name=".MainActivity"
        android:launchMode="singleTask"
        android:windowSoftInputMode="stateHidden|adjustPan"
        android:resizeableActivity="false">