Таблетка только с иконками

Я использую поддержку дизайна для создания вкладок. Я также использую ViewPager для перелистываемых вкладок.

Теперь я не знаю, как использовать только значки вместо текста во вкладках. Я пытался выяснить, но не добился никакого успеха.

Мой код:

Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    viewPager = (ViewPager) findViewById(R.id.pager);
    setupViewPager(viewPager);
    setupTablayout();
}

private void setupTablayout() {
    tabLayout = (TabLayout) findViewById(R.id.tabLayout);
    tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
    tabLayout.setupWithViewPager(viewPager);
}

class MyPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

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

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

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

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

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

private void setupViewPager(ViewPager viewPager) {
    MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
    adapter.addFrag(new frag(), "CAT");
    adapter.addFrag(new frag(), "DOG");
    adapter.addFrag(new frag(), "BIRD");
    viewPager.setAdapter(adapter);
}

person androGuy    schedule 17.06.2015    source источник
comment
попробуйте растягиваемые тексты. попробуйте мой ответ здесь . Голосуйте, если это поможет.   -  person Harry's Lab    schedule 17.06.2015


Ответы (12)


Один из подходов — установка значков после Метод TabLayout.setupWithViewPager().

mTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
  mTabLayout.getTabAt(i).setIcon(R.drawable.your_icon);
}
person user802421    schedule 18.06.2015
comment
Спасибо - офигенно. - person Simon; 17.12.2015
comment
В моем случае это решение отображает и значок, и текст, что мне и нужно :-) - person Felix; 17.01.2017
comment
Это покажет текст, если вы переопределите getPageTitle в своем адаптере пейджера, в противном случае будет отображаться только значок - person bkach; 17.07.2017
comment
это решение не работает в 27.1.0, но если я переопределю getPageTitle, вместо этого будет отображаться только заголовок - person Zulqurnain Jutt; 05.03.2018
comment
это происходит, если вы выполняете adapter.notifyDataSetChanged() до - person Kibotu; 19.10.2018

Учебник, показанный по следующей ссылке, должен охватывать то, что вы хотите. https://github.com/codepath/android_guides/wiki/Google-Play-Style-Tabs-using-TabLayout#add-icons-to-tablayout

Я скопировал соответствующий раздел ниже.

Добавляем иконки в TabLayout

В настоящее время класс TabLayout не предоставляет чистую модель абстракции, позволяющую размещать значки на вкладке. Существует много опубликованных обходных путей, один из которых заключается в том, чтобы вернуть SpannableString, содержащую ваш значок в ImageSpan, из метода getPageTitle(position) вашего 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;
}

По умолчанию вкладка, созданная TabLayout, задает для свойства textAllCaps значение true, что предотвращает визуализацию ImageSpans. Вы можете переопределить это поведение, изменив свойство tabTextAppearance.

  <style name="MyCustomTabLayout" parent="Widget.Design.TabLayout">
        <item name="tabTextAppearance">@style/MyCustomTextAppearance</item>
  </style>

  <style name="MyCustomTextAppearance" parent="TextAppearance.Design.Tab">
        <item name="textAllCaps">false</item>
  </style>
person user4989692    schedule 18.06.2015
comment
На вкладке не отображаются значки, даже установка textAllCaps = false ничего не делает - person pnavk; 27.10.2015
comment
Когда я пытаюсь создать свой код, я получаю эту ошибку: не найден идентификатор ресурса для атрибута «tabTextAppearance» в пакете «android» - person Akah; 03.02.2016
comment
Одна вещь, которую я заметил с помощью этой техники, заключается в том, что размер текста будет меняться, когда значки видны. - person ZaBlanc; 04.02.2016
comment
Спасибо, парень, свойство textAllCaps решило мою проблему с иконками. - person tryp; 17.11.2016

В новой версии TabLayout Google добавил TabItem, который легко может добавить значок через ваш XML с помощью следующего кода:

