将 ListFragment 替换为 ViewPager 中的 Fragment 与选项卡

Posted

技术标签:

【中文标题】将 ListFragment 替换为 ViewPager 中的 Fragment 与选项卡【英文标题】:Replace ListFragment with Fragment inside ViewPager with Tabs 【发布时间】:2013-02-25 15:08:24 【问题描述】:

我尝试在我的应用中设置以下导航:

实际情况:ViewPager + Tabs 在列表之间滑动:

ListFragment A ListFragment B

所需条件: ViewPager + 选项卡:

ListFragment A onListItemSelected 将 ListFragment A 替换为 DetailFragment A ListFragment B onListItemSelected 将 ListFragment B 替换为 DetailFragment B

目标是在选项卡导航中显示详细信息片段。我不能用 detailFragment 替换 fragmentList(fragmentList 没有自定义布局,因此没有 ID,我不知道该怎么做)。 此外,开始一个新的活动会隐藏标签栏。

有人可以帮帮我吗?

【问题讨论】:

【参考方案1】:

我会制作一个包装片段,它知道要显示什么 - 列表或详细信息。这将与ViewPager 完全分离——寻呼机只知道它包含包装片段,而这些片段将自己管理它们的内容。

实施将遵循以下原则:

public class WrapperFragment extends Fragment 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);

        MyListFragment list = new MyListFragment();
        list.setListAdapter(adapter);
        list.setOnItemClickListener(new OnItemClickListener() 
            @Override public void onItemClick(AdapterView<?> l, View v, int position, long id) 
              // Create details fragment based on clicked item's position
              Fragment details = new Fragment();
              getChildFragmentManager()
                  .beginTransaction()
                  .replace(R.id.container, details)
                  .addToBackStack(null)
                  .commit();
            
        );

        getChildFragmentManager()
            .beginTransaction()
            .add(R.id.container, list)
            .commit();
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        // There has to be a view with id `container` inside `wrapper.xml`
        return inflater.inflate(R.layout.wrapper, container, false);
    

    public class MyListFragment extends ListFragment 

        private OnItemClickListener listener;

        public void setOnItemClickListener(OnItemClickListener l) 
            this.listener = l;
        

        @Override
        public void onListItemClick(ListView l, View v, int position, long id) 
            if(listener != null) 
              listener.onItemClick(l, v, position, id);
            
        
    


wrapper.xml。想法是 WrapperFragment 必须提供一个布局,其中包含一个 id 为 container 的视图 - 因为我们正在使用具有此 id 的视图来放置子片段 - MyListFragmentDetailsFragment

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>

    <FrameLayout
        android:id="@+id/container"
        android:layout_
        android:layout_/>

</FrameLayout>

另一种方式。这应该可行,但你必须尝试一下(布局本身有id,而不是有一个ID为container的孩子):

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_
    android:layout_/>

【讨论】:

布局包装器看起来像这样吗?我得到 onCreateView 的 InflateException。 schemas.android.com/apk/res/android" android:id="@+id/container" android:name="PATH_TO_WrapperFragment" ... > 添加了wrapper.xml 的示例。如果您对此有任何问题,请告诉我 getChildFragmentManager().popBackStack()。在显示DetailsFragment 时注意.addToBackStack(null) 行。它基本上说“将此事务保存为历史操作 - 可以通过按下硬件返回按钮将其移回”。 popBackStack() 有点模拟硬件后退按钮的点击。将backStack 管理视为类似于 html5 History API 可能更容易理解。 首先感谢这一点,它解决了我过去几天一直遇到的问题,其次是关于我发现从 getChildFragmentManager() 更改为启用 support.app 的常规 FragmentManager() 的问题后退按钮无需从任何地方手动调用即可工作,使用 childmanager 没有,不确定这会产生什么副作用,但它的所有行为都是我想要的:D @Kevin,抱歉,错过了您的评论。原因可能是 onCreateOptionsMenu() 仅在***片段 - 包装器上调用。解决方案可能是从那里创建菜单 - 例如通过手动调用listFragment#onCreateOptionsMenu()。这是从头顶开始的,你需要试试这个

以上是关于将 ListFragment 替换为 ViewPager 中的 Fragment 与选项卡的主要内容,如果未能解决你的问题,请参考以下文章

屏幕旋转后Android片段重叠

如何设置 ListFragment 自定义布局的 Divider(为 null)

如何在 DialogFragment 中显示现有的 ListFragment

如何将 ListFragment 添加到布局中

在 Android ListFragment 上调用搜索或过滤器?

在滚动结束时将更多项目附加到 listfragment