Иконки в TabLayout

У меня есть простой AppCompatActivity с одним простым Toolbar (android.support.v7.widget.Toolbar), одной библиотекой дизайна TabLayout и одной ViewPager.

Теперь у меня есть в этом случае 4 фрагмента, которые находятся внутри вьюпейджера и могут быть пролистаны с боков. Это прекрасно работает. Но как только я использую mTabLayout.setupWithViewPager(mViewPager);, значки исчезают, но я могу использовать табуляцию на пустых местах, что отлично работает. Если я уберу строку, значки снова станут видны, «свайп» работает, но если я перейду к значку, ничего не произойдет.

Мой код

Основная активность

public class MainActivity extends AppCompatActivity {

    private Toolbar mToolbar;
    private TabLayout mTabLayout;
    private ViewPager mViewPager;
    private ViewPagerAdapter mAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initToolbar();
        initTabLayout();
        initViewPager();

        mTabLayout.setupWithViewPager(mViewPager);//Here is the code from above
        mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));

    }

    private void initToolbar() {
        mToolbar = (Toolbar) findViewById(R.id.app_bar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);

    }

    private void initTabLayout() {
        mTabLayout = (TabLayout) findViewById(R.id.tabLayout);
        mTabLayout.addTab(mTabLayout.newTab().setIcon(R.drawable.ic_fire_white));
        mTabLayout.addTab(mTabLayout.newTab().setIcon(R.drawable.ic_apps_white));
        mTabLayout.addTab(mTabLayout.newTab().setIcon(R.drawable.ic_account_plus_white));
        mTabLayout.addTab(mTabLayout.newTab().setIcon(R.drawable.ic_help_white));

    }

    private void initViewPager() {
        mAdapter = new ViewPagerAdapter(getSupportFragmentManager(), MainActivity.this);
        mViewPager = (ViewPager) findViewById(R.id.viewPager);
        mViewPager.setAdapter(mAdapter);

    }

    //MENUE STUFF

}

//ViewPagerAdapter
class ViewPagerAdapter extends FragmentStatePagerAdapter {

    public static final int TABS_COUNT = 4;
    private Context context;

    public ViewPagerAdapter(FragmentManager fm, Context context) {
        super(fm);
        this.context = context;
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0: return new HomeFragment1();
            case 1: return new HomeFragment2();
            case 2: return new HomeFragment3();
            case 3: return new HomeFragment4();
        }
        return null;
    }

    @Override
    public int getCount() {
        return TABS_COUNT;
    }

}

activity_main.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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">

    <include
        android:id="@+id/app_bar"
        layout="@layout/app_bar" />

    <android.support.design.widget.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/primary"
        app:tabGravity="fill"
        app:tabMode="fixed"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

person DominikTV    schedule 25.06.2015    source источник


Ответы (3)


setupWithViewPager() создайте экземпляр Tab, у которого есть только заголовок, предоставленный из ViewPager.Adapter. Конечно, вы можете переопределить этот метод примерно так:

public class IconicTabLayout extends TabLayout {

    private TabViewProvider mTabViewProvider;

    public interface TabViewProvider {
        Tab newTabInstance(int tabPosition);
    }

    public IconicTabLayout(Context context) {
        super(context);
    }

    public IconicTabLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public IconicTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setTabProvider(TabViewProvider provider){
        mTabViewProvider = provider;
    }

    @Override
    public void setupWithViewPager(ViewPager viewPager) {
        PagerAdapter adapter = viewPager.getAdapter();
        if (adapter == null) {
            throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set");
        } else {
            this.setTabsFromPagerAdapter(adapter);
            viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(this));
            this.setOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
        }

    }

    @Override
    public void setTabsFromPagerAdapter(PagerAdapter adapter) {
        removeAllTabs();
        mTabViewProvider = mTabViewProvider == null && adapter instanceof TabViewProvider? (TabViewProvider)adapter : null;
  if(mTabViewProvider == null){   
        super.setTabsFromPagerAdapter(adapter);
    }else{
        for (int i = 0, count = adapter.getCount(); i < count; ++i) {
            this.addTab(mTabViewProvider.newTabInstance(i));
        }

    }
   }
}

Использование:

 mIconicTabLayout.setTabProvider(new TabViewProvider() {
        @Override
        public Tab newTabInstance(int tabPosition) {
            return mIconicTabLayout.newTab().setIcon(icons[position]);
        }
    });
    mIconicTabLayout.setupWithViewPager(mViewPager);

Or

class ViewPagerAdapter extends FragmentStatePagerAdapter implements TabViewProvider{

   public void setTabLayout(TabLayout t){
      mTabLayout = t;
   }
  //...

    @Override
    public Tab newTabInstance(int position) {
                return mTabLayout.newTab().setIcon(icons[position]);
            }

}

Примечание. Убедитесь, что вы сначала вызываете метод setTabProvider или свою PagerAdapter реализацию TabViewProvider, в противном случае она вызовет реализацию по умолчанию.

person Nikola Despotoski    schedule 27.06.2015
comment
При использовании первого метода у меня не отображаются значки на вкладках. Я пробовал как файлы PNG, так и XML (используя селекторы). Оба не работали. При использовании второго метода значки могут время от времени мигать, особенно когда я использую exitFadeDuration в селекторах или быстро смахиваю. Как так? - person android developer; 05.08.2015

Вы должны инициировать и добавить значки внутри PagerAdapter.

private int[] imageResId = {
    R.drawable.ic_one,
    R.drawable.ic_two,
    R.drawable.ic_three
};

// ...

@Override
public CharSequence getPageTitle(int position) {
   // Generate title based on item position
 // return tabTitles[position];
Drawable image = context.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;
}

Источник

person lagos    schedule 29.06.2015
comment
Хотя я бы не назвал это правильным ответом, я ставлю ему +1 за изобретательность. Однако лучшим способом было бы использовать setIcon() на вкладке. - person Moritz; 17.07.2015
comment
Я не знаю. Есть пример кода, который вы могли бы показать? @androiddeveloper - person lagos; 19.08.2015
comment
Не видно, что Крис Бейнс добавляет и текст, и значки. ;) - person lagos; 19.08.2015
comment
@androiddeveloper У меня была та же проблема, что и у вас, и чертежи не отображались в заголовке. В ответе lagos отсутствует только одна часть, и проблема в том, что стиль метки вкладки имеет свойство textAllCaps, установленное на true что предотвратит визуализацию ImageSpan! Итак, вам просто нужен собственный стиль для вашего TabLayout, где для textAllCaps установлено значение false. Дополнительную информацию и необходимые стили можно найти здесь: ссылка - person Karuma; 22.10.2015
comment
Это показало значки, но они потеряли возможность выбора (они не меняли цвет при нажатии). - person galaxigirl; 08.06.2019

Другой подход — не вызывать setupWithViewPager(). Вместо этого вы можете удерживать List из Tabs и использовать PagerListener для выбора правильного Tab.

Что-то вроде этого:

private List<TabLayout.Tab> tabList;

private void initTabLayout() {
    tabList = new ArrayList<>();
    tabList.add(mTabLayout.newTab().setIcon(R.drawable.ic_fire_white));
    tabList.add(mTabLayout.newTab().setIcon(R.drawable.ic_apps_white));
    tabList.add(mTabLayout.newTab().setIcon(R.drawable.ic_account_plus_white));
    tabList.add(mTabLayout.newTab().setIcon(R.drawable.ic_help_white));
    for (TabLayout.Tab tab : tabList){
        mTabLayout.addTab(tab);
    }
    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            tabList.get(position).select();
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

}
person yshahak    schedule 06.11.2016