Android 圆形和圆角矩形总结

发布于:2025-08-19 ⋅ 阅读:(17) ⋅ 点赞:(0)

Android 圆形和圆角矩形总结

ViewOutlineProvider

ViewOutlineProvider 是 Android 5.0 引入的一个类,用来定义视图的轮廓(outline)。可以通过它来实现圆角矩形、椭圆、圆形等效果。

在这里插入图片描述

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:gravity="center"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_clip_circle"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginRight="10dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a" />

    <ImageView
        android:id="@+id/iv_clip_round"
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a" />
</LinearLayout>
binding.ivClipCircle.clipToCircleView()
binding.ivClipRound.clipToRoundView(10F.dp)

Glide

Glide 是一个强大的图片加载库,通过它的 RequestOptions 可以轻松实现图片的圆角处理。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:gravity="center"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_glide_circle"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginRight="10dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a" />

    <ImageView
        android:id="@+id/iv_glide_round"
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a" />
</LinearLayout>
Glide.with(this)
    .load(R.drawable.a)
    .transform(CircleCrop())
    .into(binding.ivGlideCircle)
Glide.with(this)
    .load(R.drawable.a)
    .apply(RequestOptions().transform(CenterCrop(), RoundedCorners(10.dp)))
    .into(binding.ivGlideRound)

Canvas#clipPath()

自定义 ImageView 并重写 onDraw() 方法,通过 Canvas.clipPath() 实现图片的圆角矩形和圆形效果。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:gravity="center"
    android:orientation="horizontal">

    <com.example.androidui.circleround.view1.CircleImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginRight="10dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a" />

    <com.example.androidui.circleround.view1.RoundImageView
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a" />
</LinearLayout>
class CircleImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private val path = Path()

    override fun onDraw(canvas: Canvas?) {
        val radius = minOf(width, height) / 2F
        path.addCircle(width / 2F, height / 2F, radius, Path.Direction.CW)
        canvas?.clipPath(path)
        super.onDraw(canvas)
    }
}
class RoundImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatImageView(context, attrs, defStyleAttr) {

    private val path = Path()

    override fun onDraw(canvas: Canvas?) {
         path.addRoundRect(
            RectF(0F, 0F, width.toFloat(), height.toFloat()),
            10F.dp,
            10F.dp,
            Path.Direction.CW
        )
        canvas?.clipPath(path)
        super.onDraw(canvas)
    }
}

CardView

通过 CardView 的 app:cardCornerRadius 属性,可以非常方便地实现圆角效果。

<LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_margin="10dp"
              android:gravity="center"
              android:orientation="horizontal">

    <androidx.cardview.widget.CardView
                                       android:layout_width="wrap_content"
                                       android:layout_height="wrap_content"
                                       android:layout_marginRight="10dp"
                                       app:cardCornerRadius="100dp">

        <ImageView
                   android:layout_width="100dp"
                   android:layout_height="100dp"
                   android:scaleType="centerCrop"
                   android:src="@drawable/a" />
    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
                                       android:layout_width="wrap_content"
                                       android:layout_height="wrap_content"
                                       app:cardCornerRadius="10dp">

        <ImageView
                   android:layout_width="150dp"
                   android:layout_height="100dp"
                   android:scaleType="centerCrop"
                   android:src="@drawable/a" />
    </androidx.cardview.widget.CardView>
</LinearLayout>

BitmapShader

