美文网首页
BadgeDrawable未读消息数

BadgeDrawable未读消息数

作者: 有点健忘 | 来源:发表于2021-02-24 16:25 被阅读0次

    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)
    

    相关文章

      网友评论

          本文标题:BadgeDrawable未读消息数

          本文链接:https://www.haomeiwen.com/subject/alkztltx.html