import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class GradientBorderDrawable extends Drawable {
private int[] mColors = null;
private float[] mPositions = null;
private float mCornerRadius = 0f;
private int mAlpha = 0xFF;
private boolean mIsLeftTopCornerRound = true;
private boolean mIsRightTopCornerRound = true;
private boolean mIsRightBottomCornerRound = true;
private boolean mIsLeftBottomCornerRound = true;
private float[] mCornerRadii = null;
private Orientation mOrientation = Orientation.TOP_BOTTOM;
private boolean mPathIsDirty = true;
private boolean mGradientIsDirty = true;
private RectF mRect = new RectF();
private Path mPath = new Path();
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@Override
public void draw(@NonNull Canvas canvas) {
if (mAlpha <= 0) {
return;
}
int[] drawColors = mColors;
if (!ensureValidRect(drawColors)) {
return;
}
mPaint.setAlpha(mAlpha);
updateRound();
if (mCornerRadii != null) {
buildPathIfDirty(drawColors);
canvas.drawPath(mPath, mPaint);
} else {
canvas.drawRect(mRect, mPaint);
}
}
@Override
public void setAlpha(int alpha) {
if (alpha != mAlpha) {
mAlpha = alpha;
invalidateSelf();
}
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
}
@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
private boolean ensureValidRect(int[] colors) {
if (mGradientIsDirty) {
mGradientIsDirty = false;
mRect.set(getBounds());
if (colors != null) {
RectF r = mRect;
float x0;
float x1;
float y0;
float y1;
switch (mOrientation) {
case RIGHT_LEFT:
x0 = r.right;
y0 = r.top;
x1 = r.left;
y1 = y0;
break;
case BOTTOM_TOP:
x0 = r.left;
y0 = r.bottom;
x1 = x0;
y1 = r.top;
break;
case LEFT_RIGHT:
x0 = r.left;
y0 = r.top;
x1 = r.right;
y1 = y0;
break;
case LT_BR:
x0 = r.left;
y0 = r.top;
x1 = r.right;
y1 = r.bottom;
break;
default:
x0 = r.left;
y0 = r.top;
x1 = x0;
y1 = r.bottom;
break;
}
mPaint.setShader(new LinearGradient(
x0, y0, x1, y1,
colors, mPositions, Shader.TileMode.CLAMP
));
}
}
return !mRect.isEmpty();
}
private void updateRound() {
if (mCornerRadius <= 0) {
mCornerRadii = null;
return;
}
if (mCornerRadii == null) {
mCornerRadii = new float[8];
}
if (mIsLeftTopCornerRound) {
mCornerRadii[0] = mCornerRadius;
} else {
mCornerRadii[0] = 0;
}
if (mIsLeftTopCornerRound) {
mCornerRadii[1] = mCornerRadius;
} else {
mCornerRadii[1] = 0;
}
if (mIsRightTopCornerRound) {
mCornerRadii[2] = mCornerRadius;
} else {
mCornerRadii[2] = 0;
}
if (mIsRightTopCornerRound) {
mCornerRadii[3] = mCornerRadius;
} else {
mCornerRadii[3] = 0;
}
if (mIsRightBottomCornerRound) {
mCornerRadii[4] = mCornerRadius;
} else {
mCornerRadii[4] = 0;
}
if (mIsRightBottomCornerRound) {
mCornerRadii[5] = mCornerRadius;
} else {
mCornerRadii[5] = 0;
}
if (mIsLeftBottomCornerRound) {
mCornerRadii[6] = mCornerRadius;
} else {
mCornerRadii[6] = 0;
}
if (mIsLeftBottomCornerRound) {
mCornerRadii[7] = mCornerRadius;
} else {
mCornerRadii[7] = 0;
}
}
private void buildPathIfDirty(int[] colors) {
if (mPathIsDirty) {
ensureValidRect(colors);
mPath.reset();
if (mCornerRadii != null) {
mPath.addRoundRect(mRect, mCornerRadii, Path.Direction.CW);
}
mPathIsDirty = false;
}
}
public void setColor(@ColorInt int color) {
mPaint.setColor(color);
mGradientIsDirty = true;
invalidateSelf();
}
public void setColors(@ColorInt int[] colors) {
setColors(colors, null);
}
public void setColors(@ColorInt int[] colors, float[] offset) {
mGradientIsDirty = true;
mPositions = offset; //需要重新计算mPositions
mColors = colors;
invalidateSelf();
}
public void setOrientation(Orientation value) {
if (mOrientation == value) {
return;
}
mGradientIsDirty = true;
mOrientation = value;
invalidateSelf();
}
public void setCornerRadius(float cornerRadius) {
if (mCornerRadius != cornerRadius) {
mPathIsDirty = true;
mCornerRadius = cornerRadius;
invalidateSelf();
}
}
public void setRoundCorner(boolean lt, boolean rt, boolean rb, boolean lb) {
mPathIsDirty = true;
mIsLeftTopCornerRound = lt;
mIsRightTopCornerRound = rt;
mIsRightBottomCornerRound = rb;
mIsLeftBottomCornerRound = lb;
if (mCornerRadius <= 0 && (mIsLeftTopCornerRound || mIsRightTopCornerRound || mIsRightBottomCornerRound
|| mIsLeftBottomCornerRound)
) {
mCornerRadius = 9f;
}
invalidateSelf();
}
//设置后将只显示边框
public void setStrokeWidth(float strokeWidth) {
if (strokeWidth == mPaint.getStrokeWidth()) {
return;
}
if (strokeWidth > 0) {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(strokeWidth);
} else {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(0f);
}
mGradientIsDirty = true;
}
public void setAntiAlias(boolean alias) {
mPaint.setAntiAlias(alias);
invalidateSelf();
}
@Override
public void setDither(boolean dither) {
mPaint.setDither(dither);
invalidateSelf();
}
enum Orientation {
TOP_BOTTOM,
RIGHT_LEFT,
BOTTOM_TOP,
LEFT_RIGHT,
LT_BR
}
}
使用:
int[] colors = {getResources().getColor(R.color.blue),
getResources().getColor(R.color.green),
getResources().getColor(R.color.read),
getResources().getColor(R.color.gold),
getResources().getColor(R.color.purple)};
float[] offset = {0f, 0.2f, 0.5f, 0.9f, 1f};
GradientBorderDrawable drawable = new GradientBorderDrawable();
drawable.setColors(colors, offset);
// drawable.setStrokeWidth(6);//设置后将只显示边框
drawable.setCornerRadius(9);
// drawable.setAlpha(100);
drawable.setOrientation(GradientBorderDrawable.Orientation.TOP_BOTTOM);
findViewById(R.id.background).setBackground(drawable);