接上一篇文章;我们在部署完项目后,虽然有打印输出,但是在屏幕上却没有任何显示
这是因为我们还没有调用onDraw()方法的缘故!onDraw()方法是把内容绘制到控件,调用这个方法我们需要两个类的帮助,Paint类和Canvas的帮助,paint是画笔,联想下我们在实际生活中,绘画的时候只需要一支画笔,在android也是这样,既然只需要一支画笔我们就可以把画笔定义在构造方法中!不说了看修改后的MyTextView的代码 !
package com.example.zi_ding_yi_kong_jian.myview;
import com.example.zi_ding_yi_kong_jian.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.Style;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
public class MyTextView extends View {
private int myTextColor;
private int defaultValue;
private int myTestSize;
private String myText;
private Paint myPaint;
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.myTextView);
myText = ta.getString(R.styleable.myTextView_myText);
myTextColor = ta
.getColor(R.styleable.myTextView_myTextColor, Color.RED);
defaultValue = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 12, getResources()
.getDisplayMetrics());
myTestSize = (int) ta.getDimension(R.styleable.myTextView_myTextSize,
defaultValue);
ta.recycle();// 要回收 Be sure to call recycle() when done with them
Log.i("zhang_xin", "myText=" + myText + " myTextColor=" + myTextColor
+ " MyTestSize=" + myTestSize);
//在构造方法中实例化画笔
initPaint();
}
private void initPaint() {
myPaint = new Paint();
myPaint.setColor(Color.BLACK);
myPaint.setTextSize(50);
myPaint.setStyle(Style.STROKE);
myPaint.setAntiAlias(true);
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyTextView(Context context) {
this(context, null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(myText, 100, 100, myPaint);
}
}
但是这样还有一个问题;我们先看下我们的布局中的MyTextView
<com.example.zi_ding_yi_kong_jian.myview.MyTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myandroid:myText="@string/myText"
myandroid:myTextColor="#13579a"
myandroid:myTextSize="10sp"
android:background="#08642d" />
它的宽和高都是包裹内容,但效果却是与match_parent一样,匹配父容器,
我们当然可以为他设置固定的值但是这样却很不方便,这我们就用到了onMeasure()方法;该方法就是测量view在屏幕中的长和宽!如果我们不重写他默认调用的就是父类的方法!onMeasure()方法在onDraw()方法之前调用,先测量在绘制!
父容器会调用onMeasure()方法,传进两个参数,这两个参数是父容器的宽高模式!我们首先也要判断容器的宽高模式是MeasureSpec.EXACTLY(固定值或者是match_parent)还是MeasureSpec.AT_MOST(wrap_content);我们来看下代码
package com.example.zi_ding_yi_kong_jian.myview;
import com.example.zi_ding_yi_kong_jian.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.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.View.MeasureSpec;
public class MyTextView extends View {
private int myTextColor;
private int defaultValue;
private int myTestSize;
private String myText;
private Paint myPaint;
private Rect bounds;
public MyTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.myTextView);
myText = ta.getString(R.styleable.myTextView_myText);
myTextColor = ta
.getColor(R.styleable.myTextView_myTextColor, Color.RED);
defaultValue = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 12, getResources()
.getDisplayMetrics());
myTestSize = (int) ta.getDimension(R.styleable.myTextView_myTextSize,
defaultValue);
ta.recycle();// 要回收 Be sure to call recycle() when done with them
Log.i("zhang_xin", "myText=" + myText + " myTextColor=" + myTextColor
+ " MyTestSize=" + myTestSize);
// 在构造方法中实例化画笔
initPaint();
}
private void initPaint() {
myPaint = new Paint();
myPaint.setColor(Color.BLACK);
myPaint.setTextSize(20);
myPaint.setStyle(Style.STROKE);
myPaint.setAntiAlias(true);
bounds = new Rect();
// 它返回Rect由文字所占据。但根据这个答案它,然后返回不同的TextView的宽度/高度。
myPaint.getTextBounds(myText, 0, myText.length(), bounds);
}
public MyTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyTextView(Context context) {
this(context, null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//默认是父容器的宽高模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
Log.i("zhangxin",widthSize+"");
int tempwidth = widthSize;
if (widthMode == MeasureSpec.AT_MOST) {
// 控件的宽度=所右内边距+文字的宽度。文字的宽度和高度可以在画笔中计算出
tempwidth = getPaddingLeft() + getPaddingRight() + bounds.width();
}
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int tempheight = heightSize;
if (heightMode == MeasureSpec.AT_MOST) {
tempheight = getPaddingTop() + getPaddingBottom() + bounds.height();
}
// 不需要调用父类的方法,但要把测量好的高度和宽度告诉父容器
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(tempwidth, tempheight);
Log.i("zhang_xin", "tempwidth:" + tempwidth + " " + "tempheight:"
+ tempheight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// getwidth(),getHeight()得到绘制后view的宽度和高度
Log.i("zhang_xin", "getWidth():" + getWidth() + " " + "getHeight:"
+ getHeight());
Log.i("zhang_xin", "bounds.width():" + bounds.width() + " "
+ "bounds.height():" + bounds.height());
Log.i("zhang_xin", "getMeasuredWidth():" + getMeasuredWidth() + " " + "getMeasuredHeight():"
+ getMeasuredHeight());
canvas.drawText(myText, (getWidth() - bounds.width()) / 2,
(getHeight() + bounds.height()) / 2, myPaint);
}
}
看下效果
另外本文还有个缺点,就是关于drawText的参数的问题,我给大家推荐三个链接,相信大家读完就明白了!哎我读完了,但还是有点迷糊
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0409/1143.html
http://blog.youkuaiyun.com/lovexieyuan520/article/details/43153275
http://mikewang.blog.51cto.com/3826268/871765/