【安卓Android】自定义控件之小红点消息提醒控件

it2024-12-12  14

开头必水,这一次水一个小红点,我是用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(); }

上述一顿操作后基本上就解决了宽度不改变的问题。 

最后!完整代码在我的码云仓库里边,因为后期进行了迭代,代码量稍微有点多,需要的可以去看看。

小红点控件传送门小红点布局控件传送门XML中的参数传送门(RedDotLayout和RedDotView) 疯狂暗示!!!

 

最新回复(0)