web-dev-qa-db-fra.com

TabHost avec Fragments and FragmentActivity

Je travaille sur une application Android et je veux utiliser 3 onglets pour la navigation en utilisant des fragments pour chaque onglet, mais je ne sais pas comment créer la structure pour le faire.

Je veux ajouter chaque fragment séparément car chacun est différent, mais je ne sais pas où les ajouter dans FragmentActivity.

J'ai ces fichiers.

tabs_layout.xml

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="vertical"
    Android:layout_height="match_parent"
    Android:layout_width="match_parent">

    <TabHost Android:id="@Android:id/tabhost"
         Android:layout_width="match_parent"
         Android:layout_height="match_parent">

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

             <TabWidget
                Android:id="@Android:id/tabs" 
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
             />

             <FrameLayout
                 Android:id="@Android:id/tabcontent" 
                 Android:layout_width="match_parent"
                 Android:layout_height="match_parent"

             >

                 <FrameLayout
                     Android:id="@+id/tabRateAPet" 
                     Android:layout_width="match_parent"
                     Android:layout_height="match_parent"

                 />

                 <FrameLayout
                     Android:id="@+id/tabViewMyRates" 
                     Android:layout_width="match_parent"
                     Android:layout_height="match_parent"

                 />

                 <FrameLayout
                     Android:id="@+id/tabViewGlobalRates" 
                     Android:layout_width="match_parent"
                     Android:layout_height="match_parent"

                 />


             </FrameLayout>
        </LinearLayout>
    </TabHost>
</LinearLayout>

TabsMain.Java

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentActivity;

public class MainTabsActivity extends FragmentActivity {
public static final String RATE_A_PET = "Rate a Pet";
public static final String MY_RATES = "My Rates";
public static final String GLOBAL_RATES = "Global Rates";

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tabs_layout);
 }
}

Tabs.Java

import Android.app.Activity;
import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.util.Log;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Android.widget.TabHost;
import Android.widget.TabHost.OnTabChangeListener;
import Android.widget.TabHost.TabSpec;
import Android.widget.TextView;

public class Tabs extends Fragment implements OnTabChangeListener {
    private static final String TAG = "FragmentTabs";
    public static final String RATE_A_PET = "Rate a Pet";
    public static final String MY_RATES = "My Rates";
    public static final String GLOBAL_RATES = "Global Rates";

    private View mRoot;
    private TabHost mTabHost;
    private int mCurrentTab;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
//      super.onCreateView(inflater, container, savedInstanceState);
        mRoot = inflater.inflate(R.layout.tabs_layout, null);
        mTabHost = (TabHost) mRoot.findViewById(Android.R.id.tabhost);
        setupTabs();
        return mRoot;
    }

    private void setupTabs() {
        mTabHost.setup(); // important!
        mTabHost.addTab(newTab(RATE_A_PET, R.string.tabRateAPet, R.id.tabRateAPet));
        mTabHost.addTab(newTab(MY_RATES, R.string.tabViewMyRates, R.id.tabViewMyRates));
    }

    private TabSpec newTab(String tag, int labelId, int tabContentId) {
        Log.d(TAG, "buildTab(): tag=" + tag);

        View indicator = LayoutInflater.from(getActivity()).inflate(
                R.layout.tab,
                (ViewGroup) mRoot.findViewById(Android.R.id.tabs), false);
        ((TextView) indicator.findViewById(R.id.text)).setText(labelId);

        TabSpec tabSpec = mTabHost.newTabSpec(tag);
        tabSpec.setIndicator(indicator);
        tabSpec.setContent(tabContentId);
        return tabSpec;
    }


    @Override
    public void onTabChanged(String tabId) {
        Log.d(TAG, "onTabChanged(): tabId=" + tabId);
        if (RATE_A_PET.equals(tabId)) {
            updateTab(tabId, R.id.tabRateAPet);
            mCurrentTab = 0;
            return;
        }
        if (MY_RATES.equals(tabId)) {
            updateTab(tabId, R.id.tabViewMyRates);
            mCurrentTab = 1;
            return;
        }
        if (GLOBAL_RATES.equals(tabId)) {
            updateTab(tabId, R.id.tabViewGlobalRates);
            mCurrentTab = 2;
            return;
        }
    }   
    private void updateTab(String tabId, int placeholder) {
        FragmentManager fm = getFragmentManager();
        if (fm.findFragmentByTag(tabId) == null) {
            fm.beginTransaction()
                    .replace(placeholder, new RateMyPetActivity(), tabId)
                    .commit();
        }
    }

}
29
imarban

