自定義控件
使用場景: 在實際開發(fā)中經(jīng)常會遇到現(xiàn)有的UI控件不能滿足項目需求咖刃,或一個功能涉及到多個UI控件的組合泳炉,或?qū)崿F(xiàn)某一特效的UI,這時必須通過自定義View的方式嚎杨,實現(xiàn)這些功能花鹅,例如股票的實時統(tǒng)計圖、電子書等枫浙。
分類
繪制控件 - 自繪控件
1.繼承View
需要自定義繪制內(nèi)容刨肃,需要繼承View,必須要重寫onDraw方法箩帚,在onDraw方法中來進行繪制真友,實現(xiàn)onMeasure方法,來測量控件的空間紧帕。
2.繼承ViewGroup
- 通過在ViewGroup中通過this.addView(<控件對象>)來添加控件
- onMeasure方法盔然,來測量控件的空間
- onLayout方法必須實現(xiàn),在此方法中處理子控件的位置是嗜。當視圖初始化愈案,或者視圖位置發(fā)生改變時候,調(diào)用此方法鹅搪。
組合控件
通過繼承系統(tǒng)已經(jīng)存在的視圖容器站绪,在初始化時候,直接加載布局
mInflater.inflate(<布局資源的ID>,this);
mIvBack = (ImageView) findViewById(R.id.btn_back);
繼承控件
通過繼承系統(tǒng)已經(jīng)存在的視圖或者視圖容器丽柿,在內(nèi)部改變此視圖或者視圖容器的功能
例如:通過改變ListView添加刪除功能
自定義View步驟
- 創(chuàng)建類恢准,繼承View及View的子類,并提供相關的構造方法
- 重寫onMeasure()方法甫题,并調(diào)用setMeasuredDimension(int width, int height)設置控件的大小
- 重寫onDraw()方法顷歌,實現(xiàn)繪制特定內(nèi)容
- 重寫onTouchEvent()方式處理觸摸事件
- 在布局文件中使用<類全名>并設置屬性
自定義View屬性
1.位置:res/values/attrs.xml
2.屬性集
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 聲明屬性集 -->
<declare-styleable name="LabelView">
<attr name="text" format="string"/>
<attr name="textSize" format="dimension"/>
<attr name="textColor" format="color" />
</declare-styleable>
</resources>
3.指定屬性名及其內(nèi)容格式
例:<attr name="text" format="string" />
string 字符型
integer 整數(shù)型
dimension 尺寸值
color 顏色值
reference 參考某一資源ID
boolean:布爾值
使用自定義View屬性
在布局控件標簽中引用:xmlns:my="http://schemas.android.com/apk/res/{package_name}"
或xmlns:app="http://schemas.android.com/apk/res-auto"
在自定義控件中使用:my:text=““或app:text=""
在自定義View的View(Context context, AttributeSet attrs)構造方法中,獲取自定義屬性的值
//TypedArray是一個用來存放由context.obtainStyledAttributes獲得的屬性的數(shù)組
//在使用完成后,一定要調(diào)用recycle方法
TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.LabelView);
CharSequence s = ta.getString(R.styleable.LabelView_text);
if (s != null) {
setText(s.toString());
}
setTextColor(ta.getColor(R.styleable.LabelView_textColor, 0xFF000000));
int textSize = ta.getDimensionPixelSize(R.styleable.LabelView_textSize, 0);
if (textSize > 0) {
setTextSize(textSize);
}
ta.recycle();
涉及相關類
View 類
- View(Context) 動態(tài)實例化控件的構造方法
- View(Context context, AttributeSet attrs) 布局中使用控件的構造的方法
- onMeasure(int widthMeasureSpec, int heightMeasureSpec) 自定義控件時重寫的方法幔睬,用于測量控件大小
- onDraw(Canvas canvas) 在自義控件上繪制相關內(nèi)容
- onTouchEvent(MotionEvent) 實現(xiàn)觸摸事件處理方法
- setPadding(int l,int t,int r,int b) 設置內(nèi)部間距
- layout(int l, int t, int r,int b) 改變控件位置的方法
- requestLayout() //清除布局眯漩,獲取新的布局空間(刷新UI,重新調(diào)用onDraw()方法繪制UI)
- invalidate() //重新繪制新的數(shù)據(jù)(刷新UI麻顶,重新調(diào)用onDraw()方法繪制UI)
MeasureSpec 測量空間工具類
- int MeasureSpec.getMode(mSpec) 獲取控件大小模式
- MeasureSpec.EXACTLY辅肾,確切空間,布局中的屬性值一般為match_parent或160dp固定值
- MeasureSpec.AT_MOST 盡量多的空間要尔,布局中的屬性值wrap_content
- MeasureSpec.UNSPECIFIED 未指定的,一般在父控件中使用
- MeasureSpec.getSize(mSpec) 獲取控件大小
TypedArray 屬性數(shù)組類
- TypeArray Context.obtainStyledAttributes(attrs,R.styleable.LabelView) 獲取指定attrs中的所有屬性
- String getString(R.styleable.LabelView_text) 獲取指定屬性的文本值
- int getDimensionPixelSize(R.styleable.LabelView_textSize, 0) 獲取指定屬性的間距值
- int getColor(R.styleable.LabelView_textColor, 0xFF000000) 獲取指定屬性的顏色值
Paint 畫筆類
- Paint.setAntiAlias(true) 啟用抗鋸齒
- Paint.setTextSize(int pixes) 設置字體大小既绩,像素饲握,一般轉成sp
- Paint.setColor(int color) 設置顏色
- Paint.setStyle(Paint.Style) 設置畫筆樣式
- float mTextPaint.measureText(String) 測量文字的大小
- Paint.ascent() 獲取文字基準線以上到文字頂部的間距蚕键,負數(shù)
- Paint.descent() 獲取文字基準線以下到文字底部的間距
Canvas 畫布類
- canvas.drawText(String,int x,int y,Paint) 繪制文本
- canvas.drawRoundRect(RectF,int rx,int ry,Paint) 繪制圓角四邊方形
- canvas.drawBitmap(bitmap, left, top, paint) 繪制圖片
- canvas.drawCircle(cx, cy, radius, paint) 繪制圓
- canvas.drawLine(startX, startY, stopX, stopY, paint) 繪制線條
Xfermode 兩個圖層的轉換模式
Xfermode有三個子類 :
AvoidXfermode 指定了一個顏色和容差锣光,強制Paint避免在它上面繪圖(或者只在它上面繪圖)。
PixelXorXfermode 當覆蓋已有的顏色時骑疆,應用一個簡單的像素異或操作箍铭。
PorterDuffXfermode 這是一個非常強大的轉換模式椎镣,使用它,可以使用圖像合成的16條Porter-Duff規(guī)則的任意一條來控制Paint如何與已有的Canvas圖像進行交互冷守。
要應用轉換模式拍摇,可以使用setXferMode方法,如下所示:
AvoidXfermode avoid = new AvoidXfermode(Color.BLUE, 10, AvoidXfermode.Mode. AVOID);
borderPen.setXfermode(avoid);
PorterDuff.Mode為枚舉類,一共有16個枚舉值:
1.PorterDuff.Mode.CLEAR
所繪制不會提交到畫布上充活。
2.PorterDuff.Mode.SRC
顯示上層繪制圖片
3.PorterDuff.Mode.DST
顯示下層繪制圖片
4.PorterDuff.Mode.SRC_OVER
正常繪制顯示混卵,上下層繪制疊蓋窖张。
5.PorterDuff.Mode.DST_OVER
上下層都顯示。下層居上顯示赘淮。
6.PorterDuff.Mode.SRC_IN
取兩層繪制交集。顯示上層走诞。
7.PorterDuff.Mode.DST_IN
取兩層繪制交集低剔。顯示下層襟齿。
8.PorterDuff.Mode.SRC_OUT
取上層繪制非交集部分枕赵。
9.PorterDuff.Mode.DST_OUT
取下層繪制非交集部分拷窜。
10.PorterDuff.Mode.SRC_ATOP
取下層非交集部分與上層交集部分
11.PorterDuff.Mode.DST_ATOP
取上層非交集部分與下層交集部分
12.PorterDuff.Mode.XOR
異或:去除兩圖層交集部分
13.PorterDuff.Mode.DARKEN
取兩圖層全部區(qū)域,交集部分顏色加深
14.PorterDuff.Mode.LIGHTEN
取兩圖層全部赋荆,點亮交集部分顏色
15.PorterDuff.Mode.MULTIPLY
取兩圖層交集部分疊加后顏色
16.PorterDuff.Mode.SCREEN
取兩圖層全部區(qū)域窄潭,交集部分變?yōu)橥该魃?/p>