在屏幕方向改变时更改片段布局

5
我有以下问题:
我有一个TabActivity,它在其中一个选项卡中显示一个FragmentActivity
当点击ListFragment的项目时,FragmentActivity添加了一个ListFragment,然后添加(也添加到回退栈)并显示了一个片段。
现在我需要更改该Fragment的布局,以在横向方向上进行更改。
但是我完全不知道在哪里实现该更改。我已经在layout-land文件夹中创建了正确的布局。但正确的设置点在哪里?
3个回答

21

警告:此可能是一篇有关“棒棒糖”(Lollipop)之前版本的答案。

Fragment 在配置更改时不会重新充气,但您可以通过使用 FrameLayout 创建它并手动(重新)填充该片段来实现相同的效果:

public class MyFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
        FrameLayout frameLayout = new FrameLayout(getActivity());
        populateViewForOrientation(inflater, frameLayout);
        return frameLayout;
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        LayoutInflater inflater = LayoutInflater.from(getActivity());
        populateViewForOrientation(inflater, (ViewGroup) getView());
    }

    private void populateViewForOrientation(LayoutInflater inflater, ViewGroup viewGroup) {
        viewGroup.removeAllViewsInLayout();
        View subview = inflater.inflate(R.layout.my_fragment, viewGroup);

        // Find your buttons in subview, set up onclicks, set up callbacks to your parent fragment or activity here.
    }
}

我对这里的getActivity()和相关调用并不特别满意,但我认为没有其他方法来获取这些东西。

更新:移除了将ViewGroup强制转换为FrameLayout并使用了LayoutInflater.from()以及inflate()的第三个参数来代替显式添加视图。


1
答案被接受了,但我认为添加FrameLayout是不必要的,因为你可以直接使用ViewGroup容器和getView()。 - Goddchen
@Godchen:你是说要将“container”对象传递给populateView()来填充视图,而不是新的FrameLayout对象,并在onConfigurationChanged()中传递getView().getParent()?这似乎与文档相矛盾:container:如果非空,则这是片段UI应附加到的父视图。片段不应该自己添加视图,但可以用于生成视图的LayoutParams。 - android.weasel
这似乎在Android 21中有所改变。在这个新的API版本中,片段的布局似乎会在旋转时自动重新填充。但令人烦恼的是,在以前的API版本中没有记录旋转管理的缺失,特别是当Google建议使用片段而不是活动时。 - Javad
这个答案非常适用于安卓5.0以下的设备。 - Saraschandraa
这种做法会导致视图监听器丢失吗? - Tamim Attafi
答案是否定的,所有的回调函数都已经失效。 - Tamim Attafi

0

res包下的layoutlayout-land包中,需要两个不同的xml设计,但命名相同。

当方向发生改变时,重写onConfigurationChanged()函数,并将其编辑如下以加载适合当前屏幕方向的XML文件。

override fun onConfigurationChanged(newConfig: Configuration) {
        val fragmentManager: FragmentManager = requireActivity().supportFragmentManager
        fragmentManager.beginTransaction().detach(this).commitAllowingStateLoss()
        super.onConfigurationChanged(newConfig)
        fragmentManager.beginTransaction().attach(this).commitAllowingStateLoss()
}

0

我相信,如果你有针对特定设备方向的布局,则只需将它们命名为相同的名称,但将它们放置在适当的资源目录中即可。这个链接提供了一些解释。Android系统会负责选择适当的资源,但如果需要,你也可以自己处理。


1
我知道所有这些是如何工作的,但这似乎只适用于Activities,而不适用于Fragments! - Goddchen
在您的Fragment类中实现onCreateView方法[http://developer.android.com/guide/topics/fundamentals/fragments.html#UI]不能达到相同的效果吗? - D-Dᴙum
它不会在方向更改时再次调用,仅调用一次。 - Goddchen
显然它不会 :( 那么你建议在onConfigurationChange方法中再次填充和展开布局吗? - Goddchen
如果Android没有处理片段资源,那么这似乎可能是包中的一个错误。然后我确实会像你建议的那样,在应用程序中处理方向更改。 - D-Dᴙum
显示剩余3条评论

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