Android 自定义View之BubbleImageView

文章目录

  • [Android 自定义View之BubbleImageView](#Android 自定义View之BubbleImageView)

Android 自定义View之BubbleImageView

效果

代码

xml 复制代码
<declare-styleable name="BubbleImageView">
    <attr name="radius" format="dimension" />
    <attr name="triangle_width" format="dimension" />
    <attr name="triangle_height" format="dimension" />
    <attr name="triangle_top" format="dimension" />
    <attr name="direction" format="integer">
        <enum name="left" value="1" />
        <enum name="right" value="2" />
    </attr>
</declare-styleable>
kotlin 复制代码
class BubbleImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private val path = Path()
    private var triangleWidth = DEFAULT_TRIANGLE_WIDTH // 气泡三角形的宽度
    private var triangleHeight = DEFAULT_TRIANGLE_HEIGHT // 气泡三角形的高度
    private var triangleTop = DEFAULT_TRIANGLE_TOP // 气泡三角形距离顶部距离
    private var direction = DEFAULT_DIRECTION // 气泡方向
    private var radius = DEFAULT_RADIUS // 圆角

    init {
        val a = context.obtainStyledAttributes(attrs, R.styleable.BubbleImageView)
        triangleWidth = a.getDimension(
            R.styleable.BubbleImageView_triangle_width,
            DEFAULT_TRIANGLE_WIDTH
        )
        triangleHeight = a.getDimension(
            R.styleable.BubbleImageView_triangle_height,
            DEFAULT_TRIANGLE_HEIGHT
        )
        triangleTop = a.getDimension(
            R.styleable.BubbleImageView_triangle_top,
            DEFAULT_TRIANGLE_TOP
        )
        direction = a.getInt(
            R.styleable.BubbleImageView_direction,
            DEFAULT_DIRECTION
        )
        radius = a.getDimension(
            R.styleable.BubbleImageView_radius,
            DEFAULT_RADIUS
        )
        a.recycle()
    }

    override fun onDraw(canvas: Canvas) {
        path.reset()
        when (direction) {
            LEFT -> {
                // 绘制三角形
                path.moveTo(triangleWidth, triangleTop)
                path.lineTo(0F, triangleTop + triangleHeight / 2)
                path.lineTo(triangleWidth, triangleTop + triangleHeight)
                path.close()
                // 绘制圆角矩形
                path.addRoundRect(
                    triangleWidth,
                    0F,
                    measuredWidth.toFloat(),
                    measuredHeight.toFloat(),
                    radius,
                    radius,
                    Path.Direction.CW
                )
            }

            RIGHT -> {
                path.moveTo(measuredWidth - triangleWidth, triangleTop)
                path.lineTo(measuredWidth.toFloat(), triangleTop + triangleHeight / 2)
                path.lineTo(measuredWidth - triangleWidth, triangleTop + triangleHeight)
                path.close()
                path.addRoundRect(
                    0F,
                    0F,
                    measuredWidth - triangleWidth,
                    measuredHeight.toFloat(),
                    radius,
                    radius,
                    Path.Direction.CW
                )
            }
        }
        canvas.clipPath(path)
        super.onDraw(canvas)
    }

    companion object {
        private const val LEFT = 1
        private const val RIGHT = 2
        private val DEFAULT_RADIUS = 10F.dp
        private val DEFAULT_TRIANGLE_WIDTH = 10F.dp
        private val DEFAULT_TRIANGLE_HEIGHT = 10F.dp
        private val DEFAULT_TRIANGLE_TOP = 20F.dp
        private const val DEFAULT_DIRECTION = LEFT
    }
}

使用:

xml 复制代码
<com.xiangxiongfly.core.widgets.bubble.BubbleImageView
    android:layout_width="100dp"
    android:layout_height="200dp"
    android:scaleType="centerCrop"
    android:src="@drawable/dark_image" />

<com.xiangxiongfly.core.widgets.bubble.BubbleImageView
    android:layout_width="100dp"
    android:layout_height="200dp"
    android:layout_marginTop="10dp"
    android:scaleType="centerCrop"
    android:src="@drawable/dark_image"
    app:direction="right" />

源码

相关推荐
2501_9371892317 小时前
2025 优化版神马影视 8.8 源码系统|零基础部署
android·源码·开源软件·源代码管理·机顶盒
モンキー・D・小菜鸡儿19 小时前
Android Jetpack Compose 基础控件介绍
android·kotlin·android jetpack·compose
无风之翼19 小时前
android15 休眠唤醒过程中有时候屏幕显示时间一闪而过
android·锁屏
方白羽21 小时前
Android全局悬浮拖拽视图
android·app·客户端
Jerry1 天前
Compose 高级状态和附带效应
android
2501_916007471 天前
苹果手机iOS应用管理全指南与隐藏功能详解
android·ios·智能手机·小程序·uni-app·iphone·webview
LFly_ice1 天前
Nest-管道
android·java·数据库
ab_dg_dp1 天前
android bugreport 模块源码分析
android
2501_915106321 天前
全面理解 iOS 帧率,构建从渲染到系统行为的多工具协同流畅度分析体系
android·ios·小程序·https·uni-app·iphone·webview
繁星星繁1 天前
【Mysql】数据库基础
android·数据库·mysql