Android 圆形和圆角矩形总结

文章目录

Android 圆形和圆角矩形总结

ViewOutlineProvider

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

xml 复制代码
<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>
kotlin 复制代码
binding.ivClipCircle.clipToCircleView()
binding.ivClipRound.clipToRoundView(10F.dp)

Glide

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

xml 复制代码
<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>
kotlin 复制代码
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() 实现图片的圆角矩形和圆形效果。

xml 复制代码
<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>
kotlin 复制代码
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)
    }
}
kotlin 复制代码
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 属性,可以非常方便地实现圆角效果。

xml 复制代码
<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 中的一种着色器,通过它可以实现自定义的圆角和圆形图片。

xml 复制代码
 <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>
kotlin 复制代码
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
    }

}
kotlin 复制代码
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属性。

xml 复制代码
<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>
kotlin 复制代码
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 文件或者第三方库。

xml 复制代码
<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>
xml 复制代码
<style name="CircleStyle">
    <item name="cornerSize">50%</item>
</style>

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

ImageFilterView

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

xml 复制代码
<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>

源码下载

相关推荐
花菜会噎住4 分钟前
MySQL 高级特性与性能优化:深入理解函数、视图、存储过程、触发器
android·mysql·函数·索引·视图
娅娅梨6 小时前
Android- Surface, SurfaceView, TextureView, SurfaceTexture 原理图解
android·surface
2501_915918417 小时前
HTTPS 端口号详解 443 端口作用、iOS 抓包方法、常见 HTTPS 抓包工具与网络调试实践
android·网络·ios·小程序·https·uni-app·iphone
程序员码歌7 小时前
明年35岁了,如何破局?说说心里话
android·前端·后端
非门由也9 小时前
Android studio安装教程——超详细(含安装包安装教程)
android·ide·android studio
平淡风云9 小时前
Android应用添加日历提醒功能
android·日历
骐骥110 小时前
2025-09-08升级问题记录:app提示“此应用专为旧版Android打造..”或“此应用与最新版 Android 不兼容”
android·升级·不兼容·target sdk·专为旧版 android 系统
Zender Han11 小时前
Flutter 视频播放器——flick_video_player 介绍与使用
android·flutter·ios·音视频
尚久龙12 小时前
安卓学习 之 用户登录界面的简单实现
android·运维·服务器·学习·手机·android studio·安卓
Modu_MrLiu12 小时前
Android实战进阶 - 启动页
android·实战进阶·启动页·倒计时场景