<android.support.design.widget.TabLayout
         app:tabTextColor="@color/gray"
         app:tabMode="fixed"
         app:tabBackground="@color/red"
         app:tabIndicatorHeight="4dp"
         app:tabIndicatorColor="@color/purple"
         app:tabPadding="2dp"
         app:tabSelectedTextColor="@color/white"
         app:tabMinWidth="64dp"
         android:layout_height="wrap_content"
         android:layout_width="match_parent">

     <!--add height and width to TabItem -->
     <android.support.design.widget.TabItem 
             android:text="@string/tab_text"/>

     <android.support.design.widget.TabItem
             android:icon="@drawable/ic_android"/>

 </android.support.design.widget.TabLayout>

Подробнее см. здесь.

person Amir    schedule 01.06.2016
comment
это реальный способ добавить значки :) - person Anand Savjani; 18.10.2016
comment
При использовании с пейджером просмотра, пейджер просмотра вызывает метод removeAllTabs(), который удаляет все элементы вкладок, добавленные через файл макета. - person JDL; 19.01.2017
comment
Не работает, при использовании PagerAdapter вкладки сбрасываются, и показываются только заголовки, взятые с адаптера. - person ballzak; 10.08.2019

попробуй это

    public class GlobalActivity extends AppCompatActivity {
    Toolbar toolbar;
    ViewPager viewPager;
    TabLayout tabLayout;
    ViewPagerAdapter adapter;
    private int[] tabIcons = {
            R.drawable.home_ic,
            R.drawable.biz_ic,
            R.drawable.network_ic,
            R.drawable.offers_ic,
            R.drawable.message_ic_b
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_global_hub);
        tab();
    }
    public void tab(){
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager(viewPager);
        tabLayout = (TabLayout) findViewById(R.id.tablayout);
        tabLayout.setupWithViewPager(viewPager);
        setupTabIcons();

    }
    private void setupTabIcons() {
        tabLayout.getTabAt(0).setIcon(tabIcons[0]);
        tabLayout.getTabAt(1).setIcon(tabIcons[1]);
        tabLayout.getTabAt(2).setIcon(tabIcons[2]);
        tabLayout.getTabAt(3).setIcon(tabIcons[3]);
        tabLayout.getTabAt(4).setIcon(tabIcons[4]);

    }
    public void setupViewPager(ViewPager viewPager){
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new GlHubFragment(),"HOME");
        adapter.addFrag(new BizForumFragment(), "BIZ FORUM");
        adapter.addFrag(new NetworkFragment(), "NETWORK");
        adapter.addFrag(new MessagesFragment(), "MESSAGEs");
        adapter.addFrag(new OfferFragmentActivity(), "OFFER");
        viewPager.setAdapter(adapter);
    }

    public class ViewPagerAdapter extends FragmentPagerAdapter{
        private final List<Fragment> mfragmentlist =new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
        public ViewPagerAdapter(FragmentManager fm) {
            super(fm);
        }

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

        @Override
        public int getCount() {
            return mfragmentlist.size();
        }
        public void addFrag(Fragment fragment,String title){
            mfragmentlist.add(fragment);
            mFragmentTitleList.add(title);
        }
        @Override
        public CharSequence getPageTitle(int position){
            return mFragmentTitleList.get(position);
        }
    }
}
person Rahul Vishwakarma    schedule 27.05.2016

Самый простой способ использовать значки, который я нашел, - это использовать Tablayout.Tab.setIcon(drawable). Это также упрощает выделение выбранного значка. Если вы хотите сделать это, выполните следующие действия.

Шаг 1. Добавьте изображения в папки res.mipmap. (mipmap-mdpi, hdpi и т. д.) Судя по другим ответам здесь, также можно поместить их в папки res.drawable.

