BadgeDrawable未读消息数

BadgeDrawable

image.png

测试代码

        TabLayoutMediator(tabBottom,vp2,object:TabLayoutMediator.TabConfigurationStrategy{
            override fun onConfigureTab(tab: TabLayout.Tab, position: Int) {
                tab.setText(tabTitles[position])
                tab.orCreateBadge.apply {
                    maxCharacterCount=3
                    number=if(position==0) 5 else 199
                    this.badgeGravity=BadgeDrawable.TOP_END
                }
            }
        }).attach()

系统代码里是和TabLayout关联的

tab.badge//返回badegDrawable或空
tab.orCreateBadge//没有的话new一个新的,有的话更新下状态

常用属性

  1. setBadgeGravity
    上下左右4个方向
 public void setBadgeGravity(@BadgeGravity int gravity)

  @IntDef({
    TOP_END,
    TOP_START,
    BOTTOM_END,
    BOTTOM_START,
  })
  1. setNumber
    最小是0,比0小的也当0处理
  public void setNumber(int number) {
    number = Math.max(0, number);
  1. setMaxCharacterCount
    最大支持的字符数,算上加号的
    比如上边我们比99大的一般都写成99+这样的。这里的count就是3
public void setMaxCharacterCount(int maxCharacterCount)

4.其他看名字就知道啥了

public void setBackgroundColor(@ColorInt int backgroundColor) 

 public void setBadgeTextColor(@ColorInt int badgeTextColor)

  /**
   * Sets how much (in pixels) to horizontally move this badge towards the center of its anchor.
   *
   * @param px badge's horizontal offset
   */
  public void setHorizontalOffset(int px)

  /**
   * Sets how much (in pixels) to vertically move this badge towards the center of its anchor.
   *
   * @param px badge's vertical offset
   */
  public void setVerticalOffset(int px)


  /** Resets any badge number so that a numberless badge will be displayed. */
  public void clearNumber()

public void setVisible(boolean visible)

BadgeDrawable是可以给任意控件用的,最简单的就是调用系统BadgeUtils的方法,可是这个类是private的了
修改:BadgeUtils在api31是可用的,api29是有一个@RestrictTo(Scope.LIBRARY)的注解的,外部无法使用
所以看下自己的api版本这个到底能用不

 BadgeUtils.attachBadgeDrawable(dra,anchor,null)

我们可以把这个工具类copy出来用,也可以把这个方法里的实现代码copy出来用
这些方法都必须在anchor创建以后才能用,也就是不能在oncreate里调用这些方法,或者你要view.post调用,保证anchor已经绘制好了

如下

        val badgeDrawable=BadgeDrawable.create(requireContext()).apply {
            number=99
//            horizontalOffset=50
//            verticalOffset=50
            badgeGravity=BadgeDrawable.BOTTOM_END
        }

            val anchor=textview
            val badgeBounds = Rect()
            anchor.getDrawingRect(badgeBounds)
            badgeDrawable.setBounds(badgeBounds)
            badgeDrawable.updateBadgeCoordinates(anchor, null)
            anchor.getOverlay().add(badgeDrawable);

badge默认是在anchor的4个顶点位置,所以你就只能看到一个红点,也就是badge很小的一般分角
要解决这个有两种办法
①badgeDrawable 设置offset,正直就会往anchor中心偏移,这样就看到了
②父容器或者加上父容器的父容器,设置如下属性,保证父容器不要裁剪这些超出anchor范围的内容

 android:clipChildren="false"
        android:clipToPadding="false"

6.实例化方法

public static BadgeDrawable create(@NonNull Context context)

public static BadgeDrawable createFromResource(@NonNull Context context, @XmlRes int id)

demo

如下


image.png
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:clipToPadding="false"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/btn_test"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#33000000"
        android:gravity="center"
        android:text="hello"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

look

        val badgeDrawable=BadgeDrawable.create(requireContext()).apply {
            number=99
//            horizontalOffset=50
//            verticalOffset=50
            badgeGravity=BadgeDrawable.BOTTOM_END
        }
        btn_test.post {
            val anchor=btn_test
            val badgeBounds = Rect()
            anchor.getDrawingRect(badgeBounds)
            badgeDrawable.setBounds(badgeBounds)
            badgeDrawable.updateBadgeCoordinates(anchor, null)
            anchor.getOverlay().add(badgeDrawable);

        }

后记

这个drawable的大小以及文字的大小我们是无法直接修改的,看源码就能发现,它在构造方法里赋值的,所以我们真要修改只能反射了
如下构造方法源码,私有的

  private BadgeDrawable(@NonNull Context context) {
    this.contextRef = new WeakReference<>(context);
    ThemeEnforcement.checkMaterialTheme(context);
    Resources res = context.getResources();
    badgeBounds = new Rect();
    shapeDrawable = new MaterialShapeDrawable();

    badgeRadius = res.getDimensionPixelSize(R.dimen.mtrl_badge_radius);
    badgeWidePadding = res.getDimensionPixelSize(R.dimen.mtrl_badge_long_text_horizontal_padding);
    badgeWithTextRadius = res.getDimensionPixelSize(R.dimen.mtrl_badge_with_text_radius);

    textDrawableHelper = new TextDrawableHelper(/* delegate= */ this);
    textDrawableHelper.getTextPaint().setTextAlign(Paint.Align.CENTER);
    this.savedState = new SavedState(context);
    setTextAppearanceResource(R.style.TextAppearance_MaterialComponents_Badge);
  }

说明:
private final float badgeRadius;//这个是没有设置数字的时候,圆点的半径
private final float badgeWithTextRadius;//这个是有数字,圆点的半径
private final float badgeWidePadding;//这个是有数字,数字超过9了,文字左右两边的间距
setTextAppearanceResource:这个是设置画笔的,也就是文字大小样式啥的
相关的就上边4个,要改啥反射即可
前三个变量没啥说的,后边需要一个style,我们在theme下添加一个style,继承那个默认的style,然后修改下自己要改的就行了,如下

   <style name="BadgeCustom30" parent="TextAppearance.MaterialComponents.Badge">
       <item name="android:textStyle">bold</item>
       <item name="android:textSize">50sp</item>
       <item name="android:textColor">@color/purple_700</item>
   </style>

完整的修改上边4个的代码如下,看需要哪个改哪个

            val drawable=BadgeDrawable.create(this).apply {
                maxCharacterCount=3
                number=9
            }
            val reflect=BadgeDrawable::class.java.getDeclaredMethod("setTextAppearanceResource",Int::class.java)
            reflect.isAccessible=true
            reflect.invoke(drawable,R.style.BadgeCustom30)

            val x1=BadgeDrawable::class.java.getDeclaredField("badgeRadius")
            x1.isAccessible=true
            x1.set(drawable,30f)

            val x2=BadgeDrawable::class.java.getDeclaredField("badgeWithTextRadius")
            x2.isAccessible=true
            x2.set(drawable,30f)

            val x3=BadgeDrawable::class.java.getDeclaredField("badgeWidePadding")
            x3.isAccessible=true
            x3.set(drawable,30f)


            BadgeUtils.attachBadgeDrawable(drawable,binding.tvTemp2,null)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容