【问题标题】:Badge Drawable not showing徽章绘图未显示
【发布时间】:2019-10-15 20:13:49
【问题描述】:

为什么BadgeDrawable 没有显示在任何地方?我正在尝试添加MaterialCardViewMaterialButton 等。它没有显示。任何人都知道如何解决这个问题?或者有相同的库来替换它?

代码如下:

val badgeDrawable = BadgeDrawable.create(holder.itemView.context)
badgeDrawable.number = 10
badgeDrawable.badgeGravity = BadgeDrawable.TOP_END
badgeDrawable.backgroundColor = holder.itemView.context.getColor(R.color.colorAccent)
holder.itemView.home_cardview.overlay.add(badgeDrawable)
badgeDrawable.updateBadgeCoordinates(holder.itemView.home_cardview, null)

这个方法也不行:

BadgeUtils.attachBadgeDrawable(badgeDrawable, anchor, null);

顺便说一下,在新版本中 compatBadgeParent 是必填字段

【问题讨论】:

    标签: android kotlin android-button


    【解决方案1】:

    您可以使用以下布局将BadgeDrawable 应用于MaterialCardViewMaterialButton

    <FrameLayout
        android:id="@+id/layout"
        android:clipChildren="false"
        android:clipToPadding="false"
        ..>
    
            <com.google.android.material.card.MaterialCardView
                android:id="@+id/card"
                .../>
    
    </FrameLayout>
    

    那就用BadgeUtils.attachBadgeDrawable的方法吧。

    例如 CardView

        MaterialCardView cardview = findViewById(R.id.card);
        cardview.setClipToOutline(false);  //Important with a CardView
    
        cardview.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                BadgeDrawable badgeDrawable = BadgeDrawable.create(MainActivity.this);
                badgeDrawable.setNumber(15);
                BadgeUtils.attachBadgeDrawable(badgeDrawable, cardview, findViewById(R.id.layout));
    
                cardview.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });
    

    对于Button

    <FrameLayout
        android:id="@+id/layout"
        android:clipChildren="false"
        android:clipToPadding="false">
    
      <com.google.android.material.button.MaterialButton
          android:id="@+id/button"
          ../>
    
    </FrameLayout>
    

    然后是类似的代码:

        button.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                BadgeDrawable badgeDrawable = BadgeDrawable.create(MainActivity.this);
                badgeDrawable.setNumber(7);
                badgeDrawable.setBackgroundColor(......);
                badgeDrawable.setVerticalOffset(20);
                badgeDrawable.setHorizontalOffset(15);
    
                BadgeUtils.attachBadgeDrawable(badgeDrawable, button, findViewById(R.id.layout));
    
                button.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
        });
    

    【讨论】:

      【解决方案2】:

      这是@0X0nosugar 在我的question 上发布的solution,所以请去看看他的答案并给他一个大拇指。上面有链接,谢谢!

      BottomNavigationView.getOrCreateBadge() 不仅将BadgeDrawable 指定为前景Drawable,而且还设置了drawable 边界。如果没有这一步,它们将停留在 (0,0,0,0),因此没有可绘制的内容。

      为了设置边界,让我们为BadgeDrawable引入一个扩展函数

      /**
       * Inspired by BadgeUtils in com.google.android.material library
       *
       * Sets the bounds of a BadgeDrawable 
       */
      private fun BadgeDrawable.setBoundsFor(@NonNull anchor: View, @NonNull parent: FrameLayout){
          val rect = Rect()
          parent.getDrawingRect(rect)
          this.setBounds(rect)
          this.updateBadgeCoordinates(anchor, parent)
      }
      

      将此函数与您的 BadgeDrawable 一起用于 FrameLayout:

      private fun setFindShiftBadge(state: HomeState) {
          val findShiftsBadge = BadgeDrawable.create(this)
          // configure the badge drawable
          findShiftsBadge.badgeGravity = BadgeDrawable.TOP_END
          findShiftsBadge.backgroundColor = resources.getColor(R.color.colorWhite)
          findShiftsBadge.badgeTextColor = resources.getColor(R.color.colorPrimary)
          findShiftsBadge.number = state.availableShifts.size
          // set bounds inside which it will be drawn
          findShiftsBadge.setBoundsFor(btn_badge, home_framelayout)
          // assign as foreground drawable
          home_framelayout.foreground = findShiftsBadge
      }
      

      【讨论】:

        【解决方案3】:

        您可以在 Kotlin 方式中使用以下不带 FrameLayout 的函数:

        view 是您要放置通知徽章的组件!

        @SuppressLint("UnsafeExperimentalUsageError")
            private fun initBadge(view : View, nbrNotification : Int) {
        
                if(nbrNotification == 0) return // Don't show the badge
        
                view.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        
                    override fun onGlobalLayout() {
        
                        BadgeDrawable.create(requireContext()).apply {
                            number = nbrNotification
                            verticalOffset = 70
                            horizontalOffset = 70
                            //badgeDrawable.setBackgroundColor() #to change the background color
                            BadgeUtils.attachBadgeDrawable(this, view)
                        }
        
                        view.viewTreeObserver.removeOnGlobalLayoutListener(this)
                    }
                })
            }
        

        【讨论】:

          【解决方案4】:

          验证您正在使用的版本,我正在使用:

          com.google.android.material:material: 1.1.0-beta01

          试试这个:

          bottomNavigationView.getOrCreateBadge(R.id.menu_item_notifications).apply {
                      backgroundColor = resources.getColor(R.color.red)
                      badgeTextColor = resources.getColor(R.color.white)
                      maxCharacterCount = 3
                      number = 10 //should be change
                      isVisible = true
                  }
          

          【讨论】:

          • 我不想在底部导航中添加徽章,我想在按钮或卡片视图中添加徽章
          【解决方案5】:

          我遇到了同样的问题。 这可能是徽章库中的错误。 这是工作:

                  badgeDrawable = BadgeDrawable.create(frameLayoutContainer.getContext());
                  frameLayoutContainer.setForeground(badgeDrawable);
                  frameLayoutContainer.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
                      //
                      badgeDrawable.updateBadgeCoordinates(frameLayoutContainer, frameLayoutContainer);
                  });
          

          frameLayoutContainer 是一个将 BadgeDrawable 设置为其前景的 FrameLayout。

          【讨论】:

          • iconParenticonContainer 是什么?
          • 抱歉错字。 iconParent 是一个 FrameLayout,它将 BadgeDrawable 设置为其前景。
          • @Mindgamer 这些解决方案是否对您有用?
          • @PrincepsPolycap 不,没有任何帮助
          • 这是某人为我发布的解决方案的链接,该解决方案最终工作stackoverflow.com/questions/60009600/…
          【解决方案6】:
              BadgeDrawable badgeDrawable = BadgeDrawable.create(this);
              badgeDrawable.setNumber(15);
          
              FrameLayout frameLayout = findViewById(R.id.framelayout);
          
              ImageView imageView = findViewById(R.id.iv_center);
          
              //core code
              frameLayout.setForeground(badgeDrawable);
              frameLayout.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
          
          
                  //either of the following two lines of code  work
                  //badgeDrawable.updateBadgeCoordinates(imageView, frameLayout);
                  BadgeUtils.attachBadgeDrawable(badgeDrawable, imageView, frameLayout);
              });
          
          
          
          
          
              <FrameLayout
                  android:id="@+id/framelayout"
                  android:layout_width="150dp"
                  android:layout_height="150dp">
          
                  <ImageView
                      android:layout_gravity="center"
                      android:id="@+id/iv_center"
                      android:layout_width="50dp"
                      android:layout_height="50dp"
                      android:scaleType="fitXY"
                      android:src="@drawable/ic_beard" />
              </FrameLayout>
          

          【讨论】:

            【解决方案7】:

            这里我已经实现了BadgeDrawable 使用带有xml 样式的BadgeUtils 在Button 上添加徽章。

            private fun setBadgeCount(count: Int) {
                    BadgeDrawable.createFromResource(this, R.xml.badge_style).apply {
                        number = count
                        BadgeUtils.attachBadgeDrawable(this, binding.buttonContact)
                    }
                }
            

            badge_style.xml:

            <badge xmlns:app="http://schemas.android.com/apk/res-auto"
                style="@style/Widget.MaterialComponents.Badge"
                app:backgroundColor="#FF0000"
                app:badgeTextColor="#FFFFFF"
                app:horizontalOffset="6dp"
                app:maxCharacterCount="2"
                app:verticalOffset="8dp" />
            

            输出:

            参考:

            1. https://material.io/develop/android/supporting/badge
            2. https://developer.android.com/reference/com/google/android/material/badge/package-summary

            【讨论】:

              猜你喜欢
              • 2014-07-29
              • 1970-01-01
              • 1970-01-01
              • 2022-11-03
              • 2020-08-05
              • 1970-01-01
              • 2017-11-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多