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

Android平台下如何显示菱形图片及带侧边圆角的菱形图片?

嘿,这个问题我刚好在项目里处理过几次,给你分享两种靠谱的实现方案,分别对应普通菱形和带侧边圆角的菱形图片:

一、实现普通菱形图片展示

这里有两种常用的实现方式,你可以根据需求选择:

方法1:自定义ImageView通过裁剪路径实现

这种方式最直观,核心是用Path构建菱形的轮廓,然后裁剪画布,让图片只显示在菱形区域内。

class RhombusImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private val clipPath = Path()

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        // 根据View的宽高,构建菱形的四个顶点路径
        clipPath.reset()
        clipPath.moveTo(w / 2f, 0f)          // 顶部顶点
        clipPath.lineTo(w.toFloat(), h / 2f) // 右侧顶点
        clipPath.lineTo(w / 2f, h.toFloat()) // 底部顶点
        clipPath.lineTo(0f, h / 2f)          // 左侧顶点
        clipPath.close()
    }

    override fun onDraw(canvas: Canvas?) {
        canvas?.clipPath(clipPath) // 裁剪画布为菱形
        super.onDraw(canvas)       // 让系统绘制图片
    }
}

使用的时候直接在布局里引用这个自定义View就行,和普通ImageView用法一样。要是遇到API 18以下的设备(现在很少见了),记得给这个View关闭硬件加速:android:layerType="software"。

方法2:用BitmapShader绘制菱形

这种方式是把图片作为着色器,直接绘制到菱形路径上,好处是可以更精准控制图片的缩放和位置,边缘也更平滑。

class RhombusImageView2 @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)

    override fun onDraw(canvas: Canvas?) {
        val drawable = drawable ?: return
        val bitmap = (drawable as BitmapDrawable).bitmap

        // 创建图片着色器,设置拉伸模式
        val shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
        // 计算缩放比例,让图片覆盖整个菱形区域
        val scale = max(width.toFloat() / bitmap.width, height.toFloat() / bitmap.height)
        val matrix = Matrix()
        matrix.postScale(scale, scale)
        matrix.postTranslate((width - bitmap.width * scale) / 2, (height - bitmap.height * scale) / 2)
        shader.setLocalMatrix(matrix)
        paint.shader = shader

        // 绘制菱形路径
        val path = Path()
        path.moveTo(width / 2f, 0f)
        path.lineTo(width.toFloat(), h / 2f)
        path.lineTo(width / 2f, height.toFloat())
        path.lineTo(0f, h / 2f)
        path.close()
        canvas?.drawPath(path, paint)
    }
}
二、实现带侧边圆角的菱形图片

这个稍微复杂点,因为菱形的边是斜线,普通的圆角矩形方法没用,得用贝塞尔曲线手动构建带圆角的菱形路径:

class RoundedRhombusImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private val clipPath = Path()
    private var cornerRadius = 20f // 默认圆角大小,可通过自定义属性配置

    init {
        // 读取自定义属性里的圆角值
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundedRhombusImageView)
        cornerRadius = typedArray.getDimension(R.styleable.RoundedRhombusImageView_cornerRadius, cornerRadius)
        typedArray.recycle()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        clipPath.reset()

        // 菱形四个顶点坐标
        val top = Pair(w / 2f, 0f)
        val right = Pair(w.toFloat(), h / 2f)
        val bottom = Pair(w / 2f, h.toFloat())
        val left = Pair(0f, h / 2f)

        // 绘制顶部圆角
        clipPath.moveTo(top.first, top.second + cornerRadius)
        clipPath.quadTo(top.first, top.second, top.first + cornerRadius, top.second)
        // 绘制右侧圆角
        clipPath.lineTo(right.first - cornerRadius, right.second)
        clipPath.quadTo(right.first, right.second, right.first, right.second + cornerRadius)
        // 绘制底部圆角
        clipPath.lineTo(bottom.first, bottom.second - cornerRadius)
        clipPath.quadTo(bottom.first, bottom.second, bottom.first - cornerRadius, bottom.second)
        // 绘制左侧圆角
        clipPath.lineTo(left.first + cornerRadius, left.second)
        clipPath.quadTo(left.first, left.second, left.first, left.second - cornerRadius)

        clipPath.close()
    }

    override fun onDraw(canvas: Canvas?) {
        canvas?.clipPath(clipPath)
        super.onDraw(canvas)
    }
}

另外要记得在res/values/attrs.xml里添加自定义属性,这样就能在布局里直接设置圆角大小了:

<declare-styleable name="RoundedRhombusImageView">
    <attr name="cornerRadius" format="dimension" />
</declare-styleable>

布局里使用示例:

<com.yourpackage.RoundedRhombusImageView
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:src="@drawable/your_image"
    app:cornerRadius="16dp" />

一些注意事项

  • 不管哪种方式,都要确保View的宽高设置合理,比如固定大小或者匹配父布局,不然菱形的形状会变形。
  • 如果需要适配低版本系统(API < 18),记得给自定义View添加android:layerType="software"关闭硬件加速,不然裁剪路径可能不生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:16:30