web-dev-qa-db-fra.com

Ajouter des icônes à SlidingTabLayout au lieu de texte

J'implémente SlidingTabLayout dans mon application Android. Ma question est que je voudrais implémenter des icônes dans mes onglets coulissants au lieu de textes pour la navigation. J'ai cherché beaucoup sur Internet pour un tel tutoriel ou échantillon mais n'en ai trouvé aucun. J'ai également cherché une question précédente sur stackoverflow: par ici - SlidingTabLayout avec icônes . C'était un peu informatif mais ne m'a pas vraiment aidé.

Pour être clair. J'ai besoin que mes onglets soient constitués de icônes uniquement. Pas de texte.

Comme je suis nouveau dans cette configuration, je vous serais reconnaissant de poster le code approprié avec une explication. Merci pour votre temps et vos efforts!

P.S.Andreaz Stuetz m'a aussi parlé du pagerslidingtabstrip et je me suis demandé si cela conviendrait mieux au type de chose que je recherche ...

Aussi: Voici à quoi je voudrais que mes onglets glissants ressemble. Découvrez le haut de cette image.

MODIFIER: MAINTENANT QUE Lollipop (AVEC LE DESIGN MATÉRIEL) EST SORTI. J'AI VU BEAUCOUP D'APPELS UTILISANT UN NOUVEAU "ICÔNE SEULE" SLIDING-TAB-LAYOUT SOUS LEUR BARRE DE TRAVAIL (Android 5.0 ACTION-BAR). IS LEUR TOUT NOUVEAU MOYEN DE METTRE EN OEUVRE CELA? MERCI UNE FOIS ENCORE!

See the Sliding Tabs on the top?

19
Adifyr

La clé est de renvoyer un SpannableString, contenant votre icône dans un ImageSpan, depuis la méthode getPageTitle (position) de votre PagerAdapter:

private int[] imageResId = {
        R.drawable.ic_tab_notifications,
        R.drawable.ic_tab_weather,
        R.drawable.ic_tab_calendar
};

@Override
public CharSequence getPageTitle(int position) {
    Drawable image = getResources().getDrawable(imageResId[position]);
    image.setBounds(0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight());
    SpannableString sb = new SpannableString(" ");
    ImageSpan imageSpan = new ImageSpan(image, ImageSpan.ALIGN_BOTTOM);
    sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return sb;
}

Normalement, cela suffirait, mais l'onglet par défaut créé par SlidingTabLayout effectue un appel à TextView#setAllCaps(true) qui désactive effectivement tous les ImageSpans. Vous devrez donc utiliser une vue à onglet personnalisée à la place:

res/layout/custom_tab.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:textSize="12sp"
    Android:textStyle="bold"
    Android:background="?android:selectableItemBackground"
    Android:padding="16dp"
    />

et où que vous installiez/liez votre ViewPager:

SlidingTabLayout slidingTabLayout = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
slidingTabLayout.setCustomTabView(R.layout.custom_tab, 0);
slidingTabLayout.setViewPager(viewPager);

(assurez-vous d'appeler setCustomTabView avant setViewPager)

41
Jeremy Dowdall

J'ai résolu le même problème, mais aussi en changeant de dessin sur l'onglet sélectionné.

Créez vos objets dessinables pour les onglets, avec deux états .

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@drawable/ic_selected" Android:state_selected="true"/>
    <item Android:drawable="@drawable/ic_normal"/>
</selector>

Créez votre propre adaptateur de pageur, à partir de PagerAdapter:

public class MyPagerAdapter extends PagerAdapter {

    private int[] drawablesIds = {
        R.drawable.first_tab_drawable,
        R.drawable.second_tab_drawable,
        R.drawable.third_tab_drawable
    };

    //Constructor and other standard funcs...

    public int getDrawableId(int position){
        //Here is only example for getting tab drawables
        return drawablesIds[position];
    }
    //...
}

Changer le code de SlidingTabLayout:

private void populateTabStrip() {
    //Here is no more standard PagerAdapter!
    final MyPagerAdapter adapter = (MyPagerAdapter) mViewPager.getAdapter();

    final View.OnClickListener tabClickListener = new TabClickListener();

    for (int i = 0; i < adapter.getCount(); i++) {
        View tabView = null;
        TextView tabTitleView = null;

        if (mTabViewLayoutId != 0) {
            // If there is a custom tab view layout id set, try and inflate it
            tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
                    false);
            tabTitleView = (TextView) tabView.findViewById(mTabViewTextViewId);
        }

        if (tabView == null) {
            tabView = createDefaultTabView(getContext());
        }

        if (tabTitleView == null && TextView.class.isInstance(tabView)) {
            tabTitleView = (TextView) tabView;
        }

        //Set icon, that can be changeable instead setting text.
        //I think the text also can setting here from getPageTitle func.
        //But we interesting only in icon
        tabTitleView.setCompoundDrawablesWithIntrinsicBounds(adapter.getDrawableId(i), 0, 0, 0);
        //Select tab if it is current
        if (mViewPager.getCurrentItem() == i){
            tabView.setSelected(true);
        }
        tabView.setOnClickListener(tabClickListener);

        mTabStrip.addView(tabView);
    }
}

