фрагмент в FragmentTabHost не отображается

На самом деле это несколько вопросов, касающихся использования FragmentTabHost. Я нашел рабочий образец, который использует FragmentTabHost в Activity. Мне нужно использовать его во фрагменте.

Он отображает фрагмент с вкладками, но фрагмент содержимого для вкладки не отображается. Я видел в журнале, что onCreateView() фрагмента содержимого действительно вызывается, но просто не отображается на экране.

  1. Я видел, как кто-то использует дополнительный FrameLayout, я не уверен, почему. Но пробовал и так, и так, не помогает. а в документе он создает FragmentTabHost вместо выхода из макета. Так как же правильно использовать FragmentTabHost?

    mTabHost = new FragmentTabHost(getActivity());
    mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.fragment1); 
    
  2. Я попытался так же определить макет фрагмента вкладки (tab_fragment_layout.xml), как в примере:

    <android.support.v4.app.FragmentTabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TabWidget
        android:id="@android:id/tabs"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"/>
    
    <!-- why need it? -->
    <!-- with or without this @android:id/tabcontent FramLayout dosent work-->
    <!--FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="0" /-->
    <!-- -->
    
    <FrameLayout
        android:id="@+id/tabFrameLayout"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
    </LinearLayout>
    

The TabFragment::onCreateView() is:

TabFragment extends Fragment...

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.tab_fragment_layout, container, false);
    mTabHost = (FragmentTabHost) view.findViewById(R.id.tabhost);
    mTabHost.setup(getActivity(), getChildFragmentManager(),
            R.id.tabFrameLayout);
    mTabHost.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
            ContentFragment.class, null);
    mTabHost.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
            ContentFragment.class, null);
    return view;
}

Фрагмент содержимого прост:

public class ContentFragment extends Fragment {

private String title = "no page data";
private int page = -1;

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

    Bundle args = getArguments();
    if (args != null) {
        page = getArguments().getInt("someInt", 0);
        title = getArguments().getString("someTitle");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_layout, container, false);
    TextView tv = (TextView) v.findViewById(R.id.text);
    tv.setText(this.getTag() + " Content"+", page data:"+title+" "+page);
    return v;
}
}

Опять же, это просто перенос sample (используя его в действии), чтобы использовать его во фрагменте. Но после добавления этого фрагмента в действие он показывает только вкладку без фрагмента содержимого для каждой вкладки.

FragmentManager fm = getSupportFragmentManager();
TabFragment tabFrgmt = new TabFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.tab_fragment_holder, tabFrgmt);
ft.addToBackStack("theTabFragment");
ft.show(tabFrgmt);
ft.commit();

person lannyf    schedule 17.05.2015    source источник


Ответы (2)


У меня тоже были проблемы с этой проблемой, в итоге я использовал компонент и получил лучшие результаты. Скользящая вкладка на странице

Я написал свой случай в Xamarin. Но вы можете найти код полезным.

    namespace project.Droid.Phone.Fragments
{
public class HostPageFragment : BaseFragment
{
    private ViewGroup _parentContainer;

    private LayoutInflater _inflater;

    private View _tabHostLayout;

    private HostPageViewModel _viewModel;


    public HostPageFragment(HostPageViewModel viewModel)
    {
        _viewModel = viewModel;
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        _parentContainer = container;
        _inflater = inflater;

        _tabHostLayout = _inflater.Inflate(Resource.Layout.HostPage, container, false);

        // Initialize the ViewPager and set an adapter
        var pager = _tabHostLayout.FindViewById<ViewPager>(Resource.Id.pager);

        pager.Adapter = new MyPagerAdapter(ChildFragmentManager,_viewModel);
        pager.SetCurrentItem(_viewModel.InitialTab,false);
        pager.OffscreenPageLimit = pager.Adapter.Count-1;

        // Bind the tabs to the ViewPager
        var tabs = _tabHostLayout.FindViewById<PagerSlidingTabStrip>(Resource.Id.tabs);

        Typeface tf = Typeface.CreateFromAsset(_tabHostLayout.Context.Assets, "Fonts/CenturyGothicBold.ttf");
        tabs.SetTypeface(tf, TypefaceStyle.Normal);

        tabs.SetViewPager(pager);

        return _tabHostLayout;

    }


}
public class MyPagerAdapter : FragmentPagerAdapter
{
    private string[] Titles = {ApplicationResources.text, ApplicationResources.text, ApplicationResources.text};

