【问题标题】:Android Tablayout tabs with notification badge like whatsApp带有通知徽章的 Android Tablayout 选项卡,例如 WhatsApp
【发布时间】:2015-11-05 05:40:34
【问题描述】:

我想用android.support.design.widget.TabLayout 实现通知徽章。我已尽最大努力实现它,但失败了。

任何帮助将不胜感激。

【问题讨论】:

  • 只需为选项卡创建一个相对布局并在其中添加文本视图。然后在运行时更改其文本。
  • 你能给我提供一个应用程序的演示吗?因为我已经尝试了所有可能的方法来做到这一点。
  • 发布您的标签代码。主标签活动。
  • github.com/natuan241/Android-Design-Support-Library-Sample,我正在使用以下代码进行导航
  • 将自定义视图添加到您的选项卡布局选项卡中,您可以轻松地附加来自github.com/jgilfelt/android-viewbadger 的徽章

标签: android badge android-tablayout


【解决方案1】:

在 kotlin 中,工作:

if(list.isNotEmpty()) {
    mTlSaved.getTabAt(0)?.orCreateBadge?.number = list.size
}

【讨论】:

    【解决方案2】:

    我会用这个:

      tabLayout.getTabAt(0).getOrCreateBadge().setNumber(10);
    

    【讨论】:

    • 已折旧。在 androidx 中不再可用。
    • @SatyajitDas TabLayout 是 Android 的 Material Components 的一部分,而不是现在的 AndroidX。你应该改用前者。
    【解决方案3】:

    这是一个古老的提示,但现在它变得更加简单。 我使用 Kotlin,AndroidX,使用下一个小部件作为 TabLayout:

    com.google.android.material.tabs.TabLayout
    

    在我的 Gradel 应用文件中:

    implementation 'com.google.android.material:material:1.1.0-alpha09'
    

    设置一个简单的徽章,只需写..

    yourTabLayout?.getTabAt(currentTabPosition)?.apply{
                            orCreateBadge
                            badge?.isVisible = true
                        }
    

    然后只需设置 isVisible = false 即可隐藏,如下所示:

    private fun changeYourTabMethod(newTabPosition : Int) {
        // do some stuff and then hide the badge...
        yourTabLayout?.getTabAt(newTabPosition)?.apply{
            badge?.isVisible = false
        }
    }
    

    【讨论】:

    • 对我有用,谢谢!
    【解决方案4】:

    编辑:更新

    随着Material Components 的最新版本,Android 团队现在提供官方BadgeDrawable 用于TabLayout 以达到要求的结果。它是 v1.1.0-alpha07 更新的一部分。 https://github.com/material-components/material-components-android/releases/tag/1.1.0-alpha07

    用法很简单,可以做如下:

    tabLayout.getTabAt(0).showBadge().setNumber(1);
    

    查看材质组件演示应用中的集成: https://github.com/material-components/material-components-android/commit/111cd001f5302bd6899f181ab7ccea2fd4002f63#diff-bf3e9a8a208f0ecab05088823fba99c4R239


    老答案

    我尝试了上面提到的一些解决方案,但它们没有提供正确的结果。如果您仔细查看TabLayout 实现,您会发现TabView 将尝试从CustomView 获取textView 和iconView(如果已应用)。

    因此,我没有做一些 hacky 的实现,而是想出了一个与原始 TabView 相同的布局,而是一个可以有徽章的附加视图。

    所以你需要 badged_tab.xml 布局

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="4dp"
            android:layout_marginTop="4dp">
    
            <ImageView
                android:id="@android:id/icon"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:scaleType="centerInside" />
    
            <TextView
                android:id="@android:id/text1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:gravity="center"
                android:maxLines="2" />
        </LinearLayout>
    
        <LinearLayout
            android:id="@+id/badgeCotainer"
            android:layout_width="wrap_content"
            android:layout_height="16dp"
            android:layout_marginStart="12dp"
            android:background="@drawable/notifications_background"
            android:gravity="center"
            android:minWidth="16dp"
            android:visibility="gone">
    
            <TextView
                android:id="@+id/badge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAlignment="center"
                android:textColor="#fff"
                android:textSize="10sp" />
        </LinearLayout>
    </RelativeLayout>
    

    还有某种通知背景:

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="oval">
        <solid android:color="@color/red" />
    </shape>
    

    以编程方式添加标签时,只需调用

    tab.setCustomView(R.layout.badged_tab);
    

    然后您可以随时通过以下方式显示/隐藏/设置徽章数量:

    if(tab != null && tab.getCustomView() != null) {
        TextView b = (TextView) tab.getCustomView().findViewById(R.id.badge);
        if(b != null) {
            b.setText(notifications + "");
        }
        View v = tab.getCustomView().findViewById(R.id.badgeCotainer);
        if(v != null) {
            v.setVisibility(View.VISIBLE);
        }
    }
    

    【讨论】:

    • 我使用了这种方法,它对我有用。我调整了这个解决方案来添加一个包含徽章的自定义视图,然后只需 setCustomView(null) 在 UI 中不需要它时将其删除。创建具有相同间距和边距的自定义视图很重要,这样您就可以无缝过渡到相应选项卡的默认视图。我成功地将它与 TabLayouts 一起使用。或者,您可以在所有选项卡上使用自定义视图,并根据需要在徽章和非徽章布局之间切换,如果您在它们之间的 UI 一致性方面遇到问题。
    • 迄今为止问题的最佳解决方案。
    • 这对我有用,但对于其他找到这篇文章的人来说,你可以将 android:orientation="vertical" 添加到 badged_tab.xml 中的第一个线性布局吗?我相信这是想要的结果。
    • 请注意,通过最新的材料组件更新,现在有更好的方法
    • 但是这个材料设计在我的 TabTitle 上显示了徽章计数器,它看起来很诡异...有什么办法可以给徽章计数器提供方向或重力吗?
    【解决方案5】:

    我建议对标签使用 CustomView。 您可以创建一个带有徽章的新视图并将其设置为您的标签。

    tab.setCustomView(R.layout.badged_tab);
    

    【讨论】:

      【解决方案6】:

      我不知道为什么,但以上答案都不适合我:(

      我有自己的解决方案,它会制作与带有该徽章的 whatsapp 相同的 tablayout :)

      首先制作一个自定义标签布局为custom_tab

      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="48dp"
      android:padding="12dp">
      
      <LinearLayout
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerInParent="true"
          android:orientation="horizontal">
      
          <TextView
              android:id="@+id/tv_title"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Calls"
              android:textColor="@drawable/tab_text_color_selector"
              android:textSize="@dimen/large_text" />
      
          <TextView
              android:id="@+id/tv_count"
              android:layout_width="20dp"
              android:layout_height="20dp"
              android:layout_marginLeft="6dp"
              android:background="@drawable/badge_background"
              android:gravity="center"
              android:text="99"
              android:textColor="@color/colorPrimary"
              android:textSize="@dimen/medium_text" />
      
      </LinearLayout>
      
      </RelativeLayout>
      

      第二个badge_background

      <?xml version="1.0" encoding="utf-8"?>
      <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
      <item xmlns:android="http://schemas.android.com/apk/res/android">
          <shape android:shape="oval">
              <solid android:color="@drawable/tab_text_color_selector" />
          </shape>
      </item>
      </layer-list>
      

      第三个 tab_color_selector

      <?xml version="1.0" encoding="utf-8"?>
      <selector xmlns:android="http://schemas.android.com/apk/res/android">
           <item android:color="@color/colorTextPrimary"android:state_selected="true" />
      <item android:color="@color/colorAccent"/>
       </selector>
      

      在你的活动中排名第四

          viewPager = (ViewPager) findViewById(R.id.viewpager);
          viewPager.setOffscreenPageLimit(3);
          setupViewPager(viewPager);
      
          //Initializing the tablayout
          tabLayout = (TabLayout) findViewById(R.id.tablayout);
          tabLayout.setupWithViewPager(viewPager);
      
          try
          {
              setupTabIcons();
          }
          catch (Exception e)
          {
              e.printStackTrace();
          }
      

      第五个定义 setupTabIcons 和 prepareTabView 方法

        private void setupTabIcons()
      {
      
          for(int i=0;i<tabTitle.length;i++)
          {
              /*TabLayout.Tab tabitem = tabLayout.newTab();
              tabitem.setCustomView(prepareTabView(i));
              tabLayout.addTab(tabitem);*/
      
              tabLayout.getTabAt(i).setCustomView(prepareTabView(i));
          }
          }
      
       String[] tabTitle={"LOL!","LOL@","LOL#"};
      int[] unreadCount={1,3,3};
      
      private View prepareTabView(int pos) {
          View view = getLayoutInflater().inflate(R.layout.custom_tab,null);
          TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
          TextView tv_count = (TextView) view.findViewById(R.id.tv_count);
          tv_title.setText(tabTitle[pos]);
          if(unreadCount[pos]>0)
          {
              tv_count.setVisibility(View.VISIBLE);
              tv_count.setText(""+unreadCount[pos]);
          }
          else
              tv_count.setVisibility(View.GONE);
      
      
          return view;
          }
      

      我可能在回答这个问题时留下了一些东西,请联系我,我很乐意提供帮助 :D

      【讨论】:

      • 谢谢,就您而言,上述解决方案均不适合我,但您的解决方案效果很好。
      【解决方案7】:

      我建议你看看这个网站:

      https://guides.codepath.com/android/Google-Play-Style-Tabs-using-TabLayout#design-support-library

      您可以使用此方法遍历不同的选项卡并将自定义视图设置为您想要的任何内容:

        // Iterate over all tabs and set the custom view
          for (int i = 0; i < tabLayout.getTabCount(); i++) {
              TabLayout.Tab tab = tabLayout.getTabAt(i);
              tab.setCustomView(pagerAdapter.getTabView(i));
          }
      
      public View getTabView(int position) {
          // Given you have a custom layout in `res/layout/custom_tab.xml` with a TextView and ImageView
          View v = LayoutInflater.from(context).inflate(R.layout.custom_tab, null);
          TextView tv = (TextView) v.findViewById(R.id.textView);
          tv.setText(tabTitles[position]);
          ImageView img = (ImageView) v.findViewById(R.id.imgView);
          img.setImageResource(imageResId[position]);
          return v;
      }
      
      }
      

      【讨论】:

      • 我试过这个和它的工作原理,但是如果我选择了自定义选项卡并希望该选项卡在此之后像其他选项卡一样返回到其默认视图(具有正常和选定的颜色),怎么能我这样做
      • 这应该是公认的答案。工作得很好,链接中有很好的解释。
      • 它正在工作,但是如何像其他标签一样设置默认宽度和高度?
      【解决方案8】:

      只要使用这个技巧:

      BadgeView bv1 = new BadgeView(this, ((ViewGroup) tabLayout.getChildAt(0)).getChildAt(0));
      

      【讨论】:

      • 什么是 BadgeView?
      • 他指的是 ViewBadger 库,为视图添加徽章。请记住,此库现已弃用。
      【解决方案9】:

      也有简单的方法。只需在后面附加一个特殊字符。它看起来就像whatsapp一样。

      ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓

      tabLayout.addTab(tabLayout.newTab().setText("News " + ➊));
      

      【讨论】:

      • 如何用特殊字符写自己的号码?
      • @Jason,那么如何动态更改该值?
      • 这似乎仅在徽章编号低于 11 或您使用更多编号创建自定义字体时才有效
      • 这似乎不是一个全面的解决方案。
      • 连web环境都不用这种方式。
      【解决方案10】:

      我对此的解决方案是使用 https://github.com/jgilfelt/android-viewbadger 并为每个选项卡设置自定义视图:

      我的标签只有图标,所以我使用了 ImageView,但我相信您可以使用任何其他视图,请查看https://github.com/jgilfelt/android-viewbadger/blob/master/README.markdown

      private BadgeView badge;
      

      Tab tab = tabLayout.getTabAt(position);
      ImageView imageView = new ImageView(context);
      tab.setCustomView(imageView);
      badge = new BadgeView(context, imageView);
      

      【讨论】:

      • 此库现已弃用
      • 它对我有用,谢谢!
      猜你喜欢
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多