BitmapShader 是 Android 中的一种着色器,通过它可以实现自定义的圆角和圆形图片。

 <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:gravity="center"
            android:orientation="horizontal">

            <com.example.androidui.circleround.view2.CircleImageView
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_marginRight="10dp"
                android:scaleType="centerCrop"
                android:src="@drawable/a" />

            <com.example.androidui.circleround.view2.RoundImageView
                android:layout_width="150dp"
                android:layout_height="100dp"
                android:scaleType="centerCrop"
                android:src="@drawable/a" />
        </LinearLayout>

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

    private val paint by lazy { Paint(Paint.ANTI_ALIAS_FLAG) }

    override fun onDraw(canvas: Canvas) {
        drawable ?: return
        val bitmap = drawableToBitmap(drawable) ?: return
        getShader(bitmap)
        val radius = minOf(width, height) / 2f
        canvas.drawCircle(width / 2F, height / 2F, radius, paint)
    }

    private fun drawableToBitmap(drawable: Drawable): Bitmap? {
        return when (drawable) {
            is BitmapDrawable -> drawable.bitmap
            else -> {
                val bitmap = Bitmap.createBitmap(
                    drawable.intrinsicWidth,
                    drawable.intrinsicHeight,
                    Bitmap.Config.ARGB_8888
                )
                val canvas = Canvas(bitmap)
                drawable.setBounds(0, 0, canvas.width, canvas.height)
                drawable.draw(canvas)
                bitmap
            }
        }
    }

    private fun getShader(bitmap: Bitmap) {
        val shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
        val matrix = Matrix()
        val scale: Float
        val dx: Float
        val dy: Float
        if (bitmap.width * height > width * bitmap.height) {
            scale = height / bitmap.height.toFloat()
            dx = (width - bitmap.width * scale) * 0.5f
            dy = 0f
        } else {
            scale = width / bitmap.width.toFloat()
            dx = 0f
            dy = (height - bitmap.height * scale) * 0.5f
        }
        matrix.setScale(scale, scale)
        matrix.postTranslate(dx, dy)
        shader.setLocalMatrix(matrix)
        paint.shader = shader
    }

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

    private val paint by lazy { Paint(Paint.ANTI_ALIAS_FLAG) }

    override fun onDraw(canvas: Canvas) {
        drawable ?: return
        val bitmap = drawableToBitmap(drawable) ?: return
        getShader(bitmap)
        val rect = RectF(0F, 0F, width.toFloat(), height.toFloat())
        canvas.drawRoundRect(rect, 10F.dp, 10F.dp, paint)
    }

    private fun drawableToBitmap(drawable: Drawable): Bitmap? {
        return when (drawable) {
            is BitmapDrawable -> drawable.bitmap
            else -> {
                val bitmap = Bitmap.createBitmap(
                    drawable.intrinsicWidth,
                    drawable.intrinsicHeight,
                    Bitmap.Config.ARGB_8888
                )
                val canvas = Canvas(bitmap)
                drawable.setBounds(0, 0, canvas.width, canvas.height)
                drawable.draw(canvas)
                bitmap
            }
        }
    }

    private fun getShader(bitmap: Bitmap) {
        val shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
        val matrix = Matrix()
        val scale: Float
        val dx: Float
        val dy: Float
        if (bitmap.width * height > width * bitmap.height) {
            scale = height / bitmap.height.toFloat()
            dx = (width - bitmap.width * scale) * 0.5f
            dy = 0f
        } else {
            scale = width / bitmap.width.toFloat()
            dx = 0f
            dy = (height - bitmap.height * scale) * 0.5f
        }
        matrix.setScale(scale, scale)
        matrix.postTranslate(dx, dy)
        shader.setLocalMatrix(matrix)
        paint.shader = shader
    }

}

RoundedBitmapDrawable

RoundedBitmapDrawable 是 Android 提供的一个工具类,用于处理圆形或圆角矩形的图片显示。

RoundedBitmapDrawable 不支持 ImageView 的 scaleType属性。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:gravity="center"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv1"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginRight="10dp" />

    <ImageView
        android:id="@+id/iv2"
        android:layout_width="150dp"
        android:layout_height="100dp" />
</LinearLayout>
binding.iv1.post {
    val bitmap = BitmapFactory.decodeResource(resources, R.drawable.a)
    val scaleBitmap =
        centerCropBitmap(bitmap, binding.iv1.measuredWidth, binding.iv1.measuredHeight)
    val circleDrawable = RoundedBitmapDrawableFactory.create(resources, scaleBitmap).apply {
        paint.isAntiAlias = true
        isCircular = true
    }
    binding.iv1.setImageDrawable(circleDrawable)
}
binding.iv2.post {
    val bitmap = BitmapFactory.decodeResource(resources, R.drawable.a)
    val scaleBitmap =
        centerCropBitmap(bitmap, binding.iv2.measuredWidth, binding.iv2.measuredHeight)
    val roundDrawable = RoundedBitmapDrawableFactory.create(resources, scaleBitmap).apply {
        paint.isAntiAlias = true
        setCornerRadius(10F.dp)
    }
    binding.iv2.setImageDrawable(roundDrawable)
}

ShapeableImageView

ShapeableImageView 是 Android Material Components 库中的一个控件,用于轻松实现自定义形状的 ImageView。通过 ShapeableImageView,开发者可以轻松地实现圆形、圆角矩形、不同角的圆角以及其他复杂形状,而无需依赖 XML 的 shape 文件或者第三方库。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:gravity="center"
    android:orientation="horizontal">

    <com.google.android.material.imageview.ShapeableImageView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginRight="10dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a"
        app:shapeAppearance="@style/CircleStyle" />

    <com.google.android.material.imageview.ShapeableImageView
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a"
        app:shapeAppearance="@style/RoundStyle" />
</LinearLayout>
<style name="CircleStyle">
    <item name="cornerSize">50%</item>
</style>

<style name="RoundStyle">
    <item name="cornerSize">10dp</item>
</style>

ImageFilterView

ImageFilterView 是 Android 提供的一个特殊的 ImageView,它继承自 ImageView 并扩展了其功能。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:gravity="center"
    android:orientation="horizontal">

    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginRight="10dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a"
        app:roundPercent="1" />

    <androidx.constraintlayout.utils.widget.ImageFilterView
        android:layout_width="150dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/a"
        app:round="10dp" />
</LinearLayout>

源码下载


网站公告

今日签到

点亮在社区的每一天
去签到