Android自定义View

来源:互联网 发布:剑三 点绛唇捏脸数据 编辑:程序博客网 时间:2024/06/16 05:04

Android自定义View的步骤:

1、编写一个类(class)继承自View(貌似还可以继承自Drawable);

2、编写自定义属性文件(不是必须)

3、在类的构造方法中获取自定义的属性值(不是必须)

4、复写onMeasure方法测量自定义view的宽高、如果复写了就必须调用setMeasuredDimension方法设置自定义view的宽高(不是必须)

5、复习onDraw方法,绘制想要的界面/结果


1、编写一个类(class)继承自View

public class MyView extends View

2、编写自定义属性文件

在android工程res->values文件夹下建立attrs.xml文件

属性有下面这些类型:

    <attr name="colorValue" format="color" />      <attr name="floatValue" format="float" />      <attr name="integerValue" format="integer" />      <attr name="booleanValue" format="boolean" />      <attr name="dimensionValue" format="dimension" />      <attr name="stringValue" format="string" />      <attr name="referenceValue" format="color|reference" />      <attr name="imageValue" format="reference"/>        <attr name="Visibility">      <enum name="invisible" value="0" />     <enum name="visible" value="1" />      <enum name="gone" value="2" />      </attr>
有颜色、浮点型、整型、布尔、尺寸(dp、sp)、字符串、引用、enum

定义的属性文件如下

<?xml version="1.0" encoding="utf-8"?><resources>   <!--  <attr name="TextColor" format="color"/>    <attr name="float" format="color"/>    <attr name="int" format="integer"/>    <attr name="bool" format="boolean"/>    <attr name="dimens" format="dimension"/>    <attr name="text" format="string"/>    <attr name="background" format="color"/>    <attr name="image" format="reference"/>    <attr name="Visibility">        <enum name="VISIBLE" value="0" />     <enum name="INVISIBLE" value="1" />      <enum name="GONE" value="2" />        </attr> -->        <declare-styleable name="MyView">          <attr name="TextColor" format="color"/>    <attr name="f" format="float"/>    <attr name="i" format="integer"/>    <attr name="bool" format="boolean"/>    <attr name="dimens" format="dimension"/>    <attr name="text" format="string"/>    <attr name="background" format="color|reference"/>    <attr name="image" format="reference"/>    <attr name="Visibility">        <enum name="VISIBLE" value="0" />     <enum name="INVISIBLE" value="1" />      <enum name="GONE" value="2" />        </attr>    </declare-styleable></resources>

上面的定义和下面的定义的效果貌似是一样的

<?xml version="1.0" encoding="utf-8"?><resources>    <attr name="TextColor" format="color"/>    <attr name="f" format="color"/>    <attr name="i" format="integer"/>    <attr name="bool" format="boolean"/>    <attr name="dimens" format="dimension"/>    <attr name="text" format="string"/>    <attr name="background" format="color"/>    <attr name="image" format="reference"/>    <attr name="Visibility">        <enum name="VISIBLE" value="0" />     <enum name="INVISIBLE" value="1" />      <enum name="GONE" value="2" />        </attr>        <declare-styleable name="MyView">          <attr name="TextColor"/>    <attr name="f"/>    <attr name="i"/>    <attr name="bool"/>    <attr name="dimens"/>    <attr name="text"/>    <attr name="background"/>    <attr name="image"/>    <attr name="Visibility"/>    </declare-styleable></resources>


3、在类的构造方法中获取自定义的属性值


自定义view中的field如下:

private Paint mPaint;private float mTitleTextSize = 150.0f;private Rect mBounds;private int textcolor;private float f;private int integer;private boolean b;private int dimens;private int background;private Drawable backgroundDrawable;private int visiblity;private Drawable image;private Bitmap bitmap;private int drawablwID;private String mTitle;

获取属性值


由一个特殊的

