Android. 在另一个TabLayout的选项卡中嵌套TabLayout

4

是否可以在另一个标签布局的标签内部放置一个标签布局? 我创建了以下图像以更好地解释。 所需的滑动移动如图像所述。

enter image description here

我的主活动

Xml

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="fixed"
            app:tabGravity="fill"/>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"  />

</android.support.design.widget.CoordinatorLayout>

代码

public class MainActivity extends AppCompatActivity {

    private TabLayout tabLayout;

    private final static int[] tabIcons = {
            R.drawable.ic_tab_1,
            R.drawable.ic_tab_2,
            R.drawable.ic_tab_3,
            R.drawable.ic_tab_4
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
        setupTabIcons();
    }

    private void setupTabIcons() {
        tabLayout.getTabAt(0).setIcon(tabIcons[0]);
        tabLayout.getTabAt(1).setIcon(tabIcons[1]);
        tabLayout.getTabAt(2).setIcon(tabIcons[2]);
        tabLayout.getTabAt(3).setIcon(tabIcons[3]);
    }

    private void setupViewPager(ViewPager viewPager) {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new Fragment1());
        adapter.addFrag(new Fragment2());
        adapter.addFrag(new Fragment3());
        adapter.addFrag(new Fragment4());
        viewPager.setAdapter(adapter);
    }

    class ViewPagerAdapter extends FragmentPagerAdapter {

        private final List<Fragment> mFragmentList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFrag(Fragment fragment) {
            mFragmentList.add(fragment);
        }
    }
}

碎片

XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@android:color/holo_blue_light"
    android:id="@+id/fragment_1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="myContext">

    <TextView
        android:text="It is just a text."
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

代码

public class Fragment1 extends Fragment {

    public Fragment1() { }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment.
        return inflater.inflate(R.layout.fragment_1, container, false);
    }
}

Fragment2_A和Fragment2_B的XML和Java代码应该怎样编写?


为什么不可能?我不明白,怎么回事? - M. Erfan Mowlaei
而且问题在哪里?据我所知,在另一个ViewPager内部保留ViewPager没有问题。默认行为就像您希望的那样 - 当在Fragment内部放置另一个ViewPager时,它会“吞咽”触摸事件直到边界,然后当它无法滑动时,将MotionEvent传递给父级。你能展示一下你的R.layout.fragment_1吗?你的R.layout.fragment_2应该包含另一个具有自己ID的TabLayout。 - snachmsm
@snachmsm 使用 R.layout.fragment_1 编辑了问题。抱歉,我只是一个 Android 初学者,没有问题 ^^ 只是我没有找到直接的解决方案。我的问题是第一个布局在一个活动中声明,但是第二个布局我不知道应该在哪里声明,因为我有两个片段 Fragment2_AFragment2_B,而不是一个活动。 - Santiago Gil
3个回答

6
我知道这不是对问题的直接回答,我可能因此受到惩罚,但是您不应在选项卡中嵌套其他选项卡。谷歌使用名为材料设计的设计概念。其中一个关于选项卡的规则是不要将它们嵌套在一起。以下是页面链接:https://material.google.com/components/tabs.html#tabs-usage。我认为作为开发者,遵循这个规则对于使Android平台变得普适和令人惊艳非常重要。
谢谢, Oak

我甚至没有一点意识到这一点,非常感谢你说出来,真的。 - Nikki

6

好的,在你的片段内,你只有一个 TextView。现在对于 fragment_2,放置另一个 TabLayoutViewPager(你不需要 AppBarCoordinator,它们已经从 Activity 的父布局中存在)

frag2.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <android.support.design.widget.TabLayout
        android:id="@+id/frag2_tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill"/>
    <android.support.v4.view.ViewPager
        android:id="@+id/frag2_viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"  />
</LinearLayout>

你需要创建Frag2 Fragment,在OnCreateView中使用上述布局进行初始化,然后为frag2_viewpager ViewPager类设置另一个适配器,仅用于frag2a.xmlfrag2b.xml Fragments,它们可以只有TextView或其他。 TabLayout将放置在Frag2上方(并且在图片中的Activity中也有)。

我必须将TabLayout放置在两个片段Fragment2_AFragment2_B中吗? - Santiago Gil
请在Frag2中使用另一个适配器来创建其他片段。TabBar将只有一个(从Frag2的另一个片段),Frag2aFrag2b按您的意愿进行初始化。滑动功能(实际上是触摸事件传递)将直接奏效,就像你图片中展示的一样。 - snachmsm
好的,如果我理解正确,这个选项卡有3个片段。RootFrag2Frag2_AFrag2_B。这两个是普通的片段。在根片段中,我为这两个片段创建了另一个适配器(我只是将主活动适配为片段)。然而,当使用getSupportFragmentManager()时,在setupViewPager方法声明中出现错误。无法解析方法'getSupportFragmentManager()' - Santiago Gil
1
如何在片段中访问getSupportFragmentManager()?请注意,在Fragment中始终有getActivity()方法,可能会有所帮助(((MainActivity) getActivity()).methodInsideMainActivity())。 - snachmsm
1
RecyclerView 有自己的“内存”来存储 Fragments,默认情况下设置为1。这意味着recycler在左右(和当前)保留一个视图/片段,以便平滑滑动而不会出现“延迟”,以绘制另一个完整屏幕。您可以使用 setOffscreenPageLimit 来增加此值。但是,如果您的应用程序崩溃,则意味着您可能在Frag2或任何Frag2children中存在错误,这些错误发生在删除(分离)Fragment时。 - snachmsm
显示剩余3条评论

2

简单易懂

一切都会保持不变,就像您在Activity中设置ViewPager一样。只是您需要在Fragment中使用getChildFragmentManager()而不是getFragmentManager()

getChildFragmentManager()文档中可以看到:

返回一个私有的FragmentManager,用于放置和管理此Fragment内部的Fragments。

getFragmentManager()文档中可以看到:

返回与此Fragment关联的Activity的FragmentManager以与Fragments进行交互。

您可以查看@此答案获取完整代码。


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