BadgeDrawable无法用于FrameLayout中的视图,例如按钮、图像、文本视图等吗?

4

我在我的主活动中有这个函数,它无法显示徽章:

private fun setFindShiftBadge(state: HomeState) {
        val findShiftsBadge = BadgeDrawable.create(this)
        home_framelayout.foreground = findShiftsBadge
        findShiftsBadge.badgeGravity = BadgeDrawable.TOP_END
        findShiftsBadge.backgroundColor = resources.getColor(R.color.colorWhite)
        findShiftsBadge.badgeTextColor = resources.getColor(R.color.colorPrimary)
        findShiftsBadge.number = state.availableShifts.size
 }

在同一个活动中,我有这个函数用于显示徽章:
private fun setMyPostedShiftBadge(state: HomeState) {
    val userShiftsBadge: BadgeDrawable =
        bottom_navigation_view.getOrCreateBadge(R.id.bottom_navigation_my_posted_shifts_text)
    userShiftsBadge.number = state.userShifts.size
    userShiftsBadge.backgroundColor = resources.getColor(R.color.colorPrimary)
} 

现在我明白第二个功能之所以有效是因为徽章设置在BottomNavigationView中。具有讽刺意味的是,BottomNavigationView扩展了FrameLayout。在Android文档中,他们建议使用以下代码:通过attachBadgeDrawable(BadgeDrawable,View,FrameLayout)将BadgeDrawable作为ViewOverlay添加到所需的锚定视图中,在基于其锚定视图的updateBadgeCoordinates(View,ViewGroup)中更新BadgeDrawable BadgeDrawable的坐标(中心和边界)。对于支持ViewOverlay的API 18+(API),可以使用此代码,而我在第一个无效的函数中使用它。
 BadgeDrawable badgeDrawable = BadgeDrawable.create(context);
 BadgeUtils.attachBadgeDrawable(badgeDrawable, anchor, null);

我也尝试过这个解决方案,但它也不起作用。 我知道有一些解决方法,例如:
  1. 创建一个可绘制对象,然后将其设置到您想要的视图之上
  2. 在该可绘制对象内放置一个TextView,然后使用您想要的数字进行更新
  3. 当有任何数字时,切换可绘制对象的可见性。
我使用的是 implementation 'com.google.android.material:material:1.2.0-alpha04' 版本。
这对我来说似乎很麻烦,因为我知道有更好的方法来做到这一点。 我只是似乎无法找出来。 我缺少什么? 这是否可能? 您如何能够在不编写解决方法的情况下完成此操作? 谢谢您的时间!期待从您的问题和答案中学习! 祝您拥有美好的一天!
3个回答

12

BottomNavigationView.getOrCreateBadge() 不仅将 BadgeDrawable 分配为前景 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
}

screenshot


13
我真的很惊讶安卓文档怎么这么没用。 - appoll

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>

0
根据Google(在这里)的说法,它需要知道视图的大小和位置来放置徽章,所以你需要将视图放在FrameLayout中,并检查布局的变化。
你可以使用这个函数来帮助你:
@androidx.annotation.OptIn(com.google.android.material.badge.ExperimentalBadgeUtils::class)
fun BadgeDrawable.attachToView(anchor: View, customBadgeParent: FrameLayout?) {
    BadgeUtils.attachBadgeDrawable(this, anchor, customBadgeParent)
    anchor.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
        updateBadgeCoordinates(anchor, customBadgeParent)
    }
}

使用方法:

badgeDrawable.attachToView(iconImageView, iconAndBadgeContainer)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接