Android 将图标添加到 SlidingTabLayout 而不是文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23472759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:11:28  来源:igfitidea点击:

Add Icons to SlidingTabLayout instead of Text

androidandroid-viewpagerandroid-tabsandroid-iconspagerslidingtabstrip

提问by Adifyr

I'm implementing a SlidingTabLayout in my android application. What my query is that I'd like to implement icons in my Sliding Tabs instead of texts for navigation. I searched heavily on the internet for any such tutorial or sample but found none. I also searched a previous question on stackoverflow: Over Here - SlidingTabLayout with Icons. It was slightly informative but didn't really help me out.

我正在我的 android 应用程序中实现一个 SlidingTabLayout。我的查询是我想在我的滑动选项卡中实现图标而不是用于导航的文本。我在互联网上大量搜索任何此类教程或示例,但没有找到。我还搜索了有关 stackoverflow 的上一个问题:Over Here - SlidingTabLayout with Icons。它提供了一些信息,但并没有真正帮助我。

To be clear. I require my tabs to consist of icons only. No text.

要清楚。我要求我的标签只包含图标。没有文字。

As I am new to this whole setup, I'd appreciate if you'd post proper code with an explanation. Thank you for your time and effort!

由于我是整个设置的新手,如果您能发布带有解释的正确代码,我将不胜感激。感谢您的时间和精力!

P.S.I also heard about the pagerslidingtabstrip by Andreaz Stuetz and wondered if that would be more suitable for the type of thing I'm going for...

PS我还听说过 Andreaz Stuetz 的 pagerslidingtabstrip 并想知道这是否更适合我想要的类型...

Also:Here is what I would like my sliding tabs to look like. Check out the top of this image.

另外:这是我希望我的滑动标签的样子。查看此图像的顶部。

EDIT : NOW THAT LOLLIPOP (WITH MATERIAL DESIGN) HAS COME OUT. I HAVE SEEN A LOT OF APPS USING A NEW "ONLY ICON" SLIDING-TAB-LAYOUTBELOW THEIR TOOLBAR (ANDROID 5.0 ACTION-BAR). IS THEIR ANY NEW WAY TO IMPLEMENT THIS?? THANKS ONCE AGAIN!

编辑:现在棒棒糖(带材料设计)已经出来了。我已经看到很多应用SLIDING-TAB-LAYOUT程序在工具栏下方使用新的“唯一图标” (Android 5.0 操作栏)。他们有什么新的实现方式吗??再次感谢!

See the Sliding Tabs on the top?

看到顶部的滑动标签了吗?

回答by Jeremy Dowdall

The key to this is to return a SpannableString, containing your icon in an ImageSpan, from your PagerAdapter's getPageTitle(position) method:

这样做的关键是从 PagerAdapter 的 getPageTitle(position) 方法返回一个 SpannableString,其中包含 ImageSpan 中的图标:

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;
}

Normally this be would be enough, but the default tab created by SlidingTabLayout makes a call to TextView#setAllCaps(true)which effectively disables all ImageSpans, so you'll have to use a custom tab view instead:

通常这已经足够了,但是由 SlidingTabLayout 创建的默认选项卡会调用TextView#setAllCaps(true)它有效地禁用所有 ImageSpans,因此您必须使用自定义选项卡视图:

res/layout/custom_tab.xml

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"
    />

and where ever you setup/bind to your ViewPager:

以及您在何处设置/绑定到 ViewPager:

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

(make sure to call setCustomTabViewbefore setViewPager)

(请确保调用setCustomTabView之前setViewPager

回答by v1k

I solved same problem, but also with changing drawable on selected tab.

我解决了同样的问题,但也改变了选定选项卡上的可绘制对象。

Create your drawables for tabs, with two states. first_tab_drawable.xml, second_tab_drawable.xml, third_tab_drawable.xml:

为选项卡创建可绘制对象,具有两种状态。first_tab_drawable.xml、second_tab_drawable.xml、third_tab_drawable.xml:

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

Create your own pager adapter, extends from PagerAdapter:

创建您自己的寻呼适配器,从 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];
    }
    //...
}

Change code of SlidingTabLayout:

更改 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);
    }
}

And make really selected TextView title also in SlidingTabLayout in InternalViewPagerListener:

并在 InternalViewPagerListener 的 SlidingTabLayout 中制作真正选定的 TextView 标题:

    @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);
        }
    }

Hope it will be helpful for somebody.

希望它会对某人有所帮助。

回答by Samuel

To customize SlidingTabLayout the way you want, you only need to modify the method populateTabStrip():

要以您想要的方式自定义 SlidingTabLayout,您只需要修改 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);
        }
    }