Je suggère de créer un fichier fragment séparé pour chaque onglet. J'ai récemment fait cela aussi, alors j'ai résumé mon code ci-dessous:

Fichiers de mise en page

activity_main.xml 

<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: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>

tab1_view.xml // ajoute vos dispositions d'onglet respectives en utilisant ce format (veillez à modifier les variables de chaîne)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
        xmlns:tools="http://schemas.Android.com/tools"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        Android:orientation="vertical"
        tools:context=".DeviceFragment" >

    <TextView
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="@string/tab1_fragment_string" />

</LinearLayout>

Fichiers SRC

MainActivity.Java // remarquez que dans le processus .addTab, je n’utilisais que du texte. Vous pouvez également ajouter des icônes en utilisant des éléments dessinables que vous auriez besoin d'ajouter à votre dossier hdpi. J'ai également créé seulement trois onglets dans cet exemple.

package com.example.applicationname;

import Android.os.Bundle;
import Android.support.v4.app.FragmentActivity;
import Android.support.v4.app.FragmentTabHost;

public class MainActivity extends FragmentActivity {
    // Fragment TabHost as mTabHost
    private FragmentTabHost mTabHost;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTabHost = (FragmentTabHost)findViewById(Android.R.id.tabhost);
        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab1"),
            Tab1Fragment.class, null);
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Tab2"),
            Tab2Fragment.class, null);
        mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("Tab3"),
            Tab3Fragment.class, null);
    }
}

Tab1Fragment.Java // encore une fois répliquer pour le nombre souhaité d'onglets

package com.example.applicationname;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;

public class Tab1Fragment extends Fragment  {

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

        return V;
    }
}

Assurez-vous que vos fichiers R.Java et strings.xml sont correctement configurés. Vos onglets doivent alors être opérationnels.

78
Kylie Moden

(TabHost } _ ne conserve pas le states du fragment. Alors pourquoi utiliser TabHost?

Utilisez donc ViewPager avec TabLayout à la place.

Prons of Viewpager sur Tabhost:

  • ViewPager conserve les états Fragments. Le fragment moyen ne sera pas à nouveau recréé s'il est activé.
  • Fonctionnalité de balayage intégrée offrant à l'utilisateur une expérience plus fluide.
  • Consommation moins de ressources processeur, car Tabhost recrée Fragment/Activity plusieurs fois lorsque Tab est activé.

Regarde la différence : 

Utilisation de Tablayout + ViewPager (prend en charge le balayage, conserve les états de fragments)

Tablayout + ViewPager

Utilisation de TabHost (ne prend pas en charge le balayage, ne conserve pas les états)

TabHost

Petit code pour Tablayout + ViewPager

// find views by id
ViewPager viewPager = findViewById(R.id.viewpager);
TabLayout tabLayout = findViewById(R.id.tablayout);

// attach tablayout with viewpager
tabLayout.setupWithViewPager(viewPager);

ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

// add your fragments
adapter.addFrag(new SampleFragment(), "Tab1");
adapter.addFrag(new SampleFragment(), "Tab2");
adapter.addFrag(new SampleFragment(), "Tab3");

// set adapter on viewpager
viewPager.setAdapter(adapter);

Mise en page XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <com.google.Android.material.tabs.TabLayout
        Android:id="@+id/tablayout"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

    <androidx.viewpager.widget.ViewPager
        Android:id="@+id/viewpager"
        Android:layout_width="match_parent"
        Android:layout_height="0dp"
        Android:layout_weight="1" />

</LinearLayout>

Remarque Si vous n'utilisez pas encore AndroidX , vous devez modifier la disposition suivante.

  • Remplacez com.google.Android.material.tabs.TabLayout par Android.support.design.widget.TabLayout
  • Chagne androidx.viewpager.widget.ViewPager à Android.support.v4.view.ViewPager

Mais je vous recommande fortement de migrer vers AndroidX, voir @cette réponse pour comprendre pourquoi.

Et ceci est commonViewPagerAdapterpour tout votre Viewpager dans l'application.

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

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

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

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

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }

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

    public void addFrag(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }
}

Liens connexes importants

0
Khemraj