在网上学习了自定义的控件之后,开始先写一个简单的自定义的TextView.
import com.xiaojiang.les.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class AutoTextView extends View {
private String text;
private int color;
private float defValue;
private Paint mPaint;
private int size;
private Rect rect;
private int mWidth;
private int mHeight;
public AutoTextView(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public AutoTextView(Context context) {
this(context, null);
}
public AutoTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initAttrs(context, attrs, -1);
}
private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) {
// 获取自定义属性的数据
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.myTextView);
text = ta.getString(R.styleable.myTextView_newText);
color = ta.getColor(R.styleable.myTextView_newTextColor, Color.YELLOW);
defValue = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics());
size = (int) ta.getDimension(R.styleable.myTextView_newTextSize, defValue);
ta.recycle();
// 初始化画笔
initPaint();
}
private void initPaint() {
mPaint = new Paint();
// 抗锯齿
mPaint.setAntiAlias(true);
mPaint.setColor(color);
mPaint.setTextSize(size);
mPaint.setStrokeWidth(2);
mPaint.setStyle(Style.FILL);
// 计算文本的宽和高
rect = new Rect();
mPaint.getTextBounds(text, 0, text.length(), rect);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wSpec = MeasureSpec.getMode(widthMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
int hSpec = MeasureSpec.getMode(heightMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
if (wSpec == MeasureSpec.AT_MOST) {
mWidth = rect.width() + getPaddingLeft() + getPaddingRight();
}
if (hSpec == MeasureSpec.AT_MOST) {
mHeight = rect.height() + getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
// 得到控件的宽和高
mWidth = getWidth();
mHeight = getHeight();
// 进行文本文字开始的设置
FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
int yStart = (mHeight - fontMetrics.descent - fontMetrics.ascent) / 2;
canvas.drawText(text, (mWidth - rect.width()) / 2, yStart, mPaint);
}
}
3.在activity_main的布局里面,代码如下:
"http://schemas.android.com/apk/res/android"
xmlns:xiaojiang="http://schemas.android.com/apk/res/com.xiaojiang.les"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<com.xiaojiang.les.view.AutoTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffffbb33"
xiaojiang:newText="hello world g"
xiaojiang:newTextColor="#ff0000"
xiaojiang:newTextSize="20sp"/>
4.好了,准备工作都已经好了,在运行在真机上之后效果很好,但是我想说的是,在上面的代码里面有几点是要注意的:
①就是在activity_main的布局里面我们在引用自定义的控件的时候要注意的是xmlns:xiaojiang=”http://schemas.android.com/apk/res/com.xiaojiang.les” 切勿将最后的格式写成com/xiaojiang/les 那就错了.
②就是View的测量模式. 要区分wrap_content match_parent 和 精确大小的情况 这三种状态下的控件的宽和高要进行区分
③就是关于将文本设置在控件的中心位置的问题 开始的X距离很简单只要记住(控件的宽 - 文本的宽)/2就可以了.但是开始的Y距离就不是那么好算了,可能会出现问题,这里有一个连接分析那个一下 [http://blog.csdn.net/xiandan87/article/details/48106797#0-tsina-1-52987-397232819ff9a47a7b7e80a40613cfe1] 这个是关于drawText()的讲解,但是我研究之后对于这个获得的中间的基线还是心存疑惑,研究的时间长了就不浪费时间了,我总结一下就是这个Y(即上面的yStart ) = (控件的高 - fontMetrics.descent - fontMetrics.ascent)/2 .
其中
fontMetrics.descent表示文本文字从所绘字符的baseline之下至该字符所绘制的最低点
fontMetrics.ascent表示文本文字从所绘字符的baseline之上至该字符所绘制的最高点