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>

源码下载

相关推荐
消失的旧时光-19434 小时前
Flutter 响应式 + Clean Architecture / MVU 模式 实战指南
android·flutter·架构
404未精通的狗5 小时前
(数据结构)栈和队列
android·数据结构
恋猫de小郭5 小时前
今年各大厂都在跟进的智能眼镜是什么?为什么它突然就成为热点之一?它是否是机会?
android·前端·人工智能
游戏开发爱好者87 小时前
iOS 混淆工具链实战 多工具组合完成 IPA 混淆与加固 无源码混淆
android·ios·小程序·https·uni-app·iphone·webview
豆豆豆大王12 小时前
Android 数据持久化(SharedPreferences)
android
Paper_Love12 小时前
RK3588-android-reboot命令内核调用流程
android
介一安全12 小时前
【Frida Android】基础篇12:Native层hook基础——调用原生函数
android·网络安全·逆向·安全性测试·frida·1024程序员节
2501_9160088913 小时前
用多工具组合把 iOS 混淆做成可复用的工程能力(iOS混淆|IPA加固|无源码混淆|Ipa Guard|Swift Shield)
android·开发语言·ios·小程序·uni-app·iphone·swift
Zach_yuan13 小时前
程序地址空间
android·linux·运维·服务器
带电的小王14 小时前
llama.cpp:Android端测试Qwen2.5-Omni
android·llama.cpp·qwen2.5-omni