Android開發(fā)之自定義View

自定義控件

使用場景: 在實際開發(fā)中經(jīng)常會遇到現(xiàn)有的UI控件不能滿足項目需求,或一個功能涉及到多個UI控件的組合,或?qū)崿F(xiàn)某一特效的UI,這時必須通過自定義View的方式,實現(xiàn)這些功能,例如股票的實時統(tǒng)計圖、電子書等。

分類

繪制控件 - 自繪控件

1.繼承View
需要自定義繪制內(nèi)容,需要繼承View,必須要重寫onDraw方法,在onDraw方法中來進(jìn)行繪制,實現(xiàn)onMeasure方法,來測量控件的空間。

2.繼承ViewGroup

  • 通過在ViewGroup中通過this.addView(<控件對象>)來添加控件
  • onMeasure方法,來測量控件的空間
  • onLayout方法必須實現(xiàn),在此方法中處理子控件的位置。當(dāng)視圖初始化,或者視圖位置發(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的子類,并提供相關(guān)的構(gòu)造方法
  • 重寫onMeasure()方法,并調(diào)用setMeasuredDimension(int width, int height)設(shè)置控件的大小
  • 重寫onDraw()方法,實現(xiàn)繪制特定內(nèi)容
  • 重寫onTouchEvent()方式處理觸摸事件
  • 在布局文件中使用<類全名>并設(shè)置屬性

自定義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屬性

在布局控件標(biāo)簽中引用: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)構(gòu)造方法中,獲取自定義屬性的值

//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();

涉及相關(guān)類

View 類

  • View(Context) 動態(tài)實例化控件的構(gòu)造方法
  • View(Context context, AttributeSet attrs) 布局中使用控件的構(gòu)造的方法
  • onMeasure(int widthMeasureSpec, int heightMeasureSpec) 自定義控件時重寫的方法,用于測量控件大小
  • onDraw(Canvas canvas) 在自義控件上繪制相關(guān)內(nèi)容
  • onTouchEvent(MotionEvent) 實現(xiàn)觸摸事件處理方法
  • setPadding(int l,int t,int r,int b) 設(shè)置內(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) 設(shè)置字體大小,像素,一般轉(zhuǎn)成sp
  • Paint.setColor(int color) 設(shè)置顏色
  • Paint.setStyle(Paint.Style) 設(shè)置畫筆樣式
  • float mTextPaint.measureText(String) 測量文字的大小
  • Paint.ascent() 獲取文字基準(zhǔn)線以上到文字頂部的間距,負(fù)數(shù)
  • Paint.descent() 獲取文字基準(zhǔn)線以下到文字底部的間距

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 兩個圖層的轉(zhuǎn)換模式

Xfermode有三個子類 :
AvoidXfermode 指定了一個顏色和容差,強制Paint避免在它上面繪圖(或者只在它上面繪圖)。
PixelXorXfermode 當(dāng)覆蓋已有的顏色時,應(yīng)用一個簡單的像素異或操作。
PorterDuffXfermode 這是一個非常強大的轉(zhuǎn)換模式,使用它,可以使用圖像合成的16條Porter-Duff規(guī)則的任意一條來控制Paint如何與已有的Canvas圖像進(jìn)行交互。


要應(yīng)用轉(zhuǎn)換模式,可以使用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>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容