Android自定义TextView控件

在网上学习了自定义的控件之后,开始先写一个简单的自定义的TextView.

  1. 首先在Android的工程目录的/res/values/下创建attrs.xml,里面的美容如下所示:






  2. 创建Java的class文件,名为AutoTextView.class.内容如下:
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之上至该字符所绘制的最高点

你可能感兴趣的:(Android自定义TextView控件)