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

Android XML实现带尾巴的聊天消息背景Drawable

Android 实现带尾巴的聊天消息背景方案

下面给你三种实用的实现方式,按需选择:

方法一:VectorDrawable 矢量图实现(推荐)

矢量图支持自适应拉伸且不失真,适合简单的圆角+尾巴样式。以左侧尾巴的消息为例,创建 drawable/chat_bubble_left.xml:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="240dp"
    android:height="120dp"
    android:viewportWidth="240"
    android:viewportHeight="120">

    <!-- 主背景+左下角尾巴 -->
    <path
        android:fillColor="#E5E5EA"
        android:pathData="M20,0 L220,0 L220,100 L20,100 L20,20 L0,10 L20,0 Z" />
</vector>

如果是右侧尾巴的消息,调整 pathData 把尾巴放在右下角即可:

<path
    android:fillColor="#007AFF"
    android:pathData="M20,0 L220,0 L220,10 L240,20 L220,30 L220,100 L20,100 Z" />

使用时直接将其设为 TextView 或布局的 background,还能通过 android:tint 修改颜色。

方法二:9-Patch 图片实现

适合复杂样式,上手快:

  • 用设计工具(PS/Sketch)绘制带尾巴的背景图,注意尾巴部分不要做拉伸处理
  • 在 Android Studio 中右键图片 → Create 9-Patch file,用工具标记可拉伸区域和内容显示区域
  • 将生成的 .9.png 放入 drawable 目录,直接作为 View 的背景使用

方法三:自定义 Drawable 代码实现

需要动态调整尾巴方向、大小或颜色时用这种方式:

class ChatBubbleDrawable(private val isRightBubble: Boolean) : Drawable() {
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = if (isRightBubble) Color.parseColor("#007AFF") else Color.parseColor("#E5E5EA")
    }
    private val path = Path()

    override fun draw(canvas: Canvas) {
        val bounds = bounds
        val cornerRadius = 16f // 圆角大小
        val tailWidth = 12f    // 尾巴宽度
        val tailHeight = 16f   // 尾巴高度

        path.reset()
        // 绘制主圆角矩形
        val rectLeft = if (isRightBubble) bounds.left.toFloat() else bounds.left + tailWidth
        val rectRight = if (isRightBubble) bounds.right - tailWidth else bounds.right.toFloat()
        path.addRoundRect(
            rectLeft, bounds.top.toFloat(),
            rectRight, bounds.bottom.toFloat(),
            cornerRadius, cornerRadius, Path.Direction.CW
        )
        // 添加尾巴路径
        val tailX = if (isRightBubble) bounds.right.toFloat() else bounds.left.toFloat()
        val tailY = bounds.bottom - tailHeight
        path.moveTo(tailX, tailY)
        path.lineTo(if (isRightBubble) tailX - tailWidth else tailX + tailWidth, bounds.bottom.toFloat())
        path.lineTo(if (isRightBubble) tailX - tailWidth else tailX + tailWidth, tailY + tailHeight / 2)
        path.close()

        canvas.drawPath(path, paint)
    }

    override fun setAlpha(alpha: Int) {
        paint.alpha = alpha
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        paint.colorFilter = colorFilter
    }

    override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
}

使用示例:

// 给TextView设置右侧气泡背景
messageTv.background = ChatBubbleDrawable(isRightBubble = true)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 17:54:58