码迷,mamicode.com
首页 > 其他好文 > 详细

自定义View的实现流程

时间:2014-08-10 12:41:20      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:des   android   style   blog   http   color   使用   os   

1.继承View组件,比如,LabelView继承了View
 
2.重写两个构造方法,比如,对于自定义View LabelView
 
LabelView(Context context),如果该自定义View是通过代码来实例化的,那么,就需要该构造方法;
LabelView(Context context, AttributeSet attrs),通过布局文件XML来使用该自定义View,那么,就需要该构造方法。
 
    /**
     * Constructor.  This version is only needed if you will be instantiating
     * the object manually (not from a layout XML file).
     * @param context
     */
    public LabelView(Context context) {
        super(context);
        initLabelView();
    }
 /**
     * Construct object, initializing with any attributes we understand from a
     * layout file. These attributes are defined in
     * SDK/assets/res/any/classes.xml.
     *
     * @see android.view.View#View(android.content.Context, android.util.AttributeSet)
     */
    public LabelView(Context context, AttributeSet attrs) {
        super(context, attrs);
   ....
     }
 
3.重写onDraw(Canvas canvas)和onMeasure(int measureWidth, int measureHeight)
 
onDraw(Canvas canvas),在实现自定义View的时候,你自己要创建一个Paint对象,用来设置自定义View的外观,尺寸,颜色。
然后,再在onDraw方法中,将图形绘制在系统传递过来的画布对象Canvas。
也就是说,系统回调onDraw来实现自定义View的渲染。
 
onMeasure(int measureWidth, int measureHeight),系统回调该方法,告诉你现在自定义View的宽度和高度是怎样设置的。
通过MeasureSpec.getMode(measureWidth),MeasureSpec.getSize(measureWidth)可以得到当前宽度的模式和大小。通过模式,可以知道用户设置的是wrap,match_parent,还是设置一个具体值,还说没有任何限制;通过大小,可以知道,当前系统检测到的当前View组件的宽度。
 
在得到这些信息后,你可以自己自定义,设置你想要的View组件的宽度和高度。
 
 
上面三个,就是自定义View的关键步骤。
 
-----------------------------------------------------------
 
其它方面:
1.Paint对象和Canvas的使用
 
要绘制一个自定义View,首先,你自己要确定出,图形的最终样式。按照最终样式,使用Paint对象,绘制出最终样式。Canvas对象的使用也需要关注。所以,在绘制图形的时候,要知道怎么使用Paint对象和Canvas绘制出最终的图形。
 
这方面的知识,需要补充。
 
 
2.属性设置
用户在使用你实现的自定义View的时候,它想自己定义View的属性,它想通过View提供的属性控制View的外观,尺寸,颜色等特征。那么,你实现的自定义View,就要提供给用户设置属性,并且要接收到用户传递过来的属性值,根据这些属性值构造出Paint对象。
这个的实现步骤:
1).在res目录下的values目录,创建一个attrs.xml,然后,在里面添加属性描述。如下:声明了三个属性。
bubuko.com,布布扣bubuko.com,布布扣
 
2).然后,在自定义View的类中,声明setter方法,如下:
根据用户传递过来的属性,重新绘制自定义VIew。requestLayout()的调用,会触发系统回调onMeasure(int measureWidth, int measureHeight)方法;invalidate()的调用,会触发系统回调onDraw()方法。
/**
        * Sets the text to display in this label
        *
        * @param text
        *            The text to display. This will be drawn as one line.
        */
        public void setText(String text) {
               mText = text;
               requestLayout();
              invalidate();
       }
 
 
3).在使用该自定义View的布局文件中,要声明该自定义View的命名空间,如下:
声明了一个命名空间
xmlns:app = "http://schemas.android.com/apk/res/com.example.customview"
红色部分,是该自定义View所在的包。
然后,你就可以使用app:text,这样命名空间加属性名的方式来设置属性。属性名,与attrs.xml中声明名字一样。
< RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android"
    xmlns:tools= "http://schemas.android.com/tools"
    xmlns:app= "http://schemas.android.com/apk/res/com.example.customview"
    android:layout_width= "match_parent"
    android:layout_height= "match_parent" >
 
    <com.example.customview.LabelView
        android:id ="@+id/oneLabelView"
        android:layout_width ="wrap_content"
        android:layout_height ="wrap_content"
        app:text= "Somethine"
        app:textColor ="#00868B"
        app:textSize ="34sp" />
 
</ RelativeLayout>
 
