现在咱们日常运用的APP中大部分控件现已赋予了圆角的特性,圆角实践上的视觉体验也比较好,不像默许那么尖利,给人一种舒适的感觉.

以前我对控件运用圆角无非就三种方法.

  1. xml文件中shape的方法
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerInParent="true"
        android:background="@drawable/shape_circle"
        />
</RelativeLayout>

shape_circle

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--    圆-->
    <corners android:radius="8dp" />
<!--    边框-->
    <solid android:color="@color/teal_200"/>
<!--    突变-->
<!--    <gradient />-->
</shape>

关于项目中圆角及特殊圆角的实际使用问题

  1. cardview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.cardview.widget.CardView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        app:cardCornerRadius="10dp"
        app:cardElevation="10dp">
        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:src="@drawable/ic_launcher_background"/>
    </androidx.cardview.widget.CardView>
</RelativeLayout>

关于项目中圆角及特殊圆角的实际使用问题

这种方法运用起来更为简单,而且CardView还自带阴影作用,直接设置特点即可,相较于xml减少了包体大小(聊胜于无).

  1. 自定义View
/**
 * 自定义圆角view
 */
public class RoundImageView extends AppCompatImageView {
    private float width, height;
    // 全部视点
    private float radius, leftRadius, rightRadius;
    // 是否是半圆
    private boolean isRound = false;
    // 底部圆角
    private boolean isBottomRound = false;
    public RoundImageView(Context context) {
        this(context, null);
    }
    public RoundImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public RoundImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }
    /**
     * 初始化
     *
     * @param context
     * @param attrs
     */
    private void init(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
        radius = array.getDimensionPixelOffset(R.styleable.RoundImageView_radius, 0);
        leftRadius = array.getDimensionPixelOffset(R.styleable.RoundImageView_left_radius, 0);
        rightRadius = array.getDimensionPixelOffset(R.styleable.RoundImageView_right_radius, 0);
        if (radius == 0 && leftRadius == 0 && rightRadius == 0) {
            isRound = true;
        }
        if (leftRadius != 0 && rightRadius != 0) {
            isBottomRound = true;
        }
        array.recycle();
    }
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        width = getWidth();
        height = getHeight();
    }
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        // 抗锯齿
        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
        Path path = new Path();
        if (isRound) {
            radius = Math.min(width, height) / 2;
        }
        // 设置布景色彩透明
        canvas.drawColor(Color.TRANSPARENT);
        Drawable drawable = getDrawable();
        int w = this.getWidth();
        int h = this.getHeight();
        if (null != drawable && w > 0 && h > 0) {
            float[] rids;
            // 圆角的半径,依次为左上角xy半径,右上角,右下角,左下角
            if (isBottomRound) {
                rids = new float[]{0, 0, 0, 0,
                        rightRadius, rightRadius, leftRadius, leftRadius};
            } else {
                rids = new float[]{radius, radius, radius, radius,
                        radius, radius, radius, radius};
            }
            path.addRoundRect(new RectF(0, 0, w, h), rids, Path.Direction.CW);
            canvas.clipPath(path);
        }
        super.onDraw(canvas);
    }
    public void setRadius(int radius) {
        this.radius = radius;
        invalidate();
    }
}

attrs

<!-- RoundImageView -->
<declare-styleable name="RoundImageView">
    <!-- 圆角的半径 -->
    <attr name="radius" format="dimension" />
    <attr name="left_radius" format="dimension" />
    <attr name="right_radius" format="dimension" />
</declare-styleable>

运用

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.jsxr.kotlintest.RoundImageView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@drawable/ic_launcher_background"
        app:radius="10dp"
        android:layout_centerInParent="true"/>
</RelativeLayout>

作用

关于项目中圆角及特殊圆角的实际使用问题

这种方法实用性上和第二种差不多,便是一开始麻烦点,你要么自己写,要么去百度仿制,但是相较于官方供给的View,这种方法自定义性比较强,你单个角圆都行.

上面三种是我以前用过的方法,最近项目重构,为了简化代码,降低体系复杂度,就另外寻找了一个功能强大的View.

GradientDrawable

关于项目中圆角及特殊圆角的实际使用问题

这是官方对于它的解说.在实践的运用上十分得劲,少了很多跟UI扯皮,自己做重复性作业的时刻,下面请看代码

东西类

