开头必水,这一次水一个小红点,我是用draw绘制的方式实现。小红点的思路也很简单,就是在开头和结尾绘制两个圆,中间绘制一个矩形(滑稽.jpg)。
效果大概长这样:
分别是:无内容、短内容、长内容。
为了比较直观和方便使用,我做了一个小红点布局控件用来展示,效果大概这样:
实现方式是在左右两边绘制圆,中间绘制矩形,如图:
本篇我们只展示小红点的核心代码,内容不是很多。
为了减少文本这块的工作量,小红点继承的是 AppCompatTextView。
基本的初始化设置
private void init() {
//绘制小红点的画笔
mPaint = new Paint();
//测量文本内容长度的画笔(拓展内容中会用到)
mMeasurePaint = new Paint();
mRect = new Rect(); //绘制矩形
mRectF = new RectF(); //绘制圆
//设置抗锯齿
mPaint.setAntiAlias( true );
//背景颜色( redDotBackgroundColor色值为:#eb2700 )
setRedDotBackgroundColor( redDotBackgroundColor );
//文本内容居中
setGravity( Gravity.CENTER );
//只能显示一行
setMaxLines(1);
}
重写onDraw方法绘制小红点
这里需要讲的是中间部分(矩形)left参数用高度是因为小红点的宽度会根据内容发生改变。
@Override
protected void onDraw(Canvas canvas) {
//绘制左边的圆
mRectF.set(0, 0,getHeight(), getHeight());
canvas.drawOval(mRectF, mPaint);
//绘制右边的圆
mRectF.set(getWidth() - getHeight(), 0, getWidth(), getHeight());
canvas.drawOval(mRectF, mPaint);
//绘制中间部分
mRect.set(getHeight() / 2,0, getWidth() - getHeight() / 2, getHeight());
canvas.drawRect(mRect, mPaint);
super.onDraw(canvas);
}
到这里就结束了。但是!既然要水我们就水长一点。上边我们说到了矩形的left由控件的实际高度控制,因为宽度会发生改变。但实际上内容时...
实际效果
emmmmm好像哪里不对???所以在此基础上我们要在内容改变时重新绘制控件的宽度,这里我用的办法是先测量文本内容的宽度,然后在原有控件的宽度基础上在加上文本宽度。
先测量文本宽度
这里用到之前提到的测量画笔
/**
* 获取测量的文本长度
* @return 文本的实际长度
*/
public int getMeasureText() {
mMeasurePaint.setTextSize( getTextSize() );
return (int) mMeasurePaint.measureText(getText().toString());
}
处理改变的宽度
private int initWidth, redDotMinWidth, redDotMinHeight;
/**
* 根据内容改变宽度
*/
private void doChangeWidth() {
ViewGroup.LayoutParams lp;
int len;
if( initWidth == - 1 ) return;
lp = getLayoutParams();
len = getText().length();
if( len == 0 ) {
//没有内容时设置为小红点,这里的最小宽高度为:10
lp.width = redDotMinWidth;
lp.height = redDotMinHeight;
}else {
//短内容:默认宽度(初始化时设置的宽度,接下来的代码片段会说到)
//长内容:默认宽度 + 测量的文本宽度
lp.width = len <= 1 ? initWidth : initWidth + getMeasureText();
}
setLayoutParams( lp );
}
最后我们重写dispatchDraw()方法调用doChangeWidth()
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
//先记录最开始设置的宽度,短内容时还原原始宽度
if( initWidth == -1 && getWidth() != 0 ) initWidth = getWidth();
//根据内容改变宽度
doChangeWidth();
}
上述一顿操作后基本上就解决了宽度不改变的问题。
最后!完整代码在我的码云仓库里边,因为后期进行了迭代,代码量稍微有点多,需要的可以去看看。