需求
1.数字为1位,显示圆形
2.数字为2位图形拉伸,左右各半圆
3.数字大于999,显示999+
4.自定义文字颜色,自定义背景色
效果(好吧,看起来挺low的)
本身并不复杂,不过作为一道计算题还是很不错的

1.自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--计数TextView-->
<declare-styleable name="CountTextView">
<attr name="z_ctv_font_size" format="reference|dimension"/>
<attr name="z_ctv_num" format="integer"/>
<attr name="z_bg_color" format="reference|color"/>
<attr name="z_txt_color" format="reference|color"/>
</declare-styleable>
</resources>
2.分析
使用圆角矩形来画背景,Paint.getTextBounds来获取文字边界矩形
1).先绘制文字,将文字左顶点与屏幕左顶点重合
2).通过计算,画出一个数时的圆角矩形两个顶点(如下图)
3).通过数字位数来控制圆角矩形两顶点的X
4).通过画布平移让圆角矩形左顶点处于画布顶点
5).计算圆角矩形的宽高,设置View大小

public class CountTextView extends View {
private int mCtvFontSize = sp(100);
private int mCtvNum = 5;
private int mCtvBgColor = 0xffBFF3F7;
private int mCtvTxtColor = Color.WHITE;
private Paint mPaint;//主画笔
private Paint mTxtPaint;
private Rect mRect;
private String mStr;
private int mOffSet;
public CountTextView(Context context) {
this(context, null);
}
public CountTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CountTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CountTextView);
mCtvFontSize = (int) a.getDimension(R.styleable.CountTextView_z_ctv_font_size, mCtvFontSize);
mCtvNum = a.getInteger(R.styleable.CountTextView_z_ctv_num, mCtvNum);
mCtvTxtColor = a.getColor(R.styleable.CountTextView_z_txt_color, mCtvTxtColor);
mCtvBgColor = a.getColor(R.styleable.CountTextView_z_bg_color, mCtvBgColor);
a.recycle();
init();
}
private void init() {
//初始化主画笔
mTxtPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTxtPaint.setColor(mCtvTxtColor);
mTxtPaint.setTextSize(mCtvFontSize);
mRect = new Rect();
mStr = mCtvNum + "";
if (mCtvNum >= 1000) {
mStr = "999+";
}
mTxtPaint.getTextBounds(mStr, 0, mStr.length(), mRect);
int AChartLen = mRect.width() / mStr.length();
mOffSet = (int) ((mStr.length() - 1) * AChartLen * 0.7f);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(mCtvBgColor);
mPaint.setStrokeWidth(mRect.height());
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//文字左侧距圆心的偏移
int offsetX = mRect.height() - mRect.width() / 2 + mOffSet;
setMeasuredDimension(2 * offsetX + mRect.width(), 2 * mRect.height());
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
int offsetX = mRect.height() - mRect.width() / 2 + mOffSet;
canvas.translate(offsetX, mRect.height() / 2);
//圆角矩形左上点
int topX = mRect.width() / 2 - mRect.height();
int topY = -mRect.height() / 2;
//圆角矩形右下点
int bottomX = mRect.height() + mRect.width() / 2;
int bottomY = mRect.height() / 2 + mRect.height();
canvas.drawRoundRect(topX - mOffSet, topY, bottomX + mOffSet, bottomY,
mRect.height(), mRect.height(), mPaint);
canvas.drawText(mStr, 0, mRect.height(), mTxtPaint);
canvas.restore();
}
private int sp(float sp) {
return (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}
}
3.使用
<com.toly1994.c.view.CountTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:z_ctv_font_size="40sp"
app:z_ctv_num="30"/>
网友评论