前言
今天呢想做一个通知红点。本来想直接用TextView再套个background就好了。可是TextView有很多属性,能用到的只有一小部分,所以索性想自定义个干干净净的View,顺便学习一下自定义View的知识。
由于刚刚入自定义View的坑,做的比较简单...
正文
在values文件夹建立attrs.xml文件,里面写上你需要的属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="myText" format="string" />
<attr name="myTextColor" format="color" />
<attr name="myTextSize" format="dimension" />
<attr name="myBackground" format="color" />
<attr name="myShape" format="string" />
<declare-styleable name="NotifyView">
<attr name="myText" />
<attr name="myTextColor" />
<attr name="myTextSize" />
<attr name="myBackground" />
<attr name="myShape" />
</declare-styleable>
</resources>
然后新建一个自定义View继承自View,我这里把它叫做NotifyView
定义NotifyView的成员变量
//view 属性
private String text;
private int textColor;
private float textSize;
private int backgroud;
private String shape;
//定义画笔
private Paint textPaint;
private Paint shapePaint;
private int height;
private int width;
重写构造方法。由于布局文件默认调用的是两个参数的构造方法,但是我们需要用到的是三个参数的构造方法,所以我们要让他调用三个参数的构造方法。构造方法主要用来获取我们自定义的一些属性值
public NotifyView(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
public NotifyView(Context context){
this(context, null);
}
public NotifyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NotifyView, defStyle, 0);
int n=attributes.getIndexCount();
for (int i=0;i<n;i++){ int attribute=attributes.getIndex(i); switch (attribute){ case R.styleable.NotifyView_myText: text=attributes.getString(attribute); if(text.length()>2){
text="99+";
}
break;
case R.styleable.NotifyView_myTextColor:
textColor=attributes.getInt(attribute, R.color.white);
break;
case R.styleable.NotifyView_myBackground:
backgroud=attributes.getInt(attribute,R.color.red);
break;
case R.styleable.NotifyView_myShape:
shape=attributes.getString(attribute);
break;
case R.styleable.NotifyView_myTextSize:
textSize=attributes.getDimension(attribute,12);
break;
}
}
attributes.recycle();
}
然后绘制形状和文本
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 初始化画笔
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
shapePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
height=getHeight();
width=getWidth();
//文本属性
textPaint.setColor(textColor);
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTextSize(textSize);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float top = fontMetrics.top;//为基线到字体上边框的距离,即上图中的top
float bottom = fontMetrics.bottom;//为基线到字体下边框的距离,即上图中的bottom
int baseLineY = (int) (height/2 - top/2 - bottom/2);//基线中间点的y轴计算公式
shapePaint.setColor(backgroud);
if("rectangle".equals(shape)) {
shapePaint.setStyle(Paint.Style.FILL);
Rect rect=new Rect(height,width,height,width);
canvas.drawRect(rect, shapePaint);
canvas.drawText(text,width/2,baseLineY,textPaint);
}
//画圆
else {
canvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2, shapePaint);
canvas.drawText(text,width / 2,baseLineY,textPaint);
}
}
这里有一点要说明一下,就是文字居中显示的问题
这里借用网上的图来说明一下android canvas drawText()文字居中
安卓绘制文字是相对于基线绘制的,文字的高度即图中top和bottom之间的距离
要让文字水平竖直居中,就要找到图中基线上center那个点的坐标
以矩形为例,矩形中点的坐标为(width/2,height/2);黑点到基线上红点的距离为(-top+bottom)/2-bottom,即-top/2-bottom/2
所以红点的坐标为(width/2,height/2-top/2-bottom/2);
最后就是一些setter和getter方法了
public int getBackgroud() {
return backgroud;
}
public void setBackgroud(int backgroud) {
this.backgroud = backgroud;
}
public String getShape() {
return shape;
}
public void setShape(String shape) {
this.shape = shape;
}
public String getText() {
return text;
}
public void setText(String text) {
if(text.length()>2){
text="99+";
}else
this.text = text;
}
public int getTextColor() {
return textColor;
}
public void setTextColor(int textColor) {
this.textColor = textColor;
}
public float getTextSize() {
return textSize;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
接下来就可以在布局里引用了(要先在布局根标签里引入命名空间xmlns:xesygao="http://schemas.android.com/apk/res-auto")
<com.xesygao.xtieba.custom.NotifyView
android:layout_width="22dp"
android:layout_height="22dp"
android:visibility="gone"
tools:visibility="visible"
xesygao:myText="121"
xesygao:myTextSize="10sp"
xesygao:myShape="circle"
xesygao:myBackground="@color/lightRed"
xesygao:myTextColor="@color/white"
android:id="@+id/replyme_count"/>
Comments | 2 条评论
夜猫的哭泣
什么时候自己的回复可以删除呢
xesygao
@夜猫的哭泣 : 规划中,请耐心等待