---------------下面是实现例子--------------------------
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
* Example of how to write a custom subclass of View. LabelView is used to draw
* simple text views. Note that it does not handle styled text or right-to-left
* writing systems.
* 
*/
public class LabelView extends View {
     private Paint mTextPaint;
     private String mText;
     private int mAscent;

     /**
     * Constructor. This version is only needed if you will be instantiating the
     * object manually (not from a layout XML file).
     * 
     * @param context
     */
     public LabelView(Context context) {
          super(context);
          initLabelView();
     }

     /**
     * Construct object, initializing with any attributes we understand from a
     * layout file. These attributes are defined in
     * SDK/assets/res/any/classes.xml.
     * 
     * @see android.view.View#View(android.content.Context,
     *      android.util.AttributeSet)
     */
     public LabelView(Context context, AttributeSet attrs) {
          super(context, attrs);
          initLabelView();

          TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.LabelView);

          CharSequence s = a.getString(R.styleable.LabelView_text);
          if (s != null) {
               setText(s.toString());
          }

          // Retrieve the color(s) to be used for this view and apply them.
          // Note, if you only care about supporting a single color, that you
          // can instead call a.getColor() and pass that to setTextColor().
          setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));

          int textSize = a.getDimensionPixelOffset(
                    R.styleable.LabelView_textSize, 0);
          if (textSize > 0) {
               setTextSize(textSize);
          }

          a.recycle();
     }

     private final void initLabelView() {
          mTextPaint = new Paint();
          mTextPaint.setAntiAlias(true);
          // Must manually scale the desired text size to match screen density
          mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
          mTextPaint.setColor(0xFF000000);
          setPadding(3, 3, 3, 3);
     }

     /**
     * Sets the text to display in this label
     * 
     * @param text
     *            The text to display. This will be drawn as one line.
     */
     public void setText(String text) {
          mText = text;
          requestLayout();
          invalidate();
     }

     /**
     * Sets the text size for this label
     * 
     * @param size
     *            Font size
     */
     public void setTextSize(int size) {
          // This text size has been pre-scaled by the getDimensionPixelOffset
          // method
          mTextPaint.setTextSize(size);
          requestLayout();
          invalidate();
     }

     /**
     * Sets the text color for this label.
     * 
     * @param color
     *            ARGB value for the text
     */
     public void setTextColor(int color) {
          mTextPaint.setColor(color);
          invalidate();
     }

     /**
     * @see android.view.View#measure(int, int)
     */
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          setMeasuredDimension(measureWidth(widthMeasureSpec),
                    measureHeight(heightMeasureSpec));
     }

     /**
     * Determines the width of this view
     * 
     * @param measureSpec
     *            A measureSpec packed into an int
     * @return The width of the view, honoring constraints from measureSpec
     */
     private int measureWidth(int measureSpec) {
          int result = 0;
          int specMode = MeasureSpec.getMode(measureSpec);
          int specSize = MeasureSpec.getSize(measureSpec);

          if (specMode == MeasureSpec.EXACTLY) {
               // We were told how big to be
               result = specSize;
          } else {
               // Measure the text
               result = (int) mTextPaint.measureText(mText) + getPaddingLeft()
                         + getPaddingRight();
               if (specMode == MeasureSpec.AT_MOST) {
                    // Respect AT_MOST value if that was what is called for by
                    // measureSpec
                    result = Math.min(result, specSize);
               }
          }

          return result;
     }

     /**
     * Determines the height of this view
     * 
     * @param measureSpec
     *            A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     */
     private int measureHeight(int measureSpec) {
          int result = 0;
          int specMode = MeasureSpec.getMode(measureSpec);
          int specSize = MeasureSpec.getSize(measureSpec);

          mAscent = (int) mTextPaint.ascent();
          if (specMode == MeasureSpec.EXACTLY) {
               // We were told how big to be
               result = specSize;
          } else {
               // Measure the text (beware: ascent is a negative number)
               result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop()
                         + getPaddingBottom();
               if (specMode == MeasureSpec.AT_MOST) {
                    // Respect AT_MOST value if that was what is called for by
                    // measureSpec
                    result = Math.min(result, specSize);
               }
          }
          return result;
     }

     /**
     * Render the text
     * 
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
     @Override
     protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
          canvas.drawText(mText, getPaddingLeft(), getPaddingTop() - mAscent,
                    mTextPaint);
     }
}

 

自定义View的实现流程,布布扣,bubuko.com

自定义View的实现流程

标签:des   android   style   blog   http   color   使用   os   

原文地址:http://www.cnblogs.com/ttylinux/p/3902473.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!