王学岗自定义控件(二)
来源:互联网 发布:达内大数据 编辑:程序博客网 时间:2024/06/03 18:25
接上一篇文章;我们在部署完项目后,虽然有打印输出,但是在屏幕上却没有任何显示
这是因为我们还没有调用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.csdn.net/lovexieyuan520/article/details/43153275
http://mikewang.blog.51cto.com/3826268/871765/
- 王学岗自定义控件(二)
- 自定义UIPageControl 控件(二)
- 自定义控件(二)
- 自定义控件二
- Android自定义控件二
- 自定义控件(二)
- 自定义控件(二)
- 自定义控件二
- 自定义控件二
- 自定义控件(二)
- iOS自定义控件二
- Android自定义控件<二>
- 自定义控件二
- 自定义Switch控件二
- 自定义VB系统控件二
- .NET 自定义Button控件(二)
- 自定义控件开发示例二
- C#自定义控件简介(二)
- Android开发之多线程下载文件
- PHP register_shutdown_function函数的深入解析
- Contains Duplicate
- SCons 简介与安装
- 关于VS项目平台的x86,x64,Any CPU以及Debug和Release的区别
- 王学岗自定义控件(二)
- 解决DEDECMS Call to undefined function dede_htmlspecialchars()
- 绘图
- Dubbo高级篇--Dubbo负载均衡策略
- 使用 SCons
- MVP
- mysql auto increment特性说明
- 文章标题
- Android WebView 不能加载出全部网页