    private HostPageViewModel _viewModel;

    public MyPagerAdapter(Android.Support.V4.App.FragmentManager fm, HostPageViewModel viewModel) : base(fm)
    {
        _viewModel = viewModel;

        Titles = _viewModel.BooleanFlag? Titles : Titles.Take(Titles.Length - 1).ToArray();
    }

    public override void DestroyItem(ViewGroup container, int position, Object @object)
    {
        container.RemoveView(@object as View);
        base.DestroyItem(container, position, @object);
    }

    public override ICharSequence GetPageTitleFormatted(int position)
    {
        return new Java.Lang.String(Titles[position]);
    }
    #region implemented abstract members of PagerAdapter
    public override int Count
    {
        get
        {
            return Titles.Length;
        }
    }
    #endregion
    #region implemented abstract members of FragmentPagerAdapter
    public override Android.Support.V4.App.Fragment GetItem(int position)
    {
        switch (position)
        {
            case 0:
                var vm = new ViewModel();
                //Initialization of Initial Tab is from the Hamubruger Menu and is used for HudService/Choosing first tab
                return new MyPageFragment(vm,_viewModel.InitialTab == position);
            case 1:
                var vm = new ViewModel();
                return new MyPageFragment(vm, _viewModel.InitialTab == position);
            case 2:
                var vm = new ViewModel();
                return new MyPageFragment(vm,_viewModel.InitialTab == position);
            default:
                //Incase we fall to default show the first tab
                var vm = new ViewModel();
                return new MyPageFragment(vm, _viewModel.InitialTab == position);
        }

    }
    #endregion
}
}
person Zach S.    schedule 17.05.2015
comment
Спасибо, Зак. Но все же хотите использовать FragmentTabHost во фрагменте. - person lannyf; 17.05.2015

Лично я считаю, что использовать FragmentTabHost проще, чем подавать в суд на slideTab/ViewPager, если не заботится о поведении салфетки.

Для №1. Глядя на код (в v4.app.FragmentTabHost поддержки-v4-21):

public void setup(Context context, FragmentManager manager, int containerId) {
    ensureHierarchy(context);  // Ensure views required by super.setup()
    super.setup();
    mContext = context;
    mFragmentManager = manager;
    mContainerId = containerId;
    ensureContent();
    mRealTabContent.setId(containerId);

    // We must have an ID to be able to save/restore our state.  If
    // the owner hasn't set one at this point, we will set it ourself.
    if (getId() == View.NO_ID) {
        setId(android.R.id.tabhost);
    }
}

private void ensureHierarchy(Context context) {
    // If owner hasn't made its own view hierarchy, then as a convenience
    // we will construct a standard one here.
    if (findViewById(android.R.id.tabs) == null) {
        LinearLayout ll = new LinearLayout(context);
        ll.setOrientation(LinearLayout.VERTICAL);
        addView(ll, new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.FILL_PARENT));

        TabWidget tw = new TabWidget(context);
        tw.setId(android.R.id.tabs);
        tw.setOrientation(TabWidget.HORIZONTAL);
        ll.addView(tw, new LinearLayout.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT, 0));

        FrameLayout fl = new FrameLayout(context);
        fl.setId(android.R.id.tabcontent);
        ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0));

        mRealTabContent = fl = new FrameLayout(context);
        mRealTabContent.setId(mContainerId);
        ll.addView(fl, new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.FILL_PARENT, 0, 1));
    }
}

и отчет об ошибке для FragmentTabHost, похоже, это можно сделать в один из нижеприведенных:

  <android.support.v4.app.FragmentTabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.app.FragmentTabHost>

или чтобы имитировать обеспечениеHierarchy().

<android.support.v4.app.FragmentTabHost
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:background="@drawable/alert_dialog_icon"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TabWidget
        android:id="@android:id/tabs"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0"/>

    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="0"/>

    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    </LinearLayout>
</android.support.v4.app.FragmentTabHost>

Из-за проблемы с отображением фрагмента содержимого после переноса FragmentTabHost в другой корневой макет он отображается.

Но остался один вопрос: следует ли продолжать использовать support.v4 или перейти на последнюю версию, например support.v7.app.FragmentTabHost и т. д.?

У кого-нибудь есть лучшее решение или внутри того, как правильно использовать FragmentTabHost, пожалуйста, прокомментируйте. Спасибо!

person lannyf    schedule 17.05.2015