public class MyShape {
    private static final ConcurrentHashMap<String, GradientDrawable> hashMap = new ConcurrentHashMap();
    /**
     * 设置圆角
     * @param context
     * @param radius
     * @return
     */
    public static GradientDrawable setMyShape(Context context, int radius) {
        int realRadius = ImageUtil.dp2px(context, radius);
        String radiusKey = String.valueOf(radius);
        if (hashMap.contains(radiusKey)) {
            return hashMap.get(radiusKey);
        } else {
            GradientDrawable drawable = new GradientDrawable();
            if (radius != 0) {
                drawable.setCornerRadius(realRadius);
            }
            hashMap.put(radiusKey, drawable);
            return drawable;
        }
    }
    /**
     * @param context
     * @param radius
     * @param bg
     * @return 自定义圆角、布景图形
     */
    public static GradientDrawable setMyShape(Context context, int radius, int bg) {
        int realRadius = ImageUtil.dp2px(context, radius);
        String key = String.valueOf(realRadius + bg);
        if (hashMap.contains(key)) {
            return hashMap.get(key);
        } else {
            GradientDrawable drawable = new GradientDrawable();
            if (radius != 0) {
                drawable.setCornerRadius(realRadius);
            }
            if (bg != 0) {
                drawable.setColor(bg);
            }
            hashMap.put(key, drawable);
            return drawable;
        }
    }
    /**
     * 设置圆角、布景、透明度
     *
     * @param radius
     * @param bg
     * @param alpha
     * @return
     */
    public static GradientDrawable setMyShapeWithAlpha(Context activity,int radius, int bg, int alpha) {
        int realRadius = ImageUtil.dp2px(activity, radius);
        String key = String.valueOf(realRadius + bg + alpha);
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        } else {
            GradientDrawable drawable = new GradientDrawable();
            drawable.setCornerRadius(radius);
            drawable.setColor(bg);
            drawable.setAlpha(alpha);
            hashMap.put(key, drawable);
            return drawable;
        }
    }
    /**
     * @param activity
     * @param topLeft,topRight,bottomLeft,bottomRight
     * @param bg
     * @return 自定义圆角、布景布局
     */
    public static GradientDrawable setMyShapeRadiusWithBg(Context activity, int topLeft, int topRight, int bottomLeft, int bottomRight, int bg) {
        topLeft = ImageUtil.dp2px(activity, topLeft);
        topRight = ImageUtil.dp2px(activity, topRight);
        bottomLeft = ImageUtil.dp2px(activity, bottomLeft);
        bottomRight = ImageUtil.dp2px(activity, bottomRight);
        String key = String.valueOf(topLeft + topRight + bottomLeft + bottomRight + bg);
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        } else {
            GradientDrawable drawable = new GradientDrawable();
            drawable.setCornerRadii(new float[]{topLeft, topLeft,
                    topRight, topRight,
                    bottomLeft, bottomLeft,
                    bottomRight, bottomRight});
            if (bg != 0) {
                drawable.setColor(bg);
            }
            hashMap.put(key, drawable);
            return drawable;
        }
    }
    /**
     * @param activity
     * @param radius
     * @param width
     * @param bg
     * @return 设置带边框的椭圆+圆角+自定义边框色彩
     */
    public static GradientDrawable setMyShapeStroke(Context activity, int radius, int width, int bg) {
        int realRadius = ImageUtil.dp2px(activity, radius);
        int realWidth = ImageUtil.dp2px(activity, width);
        String key = String.valueOf(realRadius + realWidth + bg);
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        } else {
            GradientDrawable drawable = new GradientDrawable();
            if (radius != 0) {
                drawable.setCornerRadius(realRadius);
            }
            if (width != 0 && bg != 0) {
                drawable.setStroke(realWidth, bg);
            }
            hashMap.put(key, drawable);
            return drawable;
        }
    }
    /**
     * @param activity
     * @param radius
     * @param width
     * @param strokeBg
     * @param bg
     * @return 设置带边框的椭圆,自定义内部色彩+自定义边框色彩
     */
    public static GradientDrawable setMyshapeStroke(Context activity, int radius, int width, int strokeBg, int bg) {
        int realRadius = ImageUtil.dp2px(activity, radius);
        int realWidth = ImageUtil.dp2px(activity, width);
        String key = String.valueOf(realRadius + realRadius + strokeBg);
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        } else {
            GradientDrawable drawable = new GradientDrawable();
            if (radius != 0) {
                drawable.setCornerRadius(realRadius);
            }
            if (width != 0 && strokeBg != 0) {
                drawable.setStroke(realWidth, strokeBg);
            }
            if (bg != 0) {
                drawable.setColor(bg);
            }
            hashMap.put(key, drawable);
            return drawable;
        }
    }
    /**
     * @param activity
     * @param topLeftRadius
     * @param topRightRadius
     * @param bottomRightRadius
     * @param bottomLeftRadius
     * @return 设置椭圆,并可以自定义内部色彩
     */
    public static GradientDrawable setMyShapeRadius(Context activity, int bgColor, int topLeftRadius, int topRightRadius,
                                                    int bottomRightRadius, int bottomLeftRadius) {
        GradientDrawable drawable = new GradientDrawable();
        if (bgColor != 0) {
            drawable.setColor(bgColor);
        }
        drawable.setCornerRadii(new float[]{ImageUtil.dp2px(activity, topLeftRadius), ImageUtil.dp2px(activity, topLeftRadius),
                ImageUtil.dp2px(activity, topRightRadius), ImageUtil.dp2px(activity, topRightRadius),
                ImageUtil.dp2px(activity, bottomRightRadius), ImageUtil.dp2px(activity, bottomRightRadius),
                ImageUtil.dp2px(activity, bottomLeftRadius), ImageUtil.dp2px(activity, bottomLeftRadius)});
        return drawable;
    }
    /**
     * @param startColor
     * @param endColor
     * @param angle
     * @return 设置突变色
     */
    @SuppressLint("WrongConstant")
    public static GradientDrawable setGradient(Context activity, int startColor, int endColor, int topLeftRadius, int topRightRadius,
                                               int bottomRightRadius, int bottomLeftRadius, int angle) {
        int[] colors = {startColor, endColor};
        topLeftRadius = ImageUtil.dp2px(activity, topLeftRadius);
        topRightRadius = ImageUtil.dp2px(activity, topRightRadius);
        bottomLeftRadius = ImageUtil.dp2px(activity, bottomLeftRadius);
        bottomRightRadius = ImageUtil.dp2px(activity, bottomRightRadius);
        String key = String.valueOf(topLeftRadius + topRightRadius + bottomLeftRadius + bottomRightRadius + angle);
        if (hashMap.containsKey(key)) {
            return hashMap.get(key);
        } else {
            GradientDrawable drawable = null;
            if (angle == 0) {
                drawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);
            } else if (angle == 90) {
                drawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, colors);
            } else if (angle == 180) {
                drawable = new GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, colors);
            } else if (angle == 270) {
                drawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
            } else if (angle == 315) {
                drawable = new GradientDrawable(GradientDrawable.Orientation.TL_BR, colors);
            } else {
                drawable = new GradientDrawable();
            }
            drawable.setCornerRadii(new float[]{topLeftRadius, topLeftRadius,
                    topRightRadius, topRightRadius,
                    bottomRightRadius, bottomRightRadius,
                    bottomLeftRadius, bottomLeftRadius});
            drawable.setGradientType(GradientDrawable.RECTANGLE);
            hashMap.put(key, drawable);
            return drawable;
        }
    }
}

