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>

源码下载

相关推荐
踏雪羽翼17 小时前
android TextView实现文字字符不同方向显示
android·自定义view·textview方向·文字方向·textview文字显示方向·文字旋转·textview文字旋转
lxysbly17 小时前
安卓玩MRP冒泡游戏:模拟器下载与使用方法
android·游戏
夏沫琅琊20 小时前
Android 各类日志全面解析(含特点、分析方法、实战案例)
android
程序员JerrySUN20 小时前
OP-TEE + YOLOv8:从“加密权重”到“内存中解密并推理”的完整实战记录
android·java·开发语言·redis·yolo·架构
TeleostNaCl21 小时前
Android | 启用 TextView 跑马灯效果的方法
android·经验分享·android runtime
TheNextByte11 天前
Android USB文件传输无法使用?5种解决方法
android
quanyechacsdn1 天前
Android Studio创建库文件用jitpack构建后使用implementation方式引用
android·ide·kotlin·android studio·implementation·android 库文件·使用jitpack
程序员陆业聪1 天前
聊聊2026年Android开发会是什么样
android
编程大师哥1 天前
Android分层
android
极客小云1 天前
【深入理解 Android 中的 build.gradle 文件】
android·安卓·安全架构·安全性测试