【问题标题】:Should I use a nested fragment for tabs in a fragment?我应该为片段中的选项卡使用嵌套片段吗?
【发布时间】:2018-01-31 22:48:36
【问题描述】:

我有一个 Main Activity,它使用 AHBottomNavigationView 作为屏幕底部的菜单。当点击一个不同的菜单项时,它会创建一个与该菜单项对应的新片段,其逻辑如下(为了简化这个问题,简化了 switch 语句):

fragmentManager.beginTransaction().replace(R.id.content_id, New TheFragmentForTheTabClicked).commit();

content_id 是 Main Activity 的 ConstraintLayout 的 ID。

在我的第一个导航菜单项的片段中,还有两个选项卡(使用 TabLayout),它们用另一个片段替换屏幕空间。这是通过设置在 ViewPager 上的 FragmentPagerAdapter 完成的,因此点击每个选项卡都会更改子片段。所以此时,有一个片段嵌套在一个片段中嵌套在一个类中。一般是这样的:

 Main Activity  
 |
 +-- Fragment 1 (selected from AHBottomNavigationView)
 |   |
 |   +-- Sub-Fragment 1 (selected by clicking the first tab in Fragment 1)
 |   |
 |   +-- Sub-Fragment 2 (selected by clicking the second tab in Fragment 1)
 |
 +-- Fragment 2 (selected from AHBottomNavigationView)
 |
 +-- Fragment 3 (selected from AHBottomNavigationView)
 |
 +-- Fragment 4 (selected from AHBottomNavigationView)

所以我的问题是: 我这样做的方式是否正确,如果不是,更好的方法是什么? 此外,我发现当我第一次选择片段 1 时,两个标签之间的滑动和点击工作正常,但是如果我点击不同的底部导航菜单项(即片段 3)然后返回,我得到以下2个问题:

  1. 任一子片段中的内容均未显示
  2. 在两个选项卡之间滑动不再起作用。与其将一个动作移动到不同的选项卡,我必须完全拉动屏幕,因为指示器会“卡”在两个选项卡之间。

如果我可以提供更多信息,请告诉我,我会提供的。

Fragment1.java:

package com.mypackage.mypackage;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * A simple {@link Fragment} subclass.
 */
public class Fragment1 extends Fragment {

    private FragmentActivity mContext;

    public Fragment1() {
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_1, container, false);

    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);

        // Find the view pager that will allow the user to swipe between fragments
        ViewPager viewPager = (ViewPager) getView().findViewById(R.id.viewpager);

        // Create an adapter that knows which fragment should be shown on each page
        // using getFragmentManager() will work too
        Fragment1PagerAdapter adapter = new Fragment1PagerAdapter(mContext.getSupportFragmentManager(), mContext);

        // Set the adapter onto the view pager
        viewPager.setAdapter(adapter);

        TabLayout tabLayout = (TabLayout) getView().findViewById(R.id.sliding_tabs);
        tabLayout.setupWithViewPager(viewPager);
    }

    /**
     * Override to set context.  This context is used for getSupportFragmentManager in onCreateView
     * @param activity
     */
    @Override
    public void onAttach(Activity activity) {
        mContext=(FragmentActivity) activity;
        super.onAttach(activity);
    }

}

fragment_1.xml

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="fixed"
            app:tabBackground="@color/fragment1TabBackground"
            app:tabIndicatorColor="@color/fragment1TabIndicatorColor"/>

        <android.support.v4.view.ViewPager
            android:id="@+id/viewpager"
            android:layout_width="match_parent"
            android:layout_height="0px"
            android:layout_weight="1"/>

    </LinearLayout>


</android.support.constraint.ConstraintLayout>

Fragment1PagerAdapter.java

package com.mypackage.mypackage;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.content.Context;


public class Fragment1PagerAdapter extends FragmentPagerAdapter {

    private Context context;

    public Fragment1PagerAdapter(FragmentManager fm, Context mContext){
        super(fm);
        context = mContext;

    }

    @Override
    public Fragment getItem(int position){
        if (position == 0){
            return new SubFragment1();
        }
        else{
            return new SubFragment2();
        }
    }

    @Override
    public int getCount() {return 2;}

    @Override
    public CharSequence getPageTitle(int position) {

        switch(position){
            case 0:
                return context.getResources().getString(R.string.sub_fragment_1_page_title);
            case 1:
                return context.getResources().getString(R.string.sub_fragment_2_page_title);
            default:
                return null;
        }
    }
}

【问题讨论】:

  • 当使用ViewPager 滑动将Fragments 嵌套到Fragments 中时,我认为在您的适配器内部您应该使用getChildFragmentManager() 而不是mContext.getSupportFragmentManager()
  • @Yupi 也发布我的适配器对我有用吗?
  • 这里是你需要做的改变:Fragment1PagerAdapter(mContext.getSupportFragmentManager()...
  • @Yupi 当我将Fragment1PagerAdapter(mContext.getSupportFragmentManager() 更改为Fragment1PagerAdapter(mContext.getChildFragmentManager() 时,它说它无法解析该方法。我需要为此导入一个包吗?
  • 没有mContext 只是getChildFragmentManager()

标签: android android-fragments android-activity android-tablayout


【解决方案1】:

当将Fragments 嵌套在Fragment 中时,ViewPager 和作为FragmentManager 的滑动功能需要提供给Adapter,建议使用:getChildFragmentManager() 而不是getSupportFragmentManager()getFragmentManager()。因为两者实际上都与Activities 相关,而不是getChildFragmentManager(),正如文档所述,与Fragment 相关:

返回一个私有的 FragmentManager 用于放置和管理 Fragment 在这个 Fragment 内部。

【讨论】:

    猜你喜欢
    • 2013-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多