Et rendre le titre TextView vraiment sélectionné également dans SlidingTabLayout dans InternalViewPagerListener:

    @Override
    public void onPageSelected(int position) {

        //Clear old selection and make new
        for(int i = 0; i < mTabStrip.getChildCount(); i ++){
            mTabStrip.getChildAt(i).setSelected(false);
        }
        mTabStrip.getChildAt(position).setSelected(true);

        if (mScrollState == ViewPager.SCROLL_STATE_IDLE) {
            mTabStrip.onViewPagerPageChanged(position, 0f);
            scrollToTab(position, 0);
        }

        if (mViewPagerPageChangeListener != null) {
            mViewPagerPageChangeListener.onPageSelected(position);
        }
    }

J'espère que ce sera utile pour quelqu'un.

6
v1k

Pour personnaliser SlidingTabLayout comme vous le souhaitez, il vous suffit de modifier la méthode populateTabStrip (): 

public void populateTabStrip() {
        final PagerAdapter adapter = mViewPager.getAdapter();
        final View.OnClickListener tabClickListener = new TabClickListener();

        for (int i = 0; i < adapter.getCount(); i++) {
            View tabView = null;

            tabView = LayoutInflater.from(getContext()).inflate(R.layout.tab_layout, mTabStrip,
                    false);

            ImageView iconImageView = (ImageView) tabView.findViewById(R.id.tab_layout_icon);
            iconImageView.setImageDrawable(getContext().getResources().getDrawable(getIconResourceArray()[i]));

            tabView.setOnClickListener(tabClickListener);

            mTabStrip.addView(tabView);
        }
    }

Votre mise en page pourrait être quelque chose comme ça: 

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

    <ImageView
        Android:id="@+id/tab_layout_icon"
        Android:layout_width="20dp"
        Android:layout_height="20dp"
        Android:layout_gravity="center" />
</LinearLayout>

La façon dont vous implémentez la méthode getResourceArray () dépend de vous. Voici comment j'ai fait: 

public class IconSlidingTabLayout extends HorizontalScrollView {
    private Integer[] mIconResourceArray;

    ...

    public Integer[] getIconResourceArray() {
        return mIconResourceArray;
    }

    public void setIconResourceArray(Integer[] mIconResourceArray) {
        this.mIconResourceArray = mIconResourceArray;
    }
}

Dans l'activité: 

mSlidingTabLayout = (IconSlidingTabLayout) findViewById(R.id.icon_sliding_tab_layout);
Integer[] iconResourceArray = { R.drawable.news_tab_icon,
        R.drawable.challenges_tab_icon, R.drawable.trophies_tab_icon,
        R.drawable.leaderboard_tab_icon };
mSlidingTabLayout.setIconResourceArray(iconResourceArray);

Sachez que pour avoir accès à R.layout.tab_layout *, vous devez importer yourpackage.R au lieu d'Android.R tel qu'il est par défaut dans SlidingTabStrip.

3
Samuel

Je sais que ce fil est assez ancien, mais je souhaitais néanmoins partager ma solution à ce problème, car elle pourrait être utile à certains . Cela fonctionne assez bien, même pour différents tirables en fonction de l'état sélectionné.

Tout d'abord, j'ai défini deux tableaux dans la classe SlidingTabLayout (cela pourrait facilement être externalisé vers une autre classe):

private int[] imageResId = {
        R.drawable.multi_random,
        R.drawable.single_random,
        R.drawable.known_person,
};

private int[] imageResSelected = {
        R.drawable.multi_random_selected,
        R.drawable.single_random_selected,
        R.drawable.known_person_selected
};

private int mOldPosition = 0;

Maintenant, nous modifions la méthode populateTabStrip() dans la SlidingTabLayout:

 for (int i = 0; i < adapter.getCount(); i++) {
            View tabView = null;
            ImageView tabImageView = null;

            if (mTabViewLayoutId != 0) { // HAS TO BE SET FOR THE MOMENT!
                // If there is a custom tab view layout id set, try and inflate it
                tabView = LayoutInflater.from(getContext()).inflate(mTabViewLayoutId, mTabStrip,
                        false);
                tabImageView = (ImageView) tabView.findViewById(mTabViewTextViewId);
            }

            if (tabView == null) {
                tabView = createDefaultTabView(getContext());
            }

            if (tabImageView == null && ImageView.class.isInstance(tabView)) {
                tabImageView = (ImageView) tabView;
            }

            int resourceId;
            if (i == mViewPager.getCurrentItem()) {
                resourceId = imageResSelected[i];
                mOldPosition = i;
            } else {
                resourceId = imageResId[i];
            }
            tabImageView.setImageResource(resourceId);
            tabView.setOnClickListener(tabClickListener);

            mTabStrip.addView(tabView);
        }

