Android實現(xiàn)消息提醒小紅點效果
本人分享一下,自己寫的一個消息提醒小紅點控件,支持圓、矩形、橢圓、圓角矩形、正方形五種圖形樣式,可帶文字,支持鏈?zhǔn)讲僮鳌?br />
先看一下實現(xiàn)效果,隨便測了幾個控件(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;
// 該框架內(nèi)容的文本畫筆
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;
}
}
/**
* 設(shè)置該控件的背景顏色
*
* @param color
* 背景顏色
* @return BadgeView
*/
public BadgeView setBadgeBackgroundColor(int color) {
mBgColor = color;
mBgPaint.setColor(color);
invalidate();
return this;
}
/**
* 設(shè)置該控件的背景圖形
*
* @param shape
* 圖形
* @return
*/
public BadgeView setBackgroundShape(int shape) {
mBackgroundShape = shape;
invalidate();
return this;
}
/**
* 設(shè)置該控件的寬
*
* @param width
* 寬
* @return BadgeView
*/
public BadgeView setWidth(int width) {
this.mWidth = width;
this.setBadgeLayoutParams(width, mHeight);
return this;
}
/**
* 設(shè)置該控件的高
*
* @param height
* 高
* @return BadgeView
*/
public BadgeView setHeight(int height) {
this.mHeight = height;
this.setBadgeLayoutParams(mWidth, height);
return this;
}
/**
* 設(shè)置該控件的高和寬
*
* @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;
}
/**
* 設(shè)置該控件的位置
*
* @param gravity
* 位置
* @return BadgeView
*/
public BadgeView setBadgeGravity(int gravity) {
mGravity = gravity;
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) getLayoutParams();
params.gravity = gravity;
setLayoutParams(params);
return this;
}
/**
* 設(shè)置該控件的高和寬、位置
*
* @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;
}
/**
* 設(shè)置該控件的文本大小
*
* @param size
* 文本大?。╯p)
* @return
*/
public BadgeView setTextSize(int size) {
mTextSize = sp2px(getContext(), size);
mTextPaint.setTextSize(sp2px(getContext(), size));
invalidate();
return this;
}
/**
* 設(shè)置該控件的文本顏色
*
* @param color
* 文本顏色
* @return BadgeView
*/
public BadgeView setTextColor(int color) {
mTextColor = color;
mTextPaint.setColor(color);
invalidate();
return this;
}
/**
* 設(shè)置該控件的文本是否為粗體
*
* @param flag
*/
public void setBadgeBoldText(boolean flag) {
mTextPaint.setFakeBoldText(flag);
invalidate();
}
/**
* 設(shè)置該控件要顯示的整數(shù)文本
*
* @param count
* 要顯示的整數(shù)文本
* @return BadgeView
*/
public BadgeView setBadgeText(int count) {
mText = String.valueOf(count);
invalidate();
return this;
}
/**
* 設(shè)置該控件要顯示的整數(shù)文本數(shù)字,超過指定上限顯示為指定的上限內(nèi)容
*
* @param count
* 要顯示的整數(shù)文本
* @param maxCount
* 數(shù)字上限
* @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;
}
/**
* 設(shè)置該控件要顯示的字符串文本
*
* @param text
* 要顯示的字符串文本
* @return BadgeView
*/
public BadgeView setBadgeText(String text) {
mText = text;
invalidate();
return this;
}
/**
* 設(shè)置綁定的控件
*
* @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;
}
/**
* 設(shè)置綁定的控件
*
* @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 改控件的顯示狀態(tài)
*/
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);
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android中TabLayout添加小紅點的示例代碼
- Android應(yīng)用圖標(biāo)上的小紅點Badge實踐代碼
- Android高仿QQ小紅點功能
- Android仿QQ未讀消息--紅點拖拽刪除【源代碼】
- Android 未讀消息的紅點顯示
- Android帶數(shù)字或紅點的底部導(dǎo)航攔和聯(lián)網(wǎng)等待加載動畫示例
- Android BadgeView紅點更新信息提示示例代碼
- Android開發(fā)中TextView 實現(xiàn)右上角跟隨文本動態(tài)追加圓形紅點
- Android自定義ActionProvider ToolBar實現(xiàn)Menu小紅點
- Android 基于MediatorLiveData實現(xiàn)紅點的統(tǒng)一管理
相關(guān)文章
Kotlin封裝RecyclerView Adapter實例教程
這篇文章主要給大家介紹了關(guān)于Kotlin封裝RecyclerView Adapter的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
Android Studio使用教程(一):下載與安裝及創(chuàng)建HelloWorld項目
這篇文章主要介紹了Android Studio使用教程(一):下載與安裝及創(chuàng)建HelloWorld項目,本文用詳細的圖文說明講解了Android Studio初步使用,需要的朋友可以參考下2015-05-05
Android中TextView自動識別url且實現(xiàn)點擊跳轉(zhuǎn)
這篇文章主要介紹了關(guān)于Android中TextView自動識別url且實現(xiàn)點擊跳轉(zhuǎn)的相關(guān)資料,文中給出了詳細的示例代碼,對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03
Android?獲取手機已安裝的應(yīng)用列表實現(xiàn)詳解
這篇文章主要介紹了Android?獲取手機已安裝的應(yīng)用列表的實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08
ComposeDesktop開發(fā)桌面端多功能APK工具
這篇文章主要為大家介紹了ComposeDesktop開發(fā)桌面端多功能APK工具實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07

