现在咱们日常运用的APP中大部分控件现已赋予了圆角的特性,圆角实践上的视觉体验也比较好,不像默许那么尖利,给人一种舒适的感觉.
以前我对控件运用圆角无非就三种方法.
- 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>
- 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减少了包体大小(聊胜于无).
- 自定义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 圆
好啦!常用的大概便是这么多,其实东西类中我也写了点注释,我们不明白的直接评论区提问就好了,如果有时刻的话我会尽量回复给我们.