在单一活动架构中设置片段的横向方向

8
如何在单个活动架构(整个应用程序仅有一个活动)中仅为一个Fragment实现锁定屏幕方向?
是否有比在每个Fragment中指定所需方向更好的解决方案? 我试图避免将activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED放入每个无关的Fragment中。

你可以在需要保持固定方向的片段中放置 activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT。否则不要使用任何代码,它应该按预期工作。 - Rajesh K
@RajeshK 很不幸,在访问更改后的片段后,所请求的方向将用于所有其他片段。 - Francis
7个回答

15

首先,我要说的是 @madlymad 的想法是正确的,如果你还没有创建 BaseFragment 类,那么你应该去创建一个。

然而,如果由于某种原因你不能或不想这样做,你可以在FragmentonAttached()onCreate()onCreateView()中设置方向。

activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

然后在它们各自对应的onDetached()onDestroy()onDestroyView()中进行重置

activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED

这将确保您只在正确的片段中获得不同的方向。


1
非常感谢您的回答。onCreateView() / onDestroyView() 是指定方向的正确位置,因为在每个片段替换中并不会调用onAttached()onCreate() - Francis

3
在您想要在 横屏 模式下分段的位置添加以下行:
     @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            // Inflate the layout for this fragment 
            //ADD BELOW LINE
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

            view = inflater.inflate(R.layout.fragment_dashboard, container, false);

       return view;
    }

如果您在片段中添加上述代码,则所有片段都会以“横向”模式显示。但是,如果您只想要单个片段,则需要在“其他片段”中添加以下代码。
     @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            //ADD BELOW LINE
            getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

            view = inflater.inflate(R.layout.fragment_inventory, container, false);


            return view;
        }

注意:在manifest.xml中无需添加方向。

2
我会扩展Fragment并创建一个BaseFragment用于所有的片段。在这个基本片段中,我将使用activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR
public abstract class BaseFragment extends Fragment {
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser) {
            Activity a = getActivity();
            if(a != null)
             a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
        }
    }
}

对于特定的锁定片段,我只需使用activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE

public class LandscapeFragment extends BaseFragment {
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser) {
            Activity a = getActivity();
            if(a != null)
             a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }
    }
}

现在唯一需要更改的是使所有片段扩展BaseFragment而不是Fragment,但这也有可能在其他共享特性中受益。
我不熟悉Kotlin,但 Kotlin 代码可能如下所示:
abstract class BaseFragment : Fragment() {
  override fun setUserVisibleHint(isVisibleToUser : Boolean){
     super.setUserVisibleHint(isVisibleToUser)
     if(isVisibleToUser) {
       getActivity()?.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR)    
     }
  }
}

class LandscapeFragment : BaseFragment() {
    override fun setUserVisibleHint(isVisibleToUser : Boolean) {
        super.setUserVisibleHint(isVisibleToUser)
        if(isVisibleToUser) {
             getActivity()?.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
        }
    }
}

0

如果是活动,您可以仅在清单文件中为活动标签指定。

对于活动中的片段,我想您可以使用以下代码:

getActivity().setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

在Activity中,编写一个方法,通过传递布尔值true表示PORTRAIT,false表示LANDSCAPE,并从Fragment中调用它。我的意思是,如果Activity包含需要不同方向的不同Fragment。

我的问题是关于单一活动架构的,因此清单中活动的标签将为整个应用程序更改。我试图避免将 activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 放入每个不相关的 Fragment 中。 - Francis

0

方向属性是针对每个活动的,因此您可以仅为包含该片段的活动声明方向,使其呈现为横向,而其他活动则保持原样。

在希望具有特定(在此情况下为纵向)方向的片段中使用以下代码行。

getActivity().setRequestedOrientation(
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

如果您想要在片段中根据用户持有设备的方式进行定位,那么请使用以下代码行。
getActivity().setRequestedOrientation(
            ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);

0
<activity
    android:name=".user_interface.activities.MainActivity"
    android:screenOrientation="landscape"
    android:theme="@style/MyMaterialTheme"/>

这将改变整个应用程序的方向(在单个活动架构中),我的问题是关于仅更改特定片段方向的方法。 - Francis
getActivity().setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 可以实现屏幕横向显示。 - Shweta Chandarana
更改将保留所有其他片段。我只需要它适用于一个片段(寻找除了在每个片段中定义之外的任何其他解决方案)。 - Francis

0

我有和你一样的情况,我从我的Activity中调用所有的片段。我想知道如何将代码放在一个地方。

    int id = item.getFragmentId();

    if (id == R.id.nav_camera) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
    }
    // Here you can have your fragment calls
    getSupportFragmentManager().beginTransaction().replace(
           R.id.content_main,
           new YourFragmentForId(),
           NotificationFragment.class.getSimpleName())
          .commit();

我仍然认为这是最好的方法。


谢谢您的回答。但是我使用Jetpack中的导航组件(Navigation component)而不是FragmentManager - Francis

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