您的当前位置:首页正文

【Android】多种方式实现圆角控件View、图片、背景、边框(最全)

2024-10-23 来源:个人技术集锦


实现方式

button按钮、ImageView、自定义View等各种控件或者布局常常需要这样的样式:

下面是多种方式去实现圆角效果(圆角背景或者圆角边框),各有千秋吧:

1. shape

在drawable文件夹中新建一个shape.xml文件,在其中设置背景颜色和圆角半径即可:

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <!-- 设置背景颜色 -->
    <solid android:color="#02B4FE" />
    <!-- 设置边框颜色和粗细 -->
    <stroke android:color="#02B4FE" android:width="1dp"/>
    
    <!-- 圆角半径 -->
    
	<!-- 统一设置四个角 -->
    <corners android:Radius="5dp" />
	<!-- 单独设置四个角 -->
	<corners
        android:topRightRadius="5dp"
        android:bottomRightRadius="5dp"
        android:topLeftRadius="5dp" 
        android:bottomLeftRadius="5dp"/>

</shape>

在布局或者控件中设置背景即可:

android:background="@drawable/shape"

特点:一种新的配置就需要重新创建文件,在xml中配置,可以设置背景或者边框,可以单独设置某个角。

2. ViewOutlineProvider

Android 5.x引入的新特性,用于实现View的阴影和轮廓

view.setOutlineProvider(new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                // 设置圆角半径为5
                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 5);
                // 设置按钮为圆形
                outline.setOval(0, 0, view.getWidth(), view.getHeight());
            }
        });
view.setClipToOutline(true);

特点:不需要新建文件,在java中配置,不能单独设置某个角。

3. CardView

CardView嵌套view可以实现阴影和圆角,通过cardCornerRadius设置圆角半径,cardElevation设置阴影

        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height=""
            app:cardCornerRadius="5dp"
            app:cardElevation="0dp"
            app:cardUseCompatPadding="false">
 
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"/>
 
        </androidx.cardview.widget.CardView>

特点:不需要新建文件,在xml中配置,不能单独设置某个角。

4. 第三方库

这里以Glide为例,在Glide中设置圆角可以使用transform()方法应用 RoundedCorners / GranularRoundedCorners 转换

// 设置圆角半径为10dp
int radius = 10;

//统一设置4个角
RequestOptions options = new RequestOptions().transform(new RoundedCorners(radius));
//单独设置某个角
RequestOptions options = new RequestOptions().transform(new GranularRoundedCorners(radius, radius, radius, radius));

// 在ImageView上显示圆角图片
Glide.with(context)
     .load(imageUrl)
     .apply(options)
     .into(imageView);

特点:不需要新建文件,需要导入第三方包,在java中配置,可以单独设置某个角。

5. GradientDrawable和RoundedBitmapDrawable

GradientDrawable:

	// 设置圆角半径为10dp
	int radius = 10;
	
	//同时设置四个角
    GradientDrawable drawable = new GradientDrawable();
    drawable.setShape(GradientDrawable.RECTANGLE);
    drawable.setCornerRadius(radius);
    drawable.setColor(0xFFE1F5ED);
    imageView.setImageDrawable(drawable);
    
    //单独设置四个角
    GradientDrawable drawable = new GradientDrawable();
    drawable.setShape(GradientDrawable.RECTANGLE);
    drawable.setColor(0xFFE1F5ED);
    float[] rad = new float[]{
        radius, radius,
        0f, 0f,
        0f, 0f,
        radius, radius
    };
    drawable.setCornerRadii(rad);
    imageView.setImageDrawable(drawable);

RoundedBitmapDrawable:通过RoundedBitmapDrawableFactory创建RoundedBitmapDrawable,第二个参数可以传入Bitmap(可将drawable文件转成Bitmap)、filepath、InputStream三种

	RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(getResources(),...);
	drawable.setCornerRadius(radius);
	imageView.setImageDrawable(drawable);

特点:不需要新建文件,在java中配置,GradientDrawable可以单独设置某个角,RoundedBitmapDrawable不能单独设置。

可以将这两种运用在自定义View或者Button中去·自定义控件的属性,弥补了使用shape元素的缺点,当项目中需要很多不同的样式时,只需要修改对应的属性值。

6. 自定义Drawable

新建RoundRectDrawable类,实现Drawable抽象方法,用画笔绘制draw圆角背景(圆角边框也类似)

import android.graphics.*
import android.graphics.drawable.Drawable

class RoundRectDrawable() : Drawable() {

    private val paint = Paint()

    private val path = Path()

    private lateinit var rect: RectF

    private var radius: FloatArray = floatArrayOf(
        0f, 0f,
        0f, 0f,
        0f, 0f,
        0f, 0f
    )

    init {
        paint.isAntiAlias = true
        paint.isDither = true
    }

    constructor(color: Int, radius: FloatArray) : this() {
        this.radius = radius
        paint.color = color
    }

    constructor(color: Int, radius: Float) : this(
        color, floatArrayOf(
            radius, radius,
            radius, radius,
            radius, radius,
            radius, radius
        )
    )

    constructor(color: Int) : this(
        color, floatArrayOf(
            0f, 0f,
            0f, 0f,
            0f, 0f,
            0f, 0f
        )
    )

    override fun setBounds(left: Int, top: Int, right: Int, bottom: Int) {
        super.setBounds(left, top, right, bottom)
        rect = RectF(
            left.toFloat(),
            top.toFloat(),
            right.toFloat(),
            bottom.toFloat()
        )
    }

    override fun draw(canvas: Canvas) {
        path.addRoundRect(
            rect,
            radius,
            Path.Direction.CW
        )
        canvas.drawPath(path, paint)
    }

    override fun setAlpha(alpha: Int) {
        paint.alpha = alpha
        invalidateSelf()
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        paint.colorFilter = colorFilter
        invalidateSelf()
    }

    override fun getOpacity(): Int {
        return PixelFormat.TRANSLUCENT
    }
}

在自定义View中使用:设置background属性

AppCompatTextView(context).apply {
            setTextColor(0xFF06CB7C.toInt())
            background = RoundRectDrawable(0xFFE1F5ED.toInt(), 5)
            text = ""
        }

特点:在java中配置,一次配置多次使用,可以单独设置某个角(这里是统一设置)

显示全文