Android实现消息提醒小红点效果

时间:2022-07-28
本文章向大家介绍Android实现消息提醒小红点效果,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

本人分享一下,自己写的一个消息提醒小红点控件,支持圆、矩形、椭圆、圆角矩形、正方形五种图形样式,可带文字,支持链式操作。

先看一下实现效果,随便测了几个控件(TextView、ImageView、RadioButton、LinearLayout、RelativeLayout、FrameLayout),不确定其他会不会有问题。

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.RectF; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.Gravity; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.FrameLayout; 
import android.widget.TabWidget; 
public class BadgeView extends View { 
protected static final String LOG_TAG = "BadgeView"; 
// 该控件的背景图形类型 
public static final int SHAPE_CIRCLE = 1; 
public static final int SHAPE_RECTANGLE = 2; 
public static final int SHAPE_OVAL = 3; 
public static final int SHAPTE_ROUND_RECTANGLE = 4; 
public static final int SHAPE_SQUARE = 5; 
// 该框架内容的文本画笔 
private Paint mTextPaint; 
// 该控件的背景画笔 
private Paint mBgPaint; 
private int mHeight = 0; 
private int mWidth = 0; 
private int mBackgroundShape = SHAPE_CIRCLE; 
private int mTextColor = Color.WHITE; 
private int mTextSize; 
private int mBgColor = Color.RED; 
private String mText = ""; 
private int mGravity = Gravity.RIGHT | Gravity.TOP; 
private RectF mRectF; 
private float mtextH; 
private boolean mIsShow = false; 
public BadgeView(Context context) { 
this(context, null); 
} 
public BadgeView(Context context, AttributeSet attrs) { 
this(context, attrs, 0); 
} 
public BadgeView(Context context, AttributeSet attrs, int defStyleAttr) { 
super(context, attrs, defStyleAttr); 
mRectF = new RectF(); 
mTextSize = dip2px(context, 1); 
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
mTextPaint.setColor(mTextColor); 
mTextPaint.setStyle(Paint.Style.FILL); 
mTextPaint.setTextSize(mTextSize); 
mTextPaint.setTextAlign(Paint.Align.CENTER); 
mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
mBgPaint.setColor(mBgColor); 
mBgPaint.setStyle(Paint.Style.FILL); 
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( 
FrameLayout.LayoutParams.WRAP_CONTENT, 
FrameLayout.LayoutParams.WRAP_CONTENT); 
params.gravity = mGravity; 
setLayoutParams(params); 
} 
@Override 
protected void onDraw(Canvas canvas) { 
super.onDraw(canvas); 
mRectF.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); 
Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics(); 
mtextH = fontMetrics.descent - fontMetrics.ascent; 
switch (mBackgroundShape) { 
case SHAPE_CIRCLE: 
canvas.drawCircle(getMeasuredWidth() / 2f, 
getMeasuredHeight() / 2f, getMeasuredWidth() / 2, mBgPaint); 
canvas.drawText(mText, getMeasuredWidth() / 2f, getMeasuredHeight() 
/ 2f + (mtextH / 2f - fontMetrics.descent), mTextPaint); 
break; 
case SHAPE_OVAL: 
canvas.drawOval(mRectF, mBgPaint); 
canvas.drawText(mText, getMeasuredWidth() / 2f, getMeasuredHeight() 
/ 2f + (mtextH / 2f - fontMetrics.descent), mTextPaint); 
break; 
case SHAPE_RECTANGLE: 
canvas.drawRect(mRectF, mBgPaint); 
canvas.drawText(mText, getMeasuredWidth() / 2f, getMeasuredHeight() 
/ 2f + (mtextH / 2f - fontMetrics.descent), mTextPaint); 
break; 
case SHAPE_SQUARE: 
int sideLength = Math.min(getMeasuredHeight(), getMeasuredWidth()); 
mRectF.set(0, 0, sideLength, sideLength); 
canvas.drawRect(mRectF, mBgPaint); 
canvas.drawText(mText, sideLength / 2f, sideLength / 2f 
+ (mtextH / 2f - fontMetrics.descent), mTextPaint); 
break; 
case SHAPTE_ROUND_RECTANGLE: 
canvas.drawRoundRect(mRectF, dip2px(getContext(), getMeasuredWidth()/2), 
dip2px(getContext(), getMeasuredWidth()/2), mBgPaint); 
canvas.drawText(mText, getMeasuredWidth() / 2f, getMeasuredHeight() 
/ 2f + (mtextH / 2f - fontMetrics.descent), mTextPaint); 
break; 
} 
} 
/** 
* 设置该控件的背景颜色 
* 
* @param color 
*  背景颜色 
* @return BadgeView 
*/ 
public BadgeView setBadgeBackgroundColor(int color) { 
mBgColor = color; 
mBgPaint.setColor(color); 
invalidate(); 
return this; 
} 
/** 
* 设置该控件的背景图形 
* 
* @param shape 
*  图形 
* @return 
*/ 
public BadgeView setBackgroundShape(int shape) { 
mBackgroundShape = shape; 
invalidate(); 
return this; 
} 
/** 
* 设置该控件的宽 
* 
* @param width 
*  宽 
* @return BadgeView 
*/ 
public BadgeView setWidth(int width) { 
this.mWidth = width; 
this.setBadgeLayoutParams(width, mHeight); 
return this; 
} 
/** 
* 设置该控件的高 
* 
* @param height 
*  高 
* @return BadgeView 
*/ 
public BadgeView setHeight(int height) { 
this.mHeight = height; 
this.setBadgeLayoutParams(mWidth, height); 
return this; 
} 
/** 
* 设置该控件的高和宽 
* 
* @param width 
*  宽 
* @param height 
*  高 
* @return 
*/ 
public BadgeView setBadgeLayoutParams(int width, int height) { 
this.mWidth = width; 
this.mHeight = height; 
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams(); 
params.width = dip2px(getContext(), width); 
params.height = dip2px(getContext(), height); 
setLayoutParams(params); 
return this; 
} 
/** 
* 设置该控件的位置 
* 
* @param gravity 
*  位置 
* @return BadgeView 
*/ 
public BadgeView setBadgeGravity(int gravity) { 
mGravity = gravity; 
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams(); 
params.gravity = gravity; 
setLayoutParams(params); 
return this; 
} 
/** 
* 设置该控件的高和宽、位置 
* 
* @param width 
*  宽 
* @param height 
*  高 
* @param gravity 
*  位置 
* @return BadgeView 
*/ 
public BadgeView setBadgeLayoutParams(int width, int height, int gravity) { 
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams(); 
params.width = dip2px(getContext(), width); 
params.height = dip2px(getContext(), height); 
setLayoutParams(params); 
setBadgeGravity(gravity); 
return this; 
} 
/** 
* 设置该控件的文本大小 
* 
* @param size 
*  文本大小(sp) 
* @return 
*/ 
public BadgeView setTextSize(int size) { 
mTextSize = sp2px(getContext(), size); 
mTextPaint.setTextSize(sp2px(getContext(), size)); 
invalidate(); 
return this; 
} 
/** 
* 设置该控件的文本颜色 
* 
* @param color 
*  文本颜色 
* @return BadgeView 
*/ 
public BadgeView setTextColor(int color) { 
mTextColor = color; 
mTextPaint.setColor(color); 
invalidate(); 
return this; 
} 
/** 
* 设置该控件的文本是否为粗体 
* 
* @param flag 
*/ 
public void setBadgeBoldText(boolean flag) { 
mTextPaint.setFakeBoldText(flag); 
invalidate(); 
} 
/** 
* 设置该控件要显示的整数文本 
* 
* @param count 
*  要显示的整数文本 
* @return BadgeView 
*/ 
public BadgeView setBadgeText(int count) { 
mText = String.valueOf(count); 
invalidate(); 
return this; 
} 
/** 
* 设置该控件要显示的整数文本数字,超过指定上限显示为指定的上限内容 
* 
* @param count 
*  要显示的整数文本 
* @param maxCount 
*  数字上限 
* @param text 
*  超过上限要显示的字符串文本 
* @return BadgeView 
*/ 
public BadgeView setBadgeText(int count, int maxCount, String text) { 
if (count <= maxCount) { 
mText = String.valueOf(count); 
} else { 
mText = text; 
} 
invalidate(); 
return this; 
} 
/** 
* 设置该控件要显示的字符串文本 
* 
* @param text 
*  要显示的字符串文本 
* @return BadgeView 
*/ 
public BadgeView setBadgeText(String text) { 
mText = text; 
invalidate(); 
return this; 
} 
/** 
* 设置绑定的控件 
* 
* @param view 
*  要绑定的控件 
* @return BadgeView 
*/ 
public BadgeView setBindView(View view) { 
mIsShow = true; 
if (getParent() != null) 
((ViewGroup) getParent()).removeView(this); 
if (view == null) 
return this; 
if (view.getParent() instanceof FrameLayout) { 
((FrameLayout) view.getParent()).addView(this); 
} else if (view.getParent() instanceof ViewGroup) { 
ViewGroup parentContainer = (ViewGroup) view.getParent(); 
int viewIndex = ((ViewGroup) view.getParent()).indexOfChild(view); 
((ViewGroup) view.getParent()).removeView(view); 
FrameLayout container = new FrameLayout(getContext()); 
ViewGroup.LayoutParams containerParams = view.getLayoutParams(); 
container.setLayoutParams(containerParams); 
container.setId(view.getId()); 
view.setLayoutParams(new ViewGroup.LayoutParams( 
ViewGroup.LayoutParams.MATCH_PARENT, 
ViewGroup.LayoutParams.MATCH_PARENT)); 
container.addView(view); 
container.addView(this); 
parentContainer.addView(container, viewIndex); 
} else if (view.getParent() == null) { 
Log.e(LOG_TAG, "View must have a parent"); 
} 
return this; 
} 
/** 
* 设置绑定的控件 
* 
* @param view 要绑定的控件 
* @param tabIndex 要绑定的控件的子项 
*/ 
public void setBindView(TabWidget view, int tabIndex) { 
View tabView = view 
.getChildTabViewAt(tabIndex); 
this.setBindView(tabView); 
} 
/** 
* 移除绑定的控件 
* 
* @return BadgeView 
*/ 
public boolean removebindView() { 
if (getParent() != null) { 
mIsShow = false; 
((ViewGroup) getParent()).removeView(this); 
return true; 
} 
return false; 
} 
/** 
* @return 改控件的显示状态 
*/ 
public boolean isShow() { 
return mIsShow; 
} 
/** 
* @return 控件的字符串文本 
*/ 
public String getBadgeText() { 
return mText; 
} 
private int dip2px(Context context, int dip) { 
return (int) (dip 
* getContext().getResources().getDisplayMetrics().density + 0.5f); 
} 
private int sp2px(Context context, float spValue) { 
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; 
return (int) (spValue * fontScale + 0.5f); 
} 
} 

