【问题标题】:Tablayout with icons only仅包含图标的表格布局
【发布时间】:2015-09-02 17:53:07
【问题描述】:

我正在使用设计支持来创建选项卡。我也使用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);
}

【问题讨论】:

  • 尝试可跨文本。试试我的回答Here。如果有帮助,请投票。

标签: android android-tabs android-tablayout


【解决方案1】:

一种方法是在TabLayout.setupWithViewPager() 方法之后设置图标。

mTabLayout.setupWithViewPager(mViewPager);
for (int i = 0; i < mTabLayout.getTabCount(); i++) {
  mTabLayout.getTabAt(i).setIcon(R.drawable.your_icon);
}

【讨论】:

  • 谢谢 - 太棒了。
  • 就我而言,此解决方案同时显示图标和文本,这实际上是我所需要的 :-)
  • 如果您在寻呼机适配器中覆盖getPageTitle,这将显示文本,否则只会显示图标
  • 此解决方案在 27.1.0 中不起作用,但如果我覆盖 getPageTitle 则只显示标题
  • 如果你之前做了一个adapter.notifyDataSetChanged()它会这样做
【解决方案2】:

以下链接中显示的教程应涵盖您想要的内容。 https://github.com/codepath/android_guides/wiki/Google-Play-Style-Tabs-using-TabLayout#add-icons-to-tablayout

我复制了下面的相关部分。

将图标添加到 TabLayout

目前,TabLayout 类不提供一个干净的抽象模型,允许标签中的图标。有许多已发布的解决方法,其中之一是从 PagerAdapter 的 getPageTitle(position) 方法返回 SpannableString,其中包含 ImageSpan 中的图标,如下面的代码 sn-p 所示:

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>

【讨论】:

  • 选项卡不会显示任何图标,即使设置textAllCaps = false 也无济于事
  • 当我尝试构建我的代码时,我得到这个错误:在包'android'中找不到属性'tabTextAppearance'的资源标识符
  • 我注意到使用这种技术的一件事是,当图标可见时,文本大小会发生变化。
  • 谢谢你,属性“textAllCaps”解决了我的图标问题。
【解决方案3】:

TabLayout的新版本中,google添加了TabItem,它可以很容易地通过你的XML添加Icon,代码如下:

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

查看更多here

【讨论】:

  • 这是添加图标的实际方法:)
  • 如果与视图分页器一起使用,视图分页器调用 removeAllTabs() 删除通过布局文件添加的所有选项卡元素。
  • 不起作用,一旦使用 PagerAdapter,选项卡就会被重置,并且只显示标题,取自适配器。
【解决方案4】:

试试这个

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

【讨论】:

    【解决方案5】:

    我发现使用图标的最简单方法是使用 Tablayout.Tab.setIcon(drawable)。这也使得突出显示所选图标变得容易。如果您想这样做,请按照以下步骤操作。

    第 1 步。 将图像添加到 res.mipmap 文件夹。 (mipmap-mdpi、hdpi 等)从此处的其他答案来看,将 then 放入 res.drawable 文件夹中也可以。

    第 2 步。 设置 TabLayout 和 ViewPager 后,在所有选项卡上调用 setIcon。我在我的 AdapterTabs 中这样做以保持 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 的 AdapterTabs 中放置您的 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_3_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));
            }
        }
    }
    

    确保存储对两个列表“icons”和“iconsHilighted”的引用。稍后您将需要它们。还要存储对从 Activity 传入的 TabLayout 和 ViewPager 的引用。

    第 3 步。 确保 AdapterTabs.getPageTitle() 返回 null。 此时,如果您运行它,您应该会看到第一个图标被突出显示。

    第 4 步。 在 AdapterTabs 中实现 ViewPager.OnPageChangeListener 并将该侦听器添加到您的 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 步。 在 AdapterTabs 的 onPageSelected 回调中更新选项卡中的图标。

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

    现在,当您更改标签时,您应该会看到突出显示的图标正在更新。

    【讨论】:

    • 您有专门的可绘制对象,称为选择器,您可以在其中配置不同的状态。
    • 是的,这是正确的,但是为什么一旦您选择了一个不在缓存中的新选项卡,图标就会被删除?它们不会留下来,因此必须将它们重新插入到 .onPageSelected 中。真是愚蠢的解决方案。一个错误?
    • 我认为你需要提高你的软技能@carl。因此,我没有进一步的 cmets。
    【解决方案6】:

    TabLayout,设置图标很简单:

    getPageTitle(position) 应该返回 null(如果您不想显示标题)。

    下一步:

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

    【讨论】:

    • 我试过了,图标在文字上方。如何在文字左侧制作图标?
    • 在我的情况下,如果我保持 getPageTitle() 不变,那么...图标显示在标题旁边...在您的情况下可能是标题文本太大。
    【解决方案7】:

    当使用 TabLayout 作为 ViewPager“装饰”场景时,这些方法都不是优雅的。 TabLayout Documentation 这是 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) 而不是标题或除了标题之外。在 XML 文件中添加 TabLayoutExt,而不是普通的 TabLayout。这可以扩展为进一步修改选项卡,或者使用自定义视图或其他方式。

    【讨论】:

      【解决方案8】:

      通过Material Components Library 提供的TabLayout,您可以使用:

      类似:

      for (int i=0;i<tabLayout.getTabCount();i++){
      
         tabLayout.getTabAt(i).setIcon(iconResId);
         tabLayout.getTabAt(i).
              setTabLabelVisibility(TabLayout.TAB_LABEL_VISIBILITY_UNLABELED);
      }
      

      【讨论】:

        【解决方案9】:

        试试这个肯定会奏效。

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

        【讨论】:

          【解决方案10】:

          如 cmets 中所述,在使用 PagerAdapter 时,在 TabLayout 中定义图标不起作用。对于那些使用 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>
          

          最后,使用扩展函数来设置带有 ViewPager 的 TabLayout。

          tab_layout.setupWithViewPagerAndKeepIcons(view_pager)
          

          【讨论】:

            【解决方案11】:

            最简单的方法是通过在 tablayout 上设置 Icon 来创建新表。下面的代码将创建两个仅带有图标的选项卡。在 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)) );
            

            【讨论】:

              【解决方案12】:

              使用 ViewPager。这就是我有一个只有图标而没有文本的选项卡的方式。

              TabLayout tabs...
              
              TabLayout.Tab tab = tabs.getTabAt(0);
              tab.setText("");
              tab.setIcon(R.drawable.yourIcon);
              

              【讨论】:

                【解决方案13】:

                这可能不是所有情况的最佳答案,但我发现的内容还没有解决我的问题。

                在查看了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) {
                    }
                });
                

                查看OnPageChangeListener.onPageScrolled 中的tabLayout.setScrollPosition 调用,了解滚动时指示器的移动效果是否良好。

                如果 TabLayout 的宽度未设置为 match_parent(或必须是可滚动的),这可能不起作用。

                【讨论】:

                  猜你喜欢
                  • 2014-02-07
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-04-02
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多