Android 圆形和圆角矩形总结
文章目录
- Android 圆形和圆角矩形总结
- ViewOutlineProvider
- Glide
- Canvas#clipPath()
- CardView
- BitmapShader
- RoundedBitmapDrawable
- ShapeableImageView
- ImageFilterView
- 源码下载
Android 圆形和圆角矩形总结
ViewOutlineProvider
ViewOutlineProvider 是 Android 5.0 引入的一个类,用来定义视图的轮廓(outline
)。可以通过它来实现圆角矩形、椭圆、圆形等效果。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><ImageViewandroid:id="@+id/iv_clip_circle"android:layout_width="100dp"android:layout_height="100dp"android:layout_marginRight="10dp"android:scaleType="centerCrop"android:src="@drawable/a" /><ImageViewandroid: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 可以轻松实现图片的圆角处理。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><ImageViewandroid:id="@+id/iv_glide_circle"android:layout_width="100dp"android:layout_height="100dp"android:layout_marginRight="10dp"android:scaleType="centerCrop"android:src="@drawable/a" /><ImageViewandroid: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() 实现图片的圆角矩形和圆形效果。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><com.example.androidui.circleround.view1.CircleImageViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_marginRight="10dp"android:scaleType="centerCrop"android:src="@drawable/a" /><com.example.androidui.circleround.view1.RoundImageViewandroid: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) / 2Fpath.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
属性,可以非常方便地实现圆角效果。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><androidx.cardview.widget.CardViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="10dp"app:cardCornerRadius="100dp"><ImageViewandroid:layout_width="100dp"android:layout_height="100dp"android:scaleType="centerCrop"android:src="@drawable/a" /></androidx.cardview.widget.CardView><androidx.cardview.widget.CardViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"app:cardCornerRadius="10dp"><ImageViewandroid:layout_width="150dp"android:layout_height="100dp"android:scaleType="centerCrop"android:src="@drawable/a" /></androidx.cardview.widget.CardView>
</LinearLayout>
BitmapShader
BitmapShader 是 Android 中的一种着色器,通过它可以实现自定义的圆角和圆形图片。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><com.example.androidui.circleround.view2.CircleImageViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_marginRight="10dp"android:scaleType="centerCrop"android:src="@drawable/a" /><com.example.androidui.circleround.view2.RoundImageViewandroid: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 ?: returnval bitmap = drawableToBitmap(drawable) ?: returngetShader(bitmap)val radius = minOf(width, height) / 2fcanvas.drawCircle(width / 2F, height / 2F, radius, paint)}private fun drawableToBitmap(drawable: Drawable): Bitmap? {return when (drawable) {is BitmapDrawable -> drawable.bitmapelse -> {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: Floatval dx: Floatval dy: Floatif (bitmap.width * height > width * bitmap.height) {scale = height / bitmap.height.toFloat()dx = (width - bitmap.width * scale) * 0.5fdy = 0f} else {scale = width / bitmap.width.toFloat()dx = 0fdy = (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 ?: returnval bitmap = drawableToBitmap(drawable) ?: returngetShader(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.bitmapelse -> {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: Floatval dx: Floatval dy: Floatif (bitmap.width * height > width * bitmap.height) {scale = height / bitmap.height.toFloat()dx = (width - bitmap.width * scale) * 0.5fdy = 0f} else {scale = width / bitmap.width.toFloat()dx = 0fdy = (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属性。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><ImageViewandroid:id="@+id/iv1"android:layout_width="100dp"android:layout_height="100dp"android:layout_marginRight="10dp" /><ImageViewandroid: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 = trueisCircular = 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 = truesetCornerRadius(10F.dp)}binding.iv2.setImageDrawable(roundDrawable)
}
ShapeableImageView
ShapeableImageView 是 Android Material Components 库中的一个控件,用于轻松实现自定义形状的 ImageView。通过 ShapeableImageView,开发者可以轻松地实现圆形、圆角矩形、不同角的圆角以及其他复杂形状,而无需依赖 XML 的 shape 文件或者第三方库。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><com.google.android.material.imageview.ShapeableImageViewandroid: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.ShapeableImageViewandroid: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 并扩展了其功能。
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:gravity="center"android:orientation="horizontal"><androidx.constraintlayout.utils.widget.ImageFilterViewandroid: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.ImageFilterViewandroid:layout_width="150dp"android:layout_height="100dp"android:scaleType="centerCrop"android:src="@drawable/a"app:round="10dp" />
</LinearLayout>