可自由定制自己喜欢的控件,为了方便使用这里还采用工厂模式封装一些基本方法,如下:

import android.content.Context; 
import android.view.Gravity; 
public class BadgeFactory { 
public static BadgeView create(Context context) { 
return new BadgeView(context); 
} 
public static BadgeView createDot(Context context) { 
return new BadgeView(context).setBadgeLayoutParams(10, 10) 
.setTextSize(0) 
.setBadgeGravity(Gravity.RIGHT | Gravity.TOP) 
.setBackgroundShape(BadgeView.SHAPE_CIRCLE); 
} 
public static BadgeView createCircle(Context context) { 
return new BadgeView(context).setBadgeLayoutParams(16, 16) 
.setTextSize(12) 
.setBadgeGravity(Gravity.RIGHT | Gravity.TOP) 
.setBackgroundShape(BadgeView.SHAPE_CIRCLE); 
} 
public static BadgeView createRectangle(Context context) { 
return new BadgeView(context).setBadgeLayoutParams(2, 20) 
.setTextSize(12) 
.setBadgeGravity(Gravity.RIGHT | Gravity.TOP) 
.setBackgroundShape(BadgeView.SHAPE_RECTANGLE); 
} 
public static BadgeView createOval(Context context) { 
return new BadgeView(context).setBadgeLayoutParams(25, 20) 
.setTextSize(12) 
.setBadgeGravity(Gravity.RIGHT | Gravity.TOP) 
.setBackgroundShape(BadgeView.SHAPE_OVAL); 
} 
public static BadgeView createSquare(Context context) { 
return new BadgeView(context).setBadgeLayoutParams(20, 20) 
.setTextSize(12) 
.setBadgeGravity(Gravity.RIGHT | Gravity.TOP) 
.setBackgroundShape(BadgeView.SHAPE_SQUARE); 
} 
public static BadgeView createRoundRect(Context context) { 
return new BadgeView(context).setBadgeLayoutParams(25, 20) 
.setTextSize(12) 
.setBadgeGravity(Gravity.RIGHT | Gravity.TOP) 
.setBackgroundShape(BadgeView.SHAPTE_ROUND_RECTANGLE); 
} 
} 

源码下载:Android实现消息提醒小红点

以上就是本文的全部内容,希望对大家的学习有所帮助。