19

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

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

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

PS 我还听说了 Andreaz Stuetz 的 pagerslidingtabstrip,想知道这是否更适合我想要的东西......

另外:这是我希望我的滑动标签看起来的样子。看看这张图片的顶部。

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

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

4

11 回答 11

41

关键是从 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;
}

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

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

以及您在哪里设置/绑定到您的 ViewPager:

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

setCustomTabView(一定要提前打电话setViewPager

于 2014-05-27T15:50:45.320 回答
6

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

为选项卡创建可绘制对象,具有两种状态。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>

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

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

并在 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);
        }
    }

希望它对某人有所帮助。

于 2014-11-14T16:14:39.537 回答
3

想要按照自己的方式自定义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);
        }
    }

您的布局可能是这样的:

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

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

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

    ...

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

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

在活动中:

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

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

于 2014-11-14T17:32:01.717 回答
1

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 SlidingTabLayout class (this could easily be outsourced to another class):

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:

 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 onPageSelected method

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

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.

于 2014-11-01T23:21:35.367 回答
1

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

用方法 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);

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

于 2014-06-12T01:50:36.620 回答
1

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

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

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

于 2015-02-06T23:51:36.307 回答
0

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

这是图书馆的链接(包括设置说明):https ://bitbucket.org/modal94/viewpageraddons/src

于 2014-09-03T16:56:54.713 回答
0

我按照杰里米的回答和它的工作正常。AFAIK 没有新的方法可以做到这一点。大多数应用程序现在完全删除工具栏并添加谷歌推荐的自定义滑动标签条。

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

于 2015-08-15T06:14:51.697 回答
0

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

@Override
 public CharSequence getPageTitle(int position) {
    return null;
}
于 2015-12-31T05:53:27.503 回答
0

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

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

于 2016-02-16T09:37:15.860 回答
-1

从 FragmentActivity 扩展您的主要活动。当我们添加选项卡时,还要从 ActionBar.TabListener 实现这个类

// 用于添加标签

for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setIcon(R.drawable.drawable_id)
.setTabListener(this));
}

在这里检查。

于 2014-05-05T13:12:33.110 回答