Шаг 2. Вызовите setIcon на всех вкладках после настройки TabLayout и ViewPager. Я сделал это в своих адаптерах, чтобы поддерживать порядок в Activity. Итак, в своей деятельности сделайте следующее:

    tablayout = (TabLayout) findViewById(R.id.tab_layout);
    viewPager = (ViewPager) findViewById(R.id.viewPager);
    adapterTabs = new AdapterTabs(this, getSupportFragmentManager(), fragments, tablayout, viewPager);

    viewPager.setAdapter(adapterTabs);
    tablayout.setupWithViewPager(viewPager);
    adapterTabs.setTabIcons();

и в ваших адаптерах, которые должны расширять FragmentPagerAdapter, поместите свой метод setTabIcons().

    public void setTabTitlesToIcons() {
    Drawable icon1 = context.getResources().getDrawable(R.mipmap.ic_1);
    Drawable icon2 = context.getResources().getDrawable(R.mipmap.ic_2);
    Drawable icon3 = context.getResources().getDrawable(R.mipmap.ic_3);
    Drawable icon1Hilighted = context.getResources().getDrawable(R.mipmap.ic_1_selected);
    Drawable icon2Hilighted = context.getResources().getDrawable(R.mipmap.ic_2_selected);
    Drawable icon3Hilighted = context.getResources().getDrawable(R.mipmap.ic
    public AdapterTabs(Context context, FragmentManager fragmentManager, List<Fragment> fragments, TabLayout tabLayout, ViewPager viewPager) {
    super(fragmentManager);
    this.context = context;
    this.tabLayout = tabLayout;
    this.viewPager = viewPager;
    this.viewPager.addOnPageChangeListener(this);

    tabs.add(fragments.get(0));
    tabs.add(fragments.get(1));
    tabs.add(fragments.get(2));
}
selected); icons.add(icon1); icons.add(icon2); icons.add(icon3); iconsHilighted.add(icon1Hilighted); iconsHilighted.add(icon2Hilighted); iconsHilighted.add(icon3Hilighted); for(int i = 0; i < icons.size(); i++) { if(i == 0) { //noinspection ConstantConditions tabLayout.getTabAt(i).setIcon(iconsSelected.get(i)); } else { //noinspection ConstantConditions tabLayout.getTabAt(i).setIcon(icons.get(i)); } } }

Обязательно сохраните ссылку на два списка «значки» и «значкиHilighted». Они понадобятся вам позже. Также сохраните ссылку на TabLayout и ViewPager, которые вы передали из действия.

Шаг 3. Убедитесь, что AdapterTabs.getPageTitle() возвращает значение null. На этом этапе, если вы запустите его, вы должны увидеть, что первый значок выделен.

Шаг 4. Реализуйте ViewPager.OnPageChangeListener в AdapterTabs и добавьте этот прослушиватель в свой viewPager.

    public AdapterTabs(Context context, FragmentManager fragmentManager, List<Fragment> fragments, TabLayout tabLayout, ViewPager viewPager) {
    super(fragmentManager);
    this.context = context;
    this.tabLayout = tabLayout;
    this.viewPager = viewPager;
    this.viewPager.addOnPageChangeListener(this);

    tabs.add(fragments.get(0));
    tabs.add(fragments.get(1));
    tabs.add(fragments.get(2));
}

Шаг 5. Обновите значки на вкладках в обратном вызове onPageSelected в AdapterTabs.

    @Override
public void onPageSelected(int position) {
    for (int i = 0; i < tabs.size(); i++) {
        if(i == position) {
            //noinspection ConstantConditions
            tabLayout.getTabAt(i).setIcon(iconsSelected.get(i));
        }
        else {
            //noinspection ConstantConditions
            tabLayout.getTabAt(i).setIcon(icons.get(i));
        }
    }
}

Теперь вы должны видеть, что выделенный значок обновляется при смене вкладок.

person ninjachippie    schedule 10.11.2015
comment
У вас есть специальные чертежи для этого, называемые селекторами, в которых вы можете настроить различные состояния. - person Roel; 09.02.2016
comment
Да, это правильно, но почему значки удаляются, когда вы выбираете новую Вкладку, которой нет в кеше? Они не остаются, и поэтому их необходимо повторно вставить в .onPageSelected. Действительно глупое решение. Жук? - person carl; 23.07.2019
comment
Я думаю, тебе нужно поработать над своими навыками общения, @carl. Поэтому никаких дальнейших комментариев от меня. - person ninjachippie; 29.07.2019

Ни один из этих методов не является элегантным при использовании TabLayout в качестве сценария "декора" ViewPager. Документация по TabLayout. простое расширение TabLayout и PagerAdapter, обеспечивающее простую замену TabLayout, которое можно использовать в любом сценарии без добавления вручную значков вне класса TabLayout и после использования PagerAdapter для получения информации о вкладке.

/**
 * Created by JDL on 1/18/2017.
 */
public class TabLayoutExt extends TabLayout {

    protected ViewPager mViewPager;

    public abstract static class TabLayoutViewPagerAdapter extends PagerAdapter {
        public TabLayoutViewPagerAdapter() {
        }

        /**
         * This method may be called by the TabLayout to obtain an icon drawable
         * to for the specified tab. This method may return null
         * indicating no tab icon for this page. The default implementation returns
         * null.
         *
         * @param position The position of the title requested
         * @return A drawable icon for the requested page
         */
        public Drawable getPageIcon(Context context, int position) {
            return null;
        }
    }

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

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

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

    @Override
    protected void onAttachedToWindow() {
        //Cover the implicit setup in TabLayout
        if (mViewPager == null) {
            final ViewParent vp = getParent();
            if (vp instanceof ViewPager) {
                mViewPager = (ViewPager)vp;
            }

        }
        super.onAttachedToWindow();
    }

    public void addTab(@NonNull Tab tab, int position, boolean setSelected) {
        if (mViewPager != null && mViewPager.getAdapter() instanceof TabLayoutViewPagerAdapter) {
            Drawable icon = ((TabLayoutViewPagerAdapter) mViewPager.getAdapter()).getPageIcon(getContext(),position);
            tab.setIcon(icon);
        }
        super.addTab(tab,position,setSelected);

    }

    @Override
    public void setupWithViewPager(@Nullable ViewPager viewPager, boolean autoRefresh) {
        mViewPager = viewPager;
        super.setupWithViewPager(viewPager, autoRefresh);
    }
}

Поэтому все, что нужно сделать, это расширить TabLayoutViewPagerAdapter вместо PageAdapter и реализовать getPageIcon(Context,int) вместо или в дополнение к заголовку. Пропуск TabLayoutExt в вашем файле XML вместо обычного TabLayout. Это может быть расширено для дальнейшего изменения вкладки, либо с пользовательским представлением, либо с чем-то еще.

person JDL    schedule 19.01.2017

В TabLayout установить значок очень просто:

getPageTitle(position) должно возвращать null (если вы не хотите, чтобы заголовок отображался).

Следующий :

tabLayout.getTabAt(0).setIcon(resId);

tabLayout.getTabAt(1).setIcon(resId);

......
person Bhuwan    schedule 30.10.2015
comment
Я попробовал это, и значок находится над текстом. Как сделать значок слева от текста? - person HelloSilence; 30.10.2015
comment
в моем случае, если я оставлю getPageTitle() как есть, тогда... значок отображается рядом с заголовком... Может быть, текст заголовка слишком велик в вашем случае. - person Bhuwan; 30.10.2015

С предоставленным TabLayout с помощью библиотеки компонентов материалов вы можете использовать:

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

for (int i=0;i<tabLayout.getTabCount();i++){

   tabLayout.getTabAt(i).setIcon(iconResId);
   tabLayout.getTabAt(i).
        setTabLabelVisibility(TabLayout.TAB_LABEL_VISIBILITY_UNLABELED);
}

введите здесь описание изображения

person Gabriele Mariotti    schedule 23.09.2019

Попробуйте это, это определенно сработает.

private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
        R.drawable.single,
        R.drawable.multiple};

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

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    toolbar.setTitle("Choose contact");
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    tab();
}


public void tab(){
    viewPager = (ViewPager) findViewById(R.id.viewpager);
    setupViewPager(viewPager);
    tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);
    setupTabIcons();
}

