You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在RecyclerView列表项末尾添加带计数的通知徽章?

针对RecyclerView列表项末尾通知徽章的实现思路

方案一:自定义自适应尺寸的徽章View

直接写个继承TextView的自定义View,自动根据计数文本调整形状和大小:

  • 重写onMeasure方法,测量文本宽度后动态设置View宽高:
    • 计数≤9时,强制宽高相等(圆形),取文本宽高中的较大值加内边距;
    • 计数≥10时,用圆角矩形,宽度取文本宽度加左右内边距,高度取文本高度加上下内边距。
  • 用ShapeDrawable或XML Drawable作为背景,动态切换圆形/圆角矩形样式。
  • 在RecyclerView的item布局里把这个自定义View放在末尾,绑定数据时直接设置计数文本即可。

核心代码示例:

public class BadgeTextView extends AppCompatTextView {
    private static final int CORNER_RADIUS = 12;
    private static final int PADDING = 8;

    public BadgeTextView(Context context) {
        super(context);
        init();
    }

    private void init() {
        setTextColor(Color.WHITE);
        setGravity(Gravity.CENTER);
        setPadding(PADDING, PADDING, PADDING, PADDING);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int contentWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
        int contentHeight = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();
        
        if (getText().length() <= 1) {
            int size = Math.max(contentWidth, contentHeight) + PADDING * 2;
            setMeasuredDimension(size, size);
            GradientDrawable drawable = new GradientDrawable();
            drawable.setColor(Color.RED);
            drawable.setCornerRadius(size / 2f);
            setBackground(drawable);
        } else {
            int height = Math.max(contentWidth, contentHeight) + PADDING * 2;
            setMeasuredDimension(getMeasuredWidth(), height);
            GradientDrawable drawable = new GradientDrawable();
            drawable.setColor(Color.RED);
            drawable.setCornerRadius(height / 2f);
            setBackground(drawable);
        }
    }
}

方案二:用ConstraintLayout+BadgeDrawable实现居中徽章

解决之前用不可见按钮无法居中的问题:

  • 在RecyclerView的item布局中添加一个透明辅助View(宽高设为徽章最小圆形尺寸,比如24dp);
  • 用ConstraintLayout将辅助View定位到列表项末尾(比如和右侧元素对齐、设置margin);
  • 创建BadgeDrawable并设置setGravity(Gravity.CENTER),绑定到辅助View上;
  • 更新计数时直接调用badgeDrawable.setNumber(count)即可。

布局片段示例:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <!-- 列表项主体内容 -->
    <TextView
        android:id="@+id/tv_item_content"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/helper_view"/>

    <!-- 透明辅助View -->
    <View
        android:id="@+id/helper_view"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:background="@android:color/transparent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/tv_item_content"
        app:layout_constraintBottom_toBottomOf="@id/tv_item_content"/>

</androidx.constraintlayout.widget.ConstraintLayout>

代码绑定徽章:

View helperView = itemView.findViewById(R.id.helper_view);
BadgeDrawable badge = BadgeDrawable.create(context);
badge.setGravity(Gravity.CENTER);
badge.setNumber(5);
BadgeUtils.attachBadgeDrawable(badge, helperView);

方案三:动态调整TextView背景实现

用普通TextView配合动态背景,无需自定义View:

  • 准备两个XML Drawable:圆形背景(badge_circle.xml)、圆角矩形背景(badge_rect.xml);
  • 绑定数据时根据计数长度切换背景:
    • 计数≤9:设置圆形背景,TextView宽高设为固定值(比如24dp);
    • 计数≥10:设置圆角矩形背景,TextView宽高设为wrap_content,添加适当左右内边距;
  • 确保TextView的gravity设为center,文本居中显示。

代码示例:

TextView badgeTv = itemView.findViewById(R.id.tv_badge);
int count = data.getCount();
badgeTv.setText(String.valueOf(count));
if (count <= 9) {
    badgeTv.setBackgroundResource(R.drawable.badge_circle);
    ViewGroup.LayoutParams params = badgeTv.getLayoutParams();
    params.width = dp2px(24);
    params.height = dp2px(24);
    badgeTv.setLayoutParams(params);
    badgeTv.setPadding(dp2px(0), dp2px(0), dp2px(0), dp2px(0));
} else {
    badgeTv.setBackgroundResource(R.drawable.badge_rect);
    ViewGroup.LayoutParams params = badgeTv.getLayoutParams();
    params.width = ViewGroup.LayoutParams.WRAP_CONTENT;
    params.height = dp2px(24);
    badgeTv.setLayoutParams(params);
    badgeTv.setPadding(dp2px(8), dp2px(0), dp2px(8), dp2px(0));
}

// 辅助方法:dp转px
private int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}

内容的提问来源于stack exchange,提问作者gureisu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:07:08