注册

什么?你连个三色渐变圆角按钮都需要UI切图?

废话不多说,先上效果图:


8ab33d9bf70c4173aef97facae966499~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

该效果其实由三部分组成:



  • 渐变
  • 圆角
  • 文本

渐变


关于渐变,估计大家都不会陌生,以往都是使用gradient进行制作:


shape_gradient.xml


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#B620E0"
android:endColor="#E38746" />
</shape>

    <View
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="@drawable/shape_gradient" />

70128dde86c9418dbf2d85f26374c580~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

但是,这个只能支持双色渐变,超过双色就无能为力了,所以,我们要考虑使用其它方式:


    /**
* Create a shader that draws a linear gradient along a line.
*
* @param x0 The x-coordinate for the start of the gradient line
* @param y0 The y-coordinate for the start of the gradient line
* @param x1 The x-coordinate for the end of the gradient line
* @param y1 The y-coordinate for the end of the gradient line
* @param colors The colors to be distributed along the gradient line
* @param positions May be null. The relative positions [0..1] of
* each corresponding color in the colors array. If this is null,
* the the colors are distributed evenly along the gradient line.
* @param tile The Shader tiling mode
*/
public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
@Nullable float positions[], @NonNull TileMode tile)

    /**
* x0、y0、x1、y1为决定渐变颜色方向的两个坐标点,x0、y0为起始坐标,x1、y1为终点坐标
* @param colors 所有渐变颜色的数组,即放多少个颜色进去,就有多少种渐变颜色
* @param positions 渐变颜色的比值,默认为均匀分布。
* 把总长度理解为1,假如里面的值为[0.3,0.2,0.5],那么,渐变的颜色就会以 0.3 : 0:2 :0.5 比例进行排版
* @param tile 着色器模式
*/
public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],
TileMode tile)

创建自定义View


public class ColorView extends View {
public ColorView(Context context) {
super(context);
}

public ColorView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public ColorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取宽高
int width = getWidth();
int height = getHeight();

//渐变的颜色
int colorStart = Color.parseColor("#E38746");
int color1 = Color.parseColor("#B620E0");
int colorEnd = Color.parseColor("#5995F6");
//绘画渐变效果
Paint paintColor = new Paint();
LinearGradient backGradient = new LinearGradient(0, height, width, 0, new int[]{colorStart, color1, colorEnd}, null, Shader.TileMode.CLAMP);
paintColor.setShader(backGradient);
canvas.drawRect(0, 0, width, height, paintColor);
}
}

    <com.jm.xpproject.ColorView
android:layout_width="match_parent"
android:layout_height="70dp" />

效果:


ddff3edf221b4ab6a2effcf3e5913678~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

圆角