private void setupTabIcons() {
    tabLayout.getTabAt(0).setIcon(tabIcons[0]);
    tabLayout.getTabAt(1).setIcon(tabIcons[1]);

}

private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new Login());
    adapter.addFragment(new Register());
    viewPager.setAdapter(adapter);
}

class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = 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();
    }

    public void addFragment(Fragment fragment) {
        mFragmentList.add(fragment);

    }


}
person Kunwar Shekhar Singh    schedule 30.11.2017

Как упоминалось в комментариях, определение значков в TabLayout не работает при использовании PagerAdapter. Для тех, кто использует Kotlin, одним из обходных путей является создание функции расширения, подобной этой:

fun TabLayout.setupWithViewPagerAndKeepIcons(viewPager : ViewPager?) {
    val icons =  mutableListOf<Drawable?>()
    repeat(tabCount) {
        icons.add(getTabAt(it)?.icon)
    }
    setupWithViewPager(viewPager)

    repeat(tabCount) {
        getTabAt(it)?.setIcon(icons.get(it))
    }
}

Затем в layout.xml добавьте свои значки в TabLayout:

    <com.google.android.material.tabs.TabLayout
            android:id="@+id/tab_layout">

        <com.google.android.material.tabs.TabItem
                android:icon="@drawable/your_icon"/>

    </com.google.android.material.tabs.TabLayout>