String attributeValue = attrs.getAttributeValue(null, "textsize");if (attributeValue!=null) {try {mTitleTextSize=Integer.parseInt(attributeValue);} catch (Exception e) {}}

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyView, defStyleAttr, 0);          int n = a.getIndexCount();          for (int i = 0; i < n; i++)          {              int index = a.getIndex(i);              switch (index)              {              case R.styleable.MyView_TextColor:              textcolor = a.getColor(index,Color.BLACK);                  break;              case R.styleable.MyView_f:              f = a.getFloat(index, 0.0f);              break;              case R.styleable.MyView_i:              integer = a.getInt(index, 0);              break;              case R.styleable.MyView_bool:              b = a.getBoolean(index, false);              break;              case R.styleable.MyView_dimens:              dimens = a.getDimensionPixelSize(index, 0);              break;              case R.styleable.MyView_text:            mTitle=a.getString(index);            break;            case R.styleable.MyView_background:  //            try {//background = a.getColor(index,Color.BLACK);//} catch (Exception e) {//System.out.println("------getColor Exception-----");//backgroundDrawable=a.getDrawable(index);//}              backgroundDrawable=a.getDrawable(index);            break;              case R.styleable.MyView_image:              image = a.getDrawable(index);             break;              case R.styleable.MyView_Visibility:              visiblity = a.getInt(index, 0);              break;              }            }  

最后打印输出一下各个数据

StringBuilder sb=new StringBuilder()        .append("textcolor="+textcolor)        .append("\nf="+f)        .append("\ninteger="+integer)        .append("\nb="+b)        .append("\ndimens="+dimens)        .append("\nmTitle="+mTitle)        .append("\nbackground="+background)        .append("\nbackgroundDrawable="+backgroundDrawable)        .append("\nimage="+image)        .append("\nvisiblity="+visiblity)        ;        System.out.println(sb.toString());

注意:获取完属性后调用TypedArray 的recycle方法!!!!!!!!

a.recycle();

4、复写onMeasure方法测量自定义view的宽高

虽然这个方法不是必须复写的、但是不复写可能或显示不正常,比如wrap_content时是全屏等

代码如下,是会在一段文字,注释掉的部分是绘制图片时测试宽高的方法

int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);int width;int height;if (widthMode == MeasureSpec.EXACTLY) {width = widthSize;} else {mPaint.setTextSize(mTitleTextSize);mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);float textWidth = mBounds.width();int desired = (int) (getPaddingLeft() + textWidth + getPaddingRight());width = desired;//width=bitmap.getWidth()+getPaddingLeft()+getPaddingRight();}if (heightMode == MeasureSpec.EXACTLY) {height = heightSize;} else {mPaint.setTextSize(mTitleTextSize);mPaint.getTextBounds(mTitle, 0, mTitle.length(), mBounds);float textHeight = mBounds.height();int desired = (int) (getPaddingTop() + textHeight + getPaddingBottom());height = desired;//height=bitmap.getHeight()+getPaddingTop()+getPaddingBottom();}                <strong></strong><pre name="code" class="html">                setMeasuredDimension(width, height);

千万记住最后调用setMeasuredDimension(width, height);方式设置尺寸

5、复习onDraw方法,绘制想要的界面

注释掉部分为画图片的代码

FontMetrics fontMetrics = mPaint.getFontMetrics();canvas.drawText(mTitle, getWidth() / 2 - mBounds.width() / 2,//getHeight() / 2 + mBounds.height() / 2, //-fontMetrics.top,getHeight()/2-(fontMetrics.ascent+fontMetrics.descent)/2,mPaint);System.out.println("----------------------------------");System.out.println("getw="+getWidth()+",getH="+getHeight());System.out.println("canvas.getw="+canvas.getWidth()+",canvas.geth="+canvas.getHeight());System.out.println("mBounds.w="+mBounds.width()+",mBounds.h="+mBounds.height());System.out.println("getpaddingl="+getPaddingLeft()+",getpaddingr="+getPaddingRight());mPaint.setColor(Color.RED);canvas.drawLine(0, getHeight()/2, getWidth(), getHeight()/2, mPaint);//画中心线看文字是否画得垂直居中//canvas.drawBitmap(bitmap, //getWidth()/2-bitmap.getWidth()/2, //getHeight()/2-bitmap.getHeight()/2, //mPaint);

6、定义好View后View的使用方法

6.1 在代码中使用的话、(应该在自定义view中实现相关属性field的get、set方法)直接new出实例后addView到ViewGroup中

6.2在布局文件中使用

 <com.example.myview.MyView        android:id="@+id/myview"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerInParent="true"        android:padding="15dip"        csl:TextColor="#00f"        csl:f="123.0"        csl:i="36"        csl:bool="true"        csl:dimens="20dp"        csl:text="songlin_2015"        csl:background="#0f0"        csl:image="@drawable/ic_launcher"        csl:Visibility="GONE"        textsize="150"/>


有问题请多多指教 代码下载


最后来一张效果图压压惊:

------end----- 关于测量文字和绘制文字单独记录一篇


0 0