关于圆角,我们需要使用到BitmapShader,使用方式:


        BitmapShader bitmapShaderColor = new BitmapShader(bitmapColor, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintFillet = new Paint();
paintFillet.setAntiAlias(true);
paintFillet.setShader(bitmapShaderColor);
//绘画到画布中
canvas.drawRoundRect(new RectF(0, 0, width, height), radius, radius, paintFillet);

由于这里的BitmapShader是对于Bitmap进行操作的,所以,对于渐变效果,我们不能直接把他绘画到原始画布上,而是生成一个Bitmap,将渐变绘画记录下来:


还是刚刚的自定义View


    @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取View的宽高
int width = getWidth();
int height = getHeight();

//第一步,绘画出一个渐变效果的Bitmap
//创建存放渐变效果的bitmap
Bitmap bitmapColor = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvasColor = new Canvas(bitmapColor);
//渐变的颜色
int colorStart = Color.parseColor("#E38746");
int color1 = Color.parseColor("#B620E0");
int colorEnd = Color.parseColor("#5995F6");
//绘画渐变效果
Paint paintColor = new Paint();
LinearGradient backGradient = new LinearGradient(0, height, width, 0, new int[]{colorStart, color1, colorEnd}, null, Shader.TileMode.CLAMP);
paintColor.setShader(backGradient);
canvasColor.drawRect(0, 0, width, height, paintColor);
//第二步,绘画出一个圆角渐变效果
//绘画出圆角渐变效果
BitmapShader bitmapShaderColor = new BitmapShader(bitmapColor, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintFillet = new Paint();
paintFillet.setAntiAlias(true);
paintFillet.setShader(bitmapShaderColor);
//绘画到画布中
canvas.drawRoundRect(new RectF(0, 0, width, height), 100, 100, paintFillet);
}

效果:


c7328afcfa3445ed816a2d0db8d12000~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

至于中间的空白部分,其实我们依葫芦画瓢,再画上一个白色的圆角Bitmap即可:


        //创建存放白底的bitmap
Bitmap bitmapWhite = Bitmap.createBitmap(width - colorWidth * 2, height - colorWidth * 2, Bitmap.Config.RGB_565);
bitmapWhite.eraseColor(Color.parseColor("#FFFFFF"));

BitmapShader bitmapShaderWhite = new BitmapShader(bitmapWhite, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintWhite = new Paint();
paintWhite.setAntiAlias(true);
paintWhite.setShader(bitmapShaderWhite);
// 将白色Bitmap绘制到画布上面
canvas.drawRoundRect(new RectF(colorWidth, colorWidth, width - colorWidth, height - colorWidth), radius, radius, paintWhite);

总体代码:



@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取View的宽高
int width = getWidth();
int height = getHeight();

//第一步,绘画出一个渐变效果的Bitmap
//创建存放渐变效果的bitmap
Bitmap bitmapColor = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvasColor = new Canvas(bitmapColor);
//渐变的颜色
int colorStart = Color.parseColor("#E38746");
int color1 = Color.parseColor("#B620E0");
int colorEnd = Color.parseColor("#5995F6");
//绘画渐变效果
Paint paintColor = new Paint();
LinearGradient backGradient = new LinearGradient(0, height, width, 0, new int[]{colorStart, color1, colorEnd}, null, Shader.TileMode.CLAMP);
paintColor.setShader(backGradient);
canvasColor.drawRect(0, 0, width, height, paintColor);
//第二步,绘画出一个圆角渐变效果
//绘画出圆角渐变效果
BitmapShader bitmapShaderColor = new BitmapShader(bitmapColor, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintFillet = new Paint();
paintFillet.setAntiAlias(true);
paintFillet.setShader(bitmapShaderColor);
//绘画到画布中
canvas.drawRoundRect(new RectF(0, 0, width, height), 100, 100, paintFillet);

//第三步,绘画出一个白色的bitmap覆盖上去
//创建存放白底的bitmap
Bitmap bitmapWhite = Bitmap.createBitmap(width - 5 * 2, height - 5 * 2, Bitmap.Config.RGB_565);
bitmapWhite.eraseColor(Color.parseColor("#FFFFFF"));

BitmapShader bitmapShaderWhite = new BitmapShader(bitmapWhite, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintWhite = new Paint();
paintWhite.setAntiAlias(true);
paintWhite.setShader(bitmapShaderWhite);
// 将白色Bitmap绘制到画布上面
canvas.drawRoundRect(new RectF(5, 5, width - 5, height - 5), 100, 100, paintWhite);
}

效果:


d95a91be404345528fba30c6a2a5d425~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

文本


像文本就简单了,使用drawText即可,只要注意在绘画的时候,要对文本进行居中显示,因为 Android 默认绘画文本,是从左下角进行绘画的,就像这样:


        Paint paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setColor(Color.parseColor("#000000"));
paintText.setTextSize(100);
canvas.drawText("收藏", width / 2, height / 2, paintText);
canvas.drawLine(width / 2, 0, width / 2, height, paintText);
canvas.drawLine(0, height / 2, width, height / 2, paintText);

1f058a459f7d46829490b6882401dc15~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

正确做法:


        String text = "收藏";
Rect rect = new Rect();
Paint paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setColor(Color.parseColor("#000000"));
paintText.setTextSize(100);
paintText.getTextBounds(text, 0, text.length(), rect);
int widthFont = rect.width();//文本的宽度
int heightFont = rect.height();//文本的高度
canvas.drawText(text, (width - widthFont) / 2, (height+heightFont) / 2, paintText);

b0317fd3d57449419f2825bba6b79c14~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

至此,基本功能的制作就完成了



@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取View的宽高
int width = getWidth();
int height = getHeight();

//第一步,绘画出一个渐变效果的Bitmap
//创建存放渐变效果的bitmap
Bitmap bitmapColor = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvasColor = new Canvas(bitmapColor);
//渐变的颜色
int colorStart = Color.parseColor("#E38746");
int color1 = Color.parseColor("#B620E0");
int colorEnd = Color.parseColor("#5995F6");
//绘画渐变效果
Paint paintColor = new Paint();
LinearGradient backGradient = new LinearGradient(0, height, width, 0, new int[]{colorStart, color1, colorEnd}, null, Shader.TileMode.CLAMP);
paintColor.setShader(backGradient);
canvasColor.drawRect(0, 0, width, height, paintColor);
//第二步,绘画出一个圆角渐变效果
//绘画出圆角渐变效果
BitmapShader bitmapShaderColor = new BitmapShader(bitmapColor, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintFillet = new Paint();
paintFillet.setAntiAlias(true);
paintFillet.setShader(bitmapShaderColor);
//绘画到画布中
canvas.drawRoundRect(new RectF(0, 0, width, height), 100, 100, paintFillet);

//第三步,绘画出一个白色的bitmap覆盖上去
//创建存放白底的bitmap
Bitmap bitmapWhite = Bitmap.createBitmap(width - 5 * 2, height - 5 * 2, Bitmap.Config.RGB_565);
bitmapWhite.eraseColor(Color.parseColor("#FFFFFF"));

BitmapShader bitmapShaderWhite = new BitmapShader(bitmapWhite, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
Paint paintWhite = new Paint();
paintWhite.setAntiAlias(true);
paintWhite.setShader(bitmapShaderWhite);
// 将白色Bitmap绘制到画布上面
canvas.drawRoundRect(new RectF(5, 5, width - 5, height - 5), 100, 100, paintWhite);

String text = "收藏";
Rect rect = new Rect();
Paint paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setColor(Color.parseColor("#000000"));
paintText.setTextSize(100);
paintText.getTextBounds(text, 0, text.length(), rect);
int widthFont = rect.width();//文本的宽度
int heightFont = rect.height();//文本的高度
canvas.drawText(text, (width - widthFont) / 2, (height+heightFont) / 2, paintText);
}

封装


上面虽然已经把全部功能都讲解完了,但是,假如就直接这样放入项目中,是极其不规范的,无法动态设置文本、文本大小、颜色厚度等等


这里,我进行了简易封装,大家可以基于此进行业务修改:


attrs.xml


    <declare-styleable name="GradientColorButton">
<attr name="btnText" format="string" />
<attr name="btnTextSize" format="dimension" />
<attr name="btnTextColor" format="color" />
<attr name="colorWidth" format="dimension" />
<attr name="colorRadius" format="dimension" />
</declare-styleable>

public class GradientColorButton extends View {

/**
* 文本
*/
private String text = "";
/**
* 文本颜色
*/
private int textColor;
/**
* 文本大小
*/
private float textSize;
/**
* 颜色的宽度
*/
private float colorWidth;
/**
* 圆角度数
*/
private float radius;

//渐变的颜色
private int colorStart = Color.parseColor("#E38746");
private int color1 = Color.parseColor("#B620E0");
private int colorEnd = Color.parseColor("#5995F6");

//控件的宽高
private int width;
private int height;
/**
* 渐变颜色的Bitmap
*/
private Bitmap bitmapColor;

//画笔
private Paint paintColor;
private Paint paintFillet;
private Paint paintWhite;
private Paint paintText;
//字体的宽高
private int widthFont;
private int heightFont;

public GradientColorButton(Context context) {
super(context);
}

public GradientColorButton(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public GradientColorButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

//获取参数
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.GradientColorButton, defStyleAttr, 0);

text = a.getString(R.styleable.GradientColorButton_btnText);
textColor = a.getColor(R.styleable.GradientColorButton_btnTextColor, Color.BLACK);
textSize = a.getDimension(R.styleable.GradientColorButton_btnTextSize, 16);
colorWidth = a.getDimension(R.styleable.GradientColorButton_colorWidth, 5);
radius = a.getDimension(R.styleable.GradientColorButton_colorRadius, 100);


}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);

//获取View的宽高
width = getWidth();
height = getHeight();

//制作一个渐变效果的Bitmap
createGradientBitmap();

//初始化圆角配置
initFilletConfiguration();

//初始化白色Bitmap配置
initWhiteBitmapConfiguration();

//初始化文本配置
initTextConfiguration();

}


/**
* 创建渐变颜色的Bitmap
*/
private void createGradientBitmap() {
//创建存放渐变效果的bitmap
bitmapColor = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvasColor = new Canvas(bitmapColor);
LinearGradient backGradient = new LinearGradient(0, height, width, 0, new int[]{colorStart, color1, colorEnd}, null, Shader.TileMode.CLAMP);
//绘画渐变效果
paintColor = new Paint();
paintColor.setShader(backGradient);
canvasColor.drawRect(0, 0, width, height, paintColor);
}


/**
* 初始化圆角配置
*/
private void initFilletConfiguration() {
//绘画出圆角渐变效果
BitmapShader bitmapShaderColor = new BitmapShader(bitmapColor, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
paintFillet = new Paint();
paintFillet.setAntiAlias(true);
paintFillet.setShader(bitmapShaderColor);
}

/**
* 初始化白色Bitmap配置
*/
private void initWhiteBitmapConfiguration() {
//创建存放白底的bitmap
Bitmap bitmapWhite = Bitmap.createBitmap((int) (width - colorWidth * 2), (int) (height - colorWidth * 2), Bitmap.Config.RGB_565);
bitmapWhite.eraseColor(Color.parseColor("#FFFFFF"));

BitmapShader bitmapShaderWhite = new BitmapShader(bitmapWhite, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 初始化画笔
paintWhite = new Paint();
paintWhite.setAntiAlias(true);
paintWhite.setShader(bitmapShaderWhite);
}

/**
* 初始化文本配置
*/
private void initTextConfiguration() {
Rect rect = new Rect();
paintText = new Paint();
paintText.setAntiAlias(true);
paintText.setColor(textColor);
paintText.setTextSize(textSize);
if (!TextUtils.isEmpty(text)) {
paintText.getTextBounds(text, 0, text.length(), rect);
widthFont = rect.width();//文本的宽度
heightFont = rect.height();//文本的高度

}
}


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

//将圆角渐变bitmap绘画到画布中
canvas.drawRoundRect(new RectF(0, 0, width, height), radius, radius, paintFillet);
// 将白色Bitmap绘制到画布上面
canvas.drawRoundRect(new RectF(colorWidth, colorWidth, width - colorWidth, height - colorWidth), radius, radius, paintWhite);


if (!TextUtils.isEmpty(text)) {
canvas.drawText(text, (width - widthFont) / 2, (height + heightFont) / 2, paintText);
}

}
}

    <com.jm.xpproject.GradientColorButton
android:layout_width="120dp"
android:layout_height="70dp"
android:layout_margin="10dp"
app:btnText="收藏"
app:btnTextColor="#123456"
app:btnTextSize="18sp"
app:colorRadius="50dp"
app:colorWidth="5dp" />

6b771a558514486abfc5bc2a0417af29~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp

作者:不近视的猫
链接:https://juejin.cn/post/7110035318954262542
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册