Наконец, используйте функцию расширения для настройки TabLayout с помощью ViewPager.

tab_layout.setupWithViewPagerAndKeepIcons(view_pager)
person kjellhaaland    schedule 13.08.2019

самый простой способ - создать новую таблицу, установив значок на вкладке. ниже код создаст две вкладки только со значком. используйте этот код в методе onCreate()

 tablayout = (TabLayout) findViewById(R.id.order_tablayout);
 tablayout.addTab( tablayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_shopping_cart_white_24dp)) );
 tablayout.addTab( tablayout.newTab().setIcon(getResources().getDrawable(R.mipmap.ic_like2_fille_white_24dp)) );
person Kamal Bunkar    schedule 29.11.2017

Это может быть не лучший ответ для всех случаев, но то, что я нашел, еще не решило мою проблему.

Посмотрев на реализацию tabLayout.setupWithViewPager(ViewPager pager) на Android, я нашел решение, использующее только слушателей.

Структура макета:

| LinearLayout (vertical)
|-- TabLayout (width: match_parent)
|---- TabItem (without text, just icons)
|---- TabItem
|---- ...
|-- ViewPager

Код для обоих слушателей:

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
    @Override
    public void onTabSelected(TabLayout.Tab tab) {
        pager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(TabLayout.Tab tab) {
    }

    @Override
    public void onTabReselected(TabLayout.Tab tab) {
    }
});
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        tabLayout.setScrollPosition(position, positionOffset, false);
    }

    @Override
    public void onPageSelected(int position) {
        TabLayout.Tab tab = tabLayout.getTabAt(position);
        if (tab != null) {
            tab.select();
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }
});

Посмотрите на вызов tabLayout.setScrollPosition внутри OnPageChangeListener.onPageScrolled на предмет более-менее хорошего перемещения индикатора при прокрутке.

Это может не работать, если для ширины TabLayout не установлено значение match_parent (или оно должно быть прокручиваемым).

person michiruf    schedule 03.03.2017