Pour mettre à jour l'image en fonction de l'onglet sélectionné, nous ajoutons quelques lignes à la méthode onPageSelected

// This Method is called once the transition is finished
// Change the drawable of the old one..
ImageView view = (ImageView) mTabStrip.getChildAt(mOldPosition);
view.setImageResource(imageResId[mOldPosition]);

// And now change it of the current one
view = (ImageView) mTabStrip.getChildAt(position);
view.setImageResource(imageResSelected[position]);

mOldPosition = position;

Enfin, nous devons ajouter une vue par onglet personnalisée:

mSlidingTabLayout.setCustomTabView(R.layout.custom_tab, 0);

Comme celui-ci

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:Android="http://schemas.Android.com/apk/res/Android"
          Android:layout_width="0dp"
          Android:layout_height="wrap_content"
          Android:padding="16dp"
          Android:layout_weight="1"
          Android:src="@drawable/multi_random"
        />

Cette solution est loin d’être parfaite, mais répond à mes besoins. Peut-être que je pourrais aider quelqu'un avec ça.

1
puelo

Votre adaptateur doit implémenter PagerSlidingTabStrip.IconTabProvider.

Ensuite, dans getPageIconResIdvous pouvez retourner l'id de la ressource image:

public class ViewPagerAdapter extends FragmentPagerAdapter implements 
PagerSlidingTabStrip.IconTabProvider {

   private static final int[] icons = {R.drawable.image1, R.drawable.image2, R.drawable.image3};

    @Override
    public int getPageIconResId(int i) {
        return icons[i];
    }
}

Gardez à l'esprit que seule l'image sera affichée, pas le texte.

1
klimat

Ok .. il y a beaucoup de façons de mettre en œuvre ce changement. Ceci est le plus rapide et le plus sale, juste pour l’idée ..

Substituez la méthode SlidingTabLayout.populateTabStrip () pour cela.

    private void populateTabStrip() {
    final OnClickListener tabClickListener = new TabClickListener();

    View tabView = LayoutInflater.from(getContext()).inflate(R.layout.tab_notif_icon_only, mTabStrip, false);
    tabView.setOnClickListener(tabClickListener);
    mTabStrip.addView(tabView);

    tabView = LayoutInflater.from(getContext()).inflate(R.layout.tab_weather_icon_only, mTabStrip, false);
    tabView.setOnClickListener(tabClickListener);
    mTabStrip.addView(tabView);

    tabView = LayoutInflater.from(getContext()).inflate(R.layout.tab_calendar_icon_only, mTabStrip, false);
    tabView.setOnClickListener(tabClickListener);
    mTabStrip.addView(tabView);

Créez chaque mise en page de cette manière LinearLayout> Éléments ImageView, src pointant sur l’icône ..

1
Tom

J'ai suivi la réponse de Jeremy et tout fonctionne bien. Autant que je sache, il n’ya pas de nouveau moyen de le faire. La plupart des applications suppriment maintenant complètement la barre d’outils et ajoutent un slidetabstrip personnalisé recommandé par Google. 

Si vous avez des questions spécifiques, faites le moi savoir. mon application ressemble beaucoup à la capture d'écran que vous avez publiée. Je pense que cette mise à jour de la conception matérielle se concentrait davantage sur l'activation d'animations et d'effets personnalisés.

0
Varun Agarwal

J'ai récemment implémenté cette bibliothèque appelée ViewPagerAddons. Il inclut SlidingTabLayoutColors, ce qui est exactement ce dont vous avez besoin. Laissez simplement votre adaptateur de pageur implémenter l'interface SlidingTabLayouColors.ImageProvider, remplacer la méthode getPageImage et renvoyer les identificateurs de ressources d'image en fonction des positions de page. Simple. 

Voici le lien vers la bibliothèque (instructions d'installation incluses): https://bitbucket.org/enthusiast94/viewpageraddons/src

0
Manas Bajaj

Vérifiez cette solution lien androidhive sur les onglets de conception des matériaux/viewpager

Un très bon site sur les solutions Android. J'espère que vous trouverez une solution.

0
Chirag thaker

Je viens juste de renvoyer null de la méthode getPageTitle():

@Override
 public CharSequence getPageTitle(int position) {
    return null;
}
0
ojonugwa ochalifu