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
- Android View---自定义View
- Android View---自定义View
- Android 自定义View 之 自定义View属性
- 【自定义View系列】android自定义View概述
- Android自定义view自定义属性
- Android自定义控件 -- 自定义View
- android自定义view(自定义数字键盘)
- Android自定义View-自定义属性
- Android自定义View-自定义属性
- Android 自定义View
- Android 自定义 View
- android自定义View
- Android 中自定义 view
- android 自定义view组件
- Android 自定义 View
- android 自定义view
- Android:如何自定义View
- android 自定义View
- hdu5500--Reorder the Books
- yum install killall pstree
- 关于main和_tmain和wmain的区别
- Canvas的各种方法大集合
- ios 的 nonatomic属性nonatomic
- Android自定义View
- 【Leetcode】之Swap Nodes in Pairs
- 被误解的MVC
- 浅谈Thread和Runnable
- 信息检索对程序员真重要
- 软件测试相关术语定义《全程软件测试》
- javac 可以生成Java文件,但是找不到,或者无法加载主类
- Java中泛型类和方法
- 欢迎使用CSDN-markdown编辑器