Your layout could be something like that:

您的布局可能是这样的:

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

The way you implement the getResourceArray() method is up to you. Here is how I did:

实现 getResourceArray() 方法的方式取决于您。这是我的做法:

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

    ...

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

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

In the activity:

在活动中:

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);

Be aware that in order to have access to R.layout.tab_layout*, you have to import yourpackage.R instead of android.R as it is by default in SlidingTabStrip.

请注意,为了访问 R.layout.tab_layout*,您必须导入 yourpackage.R 而不是 android.R,因为它在 SlidingTabStrip 中是默认的。

回答by klimat

Your Adapter should implements PagerSlidingTabStrip.IconTabProvider.

您的适配器应该实现PagerSlidingTabStrip.IconTabProvider.

Then in getPageIconResIdyou can return id of image resource:

然后getPageIconResId你可以返回图像资源的id:

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];
    }
}

Keep in mind that only image will be shown, text won't.

请记住,只会显示图像,不会显示文本。

回答by Tom

Ok.. there are many ways of implementing this change. This is the most quick and dirty one, just for the idea..

好的.. 有很多方法可以实现这种变化。这是最快速和最脏的一个,只是为了这个想法..

Substitue the method SlidingTabLayout.populateTabStrip() for this..

将方法 SlidingTabLayout.populateTabStrip() 替换为此..

    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);

Create each layout this way LinearLayout > ImageView elements, src pointing to icon..

以这种方式创建每个布局 LinearLayout > ImageView 元素,src 指向图标..

回答by puelo

I know that this thread if fairly old, but i wanted to share my solution to this problem nevertheless, because it might be helpful for some. It works quite nice, even for different drawables depending on the selected state.

我知道这个线程已经很老了,但我还是想分享我对这个问题的解决方案,因为它可能对某些人有帮助。它工作得非常好,即使根据所选状态对于不同的可绘制对象也是如此。

First of i did define two array inside the SlidingTabLayoutclass (this could easily be outsourced to another class):

首先,我确实在SlidingTabLayout类中定义了两个数组(这很容易外包给另一个类):

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;

Now we alter the populateTabStrip()method inside the SlidingTabLayout:

现在我们改变populateTabStrip()里面的方法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);
        }

To update the image according to which tab is selected we add some lines to the onPageSelectedmethod

要根据选择的选项卡更新图像,我们在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;

Finally we need to add a custom Tab View:

最后我们需要添加一个自定义的 Tab View:

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

Like this one

像这个

<?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"
        />

This solution is far from perfect, but works for my needs. Maybe i could help someone with this.

这个解决方案远非完美,但适合我的需求。也许我可以帮助某人。

回答by Manas Bajaj

I recently implemented this library called ViewPagerAddons. It includes SlidingTabLayoutColors, which is exactly what you need. Simply let your pager adapter implement SlidingTabLayouColors.ImageProviderinterface, override getPageImagemethod and return the image resource ids according to the page positions. Simple.

我最近实现了这个名为ViewPagerAddons. 它包括SlidingTabLayoutColors,这正是您所需要的。只需让您的寻呼机适配器实现SlidingTabLayouColors.ImageProvider接口,覆盖getPageImage方法并根据页面位置返回图像资源 ID。简单的。

Here's the link to the library (set up instructions included): https://bitbucket.org/enthusiast94/viewpageraddons/src

这是库的链接(包括设置说明):https: //bitbucket.org/anthrop94/viewpageraddons/src

回答by Varun Agarwal

I followed Jeremy's answer and its working fine. AFAIK there is no new way of doing this. Most apps are now removing the toolbar altogether and adding a custom slidingtabstrip recommended by google.

我遵循了 Jeremy 的回答并且它工作正常。AFAIK 没有新的方法可以做到这一点。大多数应用程序现在完全删除工具栏并添加谷歌推荐的自定义滑动条。

If you have any specific questions let me know. iv got my app looking a lot like the screenshot you have posted. I feel this material design update was focusing more on enabling custom animations and effects.

如果您有任何具体问题,请告诉我。iv 让我的应用程序看起来很像您发布的屏幕截图。我觉得这次 Material Design 更新更侧重于启用自定义动画和效果。

回答by Ojonugwa Jude Ochalifu

Just returning nullfrom the getPageTitle()method did it for me:

刚刚null从该getPageTitle()方法返回为我做了:

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

回答by Chirag thaker

Check this solution link androidhive about material design tabs /viewpager

检查此解决方案链接 androidhive 关于材料设计选项卡/viewpager

A very good website about android solutions. Hope you will find a solution.

一个非常好的关于 android 解决方案的网站。希望你能找到解决办法。