简单用哈希表存了下参数,这个应该叫享元模式,我觉得意义不是很大

适配器

class TestAdapter(val context: Context, val list: MutableList<String>) :
    RecyclerView.Adapter<TestAdapter.ViewHolder>() {
    class ViewHolder(item: View) : RecyclerView.ViewHolder(item) {
        val layout: ConstraintLayout = item.findViewById(R.id.item_layout)
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflate = LayoutInflater.from(context).inflate(R.layout.item, parent, false)
        return ViewHolder(inflate)
    }
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        when (position) {
            1 -> holder.layout.background = MyShape.setMyShape(context,
                10,
                ContextCompat.getColor(context, R.color.design_default_color_error)
            )
            2 -> holder.layout.background = MyShape.setMyShapeStroke(context,
                15,
                3,
                ContextCompat.getColor(context, R.color.design_default_color_primary_dark)
            )
            3 -> holder.layout.background = MyShape.setMyShapeRadius(context,
                ContextCompat.getColor(context, R.color.design_default_color_secondary_variant),
                0,
                10,
                0,
                10
            )
            4 -> holder.layout.background = MyShape.setMyShapeWithAlpha(context,
                10,
                ContextCompat.getColor(context, android.R.color.holo_green_dark),
                50
            )
            5 -> holder.layout.background = MyShape.setMyShapeRadiusWithBg(context,
                15,
                0,
                15,
                0,
                ContextCompat.getColor(context,
                    android.R.color.holo_red_light))
            6 -> holder.layout.background = MyShape.setGradient(context,
                ContextCompat.getColor(context, android.R.color.holo_purple),
                ContextCompat.getColor(context, R.color.black),
                15,
                15,
                15,
                15,
                180)
        }
    }
    override fun getItemCount(): Int {
        return list.size
    }
}

item

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_layout"
    android:layout_width="50dp"
    android:layout_height="25dp"
    android:layout_margin="25dp"
    android:background="@color/black"
    >
</androidx.constraintlayout.widget.ConstraintLayout>

终究作用

关于项目中圆角及特殊圆角的实际使用问题

上面的东西类是我在咱们公司实践项目中经常运用的,实践上你们可以依据官方供给的API进行更多的创作.

这儿面有一个坑,我不修正,我只在这儿说哈 便是东西类中

setCornerRadii

他的圆角顺序应该是 左上,右上,右下,左下,里面有一个搞错了,你们运用的时候应该会发现,我就不修了

我这儿随便介绍一下API

setCornerRadius 设置圆角
setColor 设置布景色彩
setAlpha 设置透明度
setCornerRadii 设置多视点圆角
setStroke 设置边框+边框色彩
setGradientType 设置突变风格 有四种
GradientDrawable.RECTANGLE 矩形
GradientDrawable.LINE 线
GradientDrawable.RING 圆环
GradientDrawable.OVAL 圆

好啦!常用的大概便是这么多,其实东西类中我也写了点注释,我们不明白的直接评论区提问就好了,如果有时刻的话我会尽量回复给我们.