Android中的自定义view和自定义属性TypedArray的使用
1、自定義View的屬性
2、在View的構造方法中獲得我們自定義的屬性
[ 3、重寫onMesure ]
4、重寫onDraw
我把3用[]標出了,所以說3不一定是必須的,當然了大部分情況下還是需要重寫的。
具體理解參考:http://blog.csdn.net/lmj623565791/article/details/24252901/
<?xml version="1.0" encoding="utf-8"?> <resources><!-- 自定義屬性名和屬性類型 --><attr name="text" format="string"/><attr name="textcolor" format="color"/><attr name="textsize" format="dimension"/><!-- 聲明屬性 --><declare-styleable name="customview03_attrs"><attr name="text"></attr><attr name="textcolor"></attr><attr name="textsize"></attr></declare-styleable> </resources>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools" xmlns:tuke="http://schemas.android.com/apk/res/com.example.customview03" android:layout_width="match_parent"android:layout_height="match_parent" ><com.example.customview03.CustomView03 android:id="@+id/view03"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="20dp"tuke:text="4327"tuke:textcolor="#ff0000"tuke:textsize="40sp"/><!-- 對于繼承的view沒有的屬性,可以使用自定義屬性,加命名空間 --></RelativeLayout>
CustomView03.java
/*** */ package com.example.customview03;import java.util.HashSet; import java.util.Random; import java.util.Set;import android.R.integer; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.View.MeasureSpec; import android.widget.TextView;/*** @author tuke**/ public class CustomView03 extends View {String text;int textcolor;int textsize;/***繪制時控制文本繪制的范圍*/private Rect mBound;private Paint mPaint;public CustomView03(Context context) {this(context,null);// 代碼初始化調用的構造函數}public CustomView03(Context context, AttributeSet attrs) {this(context, attrs,0);// xml文件初始化調用的構造函數}public CustomView03(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);// xml文件初始化調用的構造函數,獲得我們所定義的自定義樣式屬性,類型數組,把自定義屬性存放到當地變量TypedArray array=context.getTheme().obtainStyledAttributes(attrs, R.styleable.customview03_attrs, defStyleAttr, 0);int count=array.getIndexCount();for(int i=0;i<count;i++){int index=array.getIndex(i);switch (index) {case R.styleable.customview03_attrs_text:text=array.getString(index);break;case R.styleable.customview03_attrs_textcolor:textcolor=array.getInt(index, Color.BLACK);break;case R.styleable.customview03_attrs_textsize:textsize=array.getDimensionPixelSize(index, 16);break;default:break;}}array.recycle();//typearray要回收// 獲得繪制文本的寬和高 mPaint=new Paint();mPaint.setTextSize(textsize);mBound = new Rect();mPaint.getTextBounds(text, 0, text.length(), mBound);this.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {text=getRamdomText();postInvalidate();}}); }//獲得隨機4位數private String getRamdomText(){Random random = new Random();Set<Integer> set = new HashSet<Integer>();while (set.size() < 4){int randomInt = random.nextInt(10);set.add(randomInt);}StringBuffer sb = new StringBuffer();for (Integer i : set){ sb.append("" + i);}return sb.toString();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){//super.onMeasure(widthMeasureSpec, heightMeasureSpec);//xml中設置為wrap_content的話,系統測量會是滿屏/** 注意:* 重寫之前先了解MeasureSpec的specMode,一共三種類型:* EXACTLY:一般是設置了布局文件設置的是明確的值或者是MATCH_PARENT* AT_MOST:表示子布局限制在一個最大值內,一般為WARP_CONTENT* UNSPECIFIED:表示子布局想要多大就多大,很少使用* 因為正是不知道內容大小才去測量* */int width=0,height=0;//測量寬int specMode=MeasureSpec.getMode(widthMeasureSpec);int specSize=MeasureSpec.getSize(widthMeasureSpec);//主要是得到View的內容的寬度switch (specMode){case MeasureSpec.EXACTLY://1073741824width = getPaddingLeft() + getPaddingRight() + specSize;//內容的寬度+內邊距=View的寬度break;case MeasureSpec.AT_MOST://-2147483648width = getPaddingLeft() + getPaddingRight() + mBound.width();break;}//測量高specMode = MeasureSpec.getMode(heightMeasureSpec);specSize = MeasureSpec.getSize(heightMeasureSpec);//主要是得到View的內容的高度switch (specMode){case MeasureSpec.EXACTLY:height = getPaddingTop() + getPaddingBottom() + specSize;//內容的高度+內邊距=View的高度break;case MeasureSpec.AT_MOST:height = getPaddingTop() + getPaddingBottom() + mBound.height();break;}//這個方法在OnMesure中必須被調用,來存儲已經測量的寬和高setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas){mPaint.setColor(Color.YELLOW);canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);mPaint.setColor(Color.BLACK);for(int i=0;i<400;i++){Random randomx=new Random(); int rx=randomx.nextInt(getWidth());int ry=randomx.nextInt(getHeight()); canvas.drawCircle(rx, ry, 3, mPaint);}mPaint.setColor(textcolor);canvas.drawText(text, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint);}} 關于自定義屬性
1,先定義屬性文件attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources><declare-styleable name="myView"> <attr name="textColor" format="color"/> <attr name="textSize" format="dimension"/> </declare-styleable> </resources>
2,在布局文件中加入自定義屬性,加上命名空間
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:test="http://schemas.android.com/apk/res/com.example.customview04" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="helloworld" /> <com.example.customview04.CustomView04android:layout_width="fill_parent" android:layout_height="fill_parent" test:textSize="10px" test:textColor="#fff" /> <!-- test是命名空間 --> </LinearLayout>3,在自定義View的構造函數中通過TypedArray獲取自定義屬性值
package com.example.customview04;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.view.View;public class CustomView04 extends View {private Paint myPaint; private static final String myString = "Welcome to our Zoon!"; public CustomView04(Context context) { super(context); // TODO Auto-generated constructor stub } public CustomView04(Context context, AttributeSet attr) { super(context, attr); myPaint = new Paint(); //獲取自定義的屬性TypedArray a = context.obtainStyledAttributes(attr, R.styleable.myView);//TypedArray是一個數組容器 float textSize = a.getDimension(R.styleable.myView_textSize, 30);//防止在XML文件里沒有定義,就加上了默認值30 int textColor = a.getColor(R.styleable.myView_textColor, 0xFFFFFFFF);//同上,這里的屬性是:名字_屬性名 myPaint.setTextSize(textSize); myPaint.setColor(textColor); a.recycle();//我的理解是:返回以前取回的屬性,供以后使用。以前取回的可能就是textSize和textColor初始化的那段 } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); //myPaint = new Paint(); myPaint.setColor(Color.RED); myPaint.setStyle(Style.FILL); canvas.drawRect(new Rect(10,10,100,100), myPaint); myPaint.setColor(Color.WHITE); canvas.drawText(myString, 10, 100, myPaint); } }
關于TypedArray和AttributeSet
? ? ? ?AttributeSet的作用就是在控件進行初始化的時候,解析布局文件中該控件的屬性(keyeg:background)與該值(valueeg:@drawable/icon)的信息封裝在AttributeSet中,傳遞給該控件(View)的構造函數。
? ? ? ?對于非Android自帶的屬性,在View類中處理時是無法識別的,因此需要我們自己解析。所以這就要用到另外一個類TypedArray。在AttributeSet中我們有屬性名稱,有屬性值,但是控件如何知道哪個屬性代表什么意思呢?這個工作就由TypedArray來做了。
? ? ? TypedArray對象封裝了/values/attrs.xml中的styleable里定義的每個屬性的類型信息,通過TypedArray我們就可以知道AttributeSet中封裝的值到底是干什么的了,從而可以對這些數據進行應用。
具體理解參考http://blog.csdn.net/lmj623565791/article/details/45022631/
總結
以上是生活随笔為你收集整理的Android中的自定义view和自定义属性TypedArray的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 字符串根据字典值排序问题
- 下一篇: android自定义LinearLayo