android-自定義View

前言

在Android應(yīng)用的開發(fā)里面靴患,UI是非常重要的一部分。一般情況下豁状,我們使用SDK自帶的控件捉偏,加上一些開源庫,已經(jīng)可以實(shí)現(xiàn)大部分的UI效果了泻红。但是要實(shí)現(xiàn)一些自定義效果得UI夭禽,往往需要通過自定義View來實(shí)現(xiàn)。掌握或是精通自定義View谊路,無疑是加分技能讹躯。

繪制

  • 方式:重寫繪制方法(最常用的方法:onDraw(Canvas canvas))

繪制:Android里的繪制是在每個View的繪制方法里發(fā)生的,View的繪制方法里寫了什么代碼缠劝,它就會繪制成什么內(nèi)容潮梯。而自定義View就是通過重寫繪制方法,去繪制成想要實(shí)現(xiàn)的效果惨恭。

public class TextView extends View{
...
    @Override
   protected void onDraw(Canvas canvas){
   super.onDraw(canvas);
    ...//TextView的繪制代碼
    }
...
}
public class ImageView extends View{
...
    @Override
   protected void onDraw(Canvas canvas){
   super.onDraw(canvas);
    ...//ImageView 的繪制代碼
    }
...
}
public class MyView extends View{
...
    @Override
    protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    ...//MyView 的繪制代碼
    }
...
}

onDraw()這個繪制方法秉馏,它負(fù)責(zé)的是View的主體的繪制。例如TextView的文字脱羡、ImageView的圖像萝究,都是在onDraw()里繪制的免都。具體執(zhí)行繪制操作的是onDraw()方法里的Canvas參數(shù)。

  • 繪制關(guān)鍵:Canvas帆竹,Canvas是一個繪制工具绕娘,它唯一的功能就是繪制
    • Canvas的繪制類方法:drawXX()
    • Canvas的輔助類方法:范圍裁切(clipXXX())和幾何變換(Matrix)
  • 使用不同的繪制方法來控制遮蓋關(guān)系

測量、布局

布局過程的自定義
  • 方式:重寫布局過程的相關(guān)方法
    1. 測量過程:onMeasure()
    2. 布局過程:onLayout()
  • 場景:
    1馆揉、重寫onMeasure()來修改已有的View的尺寸
    方式:
    1)业舍、重寫 onMeasure() 方法,并在里面調(diào)用 super.onMeasure() 升酣,觸發(fā)原有的自我測量;
    2)态罪、在 super.onMeasure() 的下面用getMeasuredWidth()和getMeasuredHeight()來獲取到之前的測量結(jié)果噩茄,并使用自己的算法,根據(jù)測量結(jié)果計算出新的結(jié)果复颈;
    3)绩聘、調(diào)用setMeasuredDimension()來保存新的結(jié)果。
public class SquareTextView extends TextView {
    ...省略部分代碼
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //先執(zhí)行原測量算法
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //獲取原先的測量結(jié)果
        int measureWidth = getMeasuredWidth();
        int measuredHeight = getMeasuredHeight();

        //利用原先的測量結(jié)果計算出新尺寸
        if (measureWidth>measuredHeight){
            measureWidth = measuredHeight;
        }else {
            measuredHeight = measureWidth;
        }

        //保存計算后的結(jié)果
        setMeasuredDimension(measureWidth,measuredHeight);
    }
}

2耗啦、重寫onMeasure()來全新計算自定義View的尺寸
方式:
1)凿菩、重新onMeasure() ,并計算出View的尺寸帜讲;
UNSPECIFIED :不限制
AT_MOST :限制上限
EXACTLY :限制固定值
2)衅谷、使用 resolveSize() 來讓子 View 的計算結(jié)果符合父View的限制

3、重寫onMeasure()和onLayout()來全新計算自定義ViewGroup的內(nèi)部布局
方式:
1)似将、重寫 onMeasure() 來計算內(nèi)部布局
調(diào)用每個子 View 的 measure() 來計算子 View 的尺寸获黔;
計算子 View 的位置并保存子 View 的位置和尺寸;
計算自己的尺寸并用 setMeasuredDimension() 保存在验;
2)玷氏、重寫 onLayout() 來擺放子View
在 onLayout() 里調(diào)用每個子 View 的 layout() ,讓它們保存自己的位置和尺 寸腋舌。

觸摸

  • 重寫onTouchEvent() 盏触,在里面寫上你的觸摸反饋算法,并返回 true(關(guān)鍵是
    ACTION_DOWN 事件時返回 true )块饺。
  • 如果是會發(fā)生觸摸沖突的 ViewGroup 赞辩,還需要重寫onInterceptTouchEvent() ,在事件流開始時返回 false 刨沦,并在確認(rèn)接管事件流時返回一次true诗宣,以實(shí)現(xiàn)對事件的攔截。
  • 當(dāng)子 View 臨時需要組織父 View 攔截事件流時想诅,可以調(diào)用父View的requestDisallowInterceptTouchEvent() 召庞,通知父View在當(dāng)前事件流中不 再嘗試通過 onInterceptTouchEvent() 來攔截岛心。

總結(jié)

對View得實(shí)現(xiàn)原理有一個清晰得認(rèn)識,在工作中篮灼,若是遇到相關(guān)bug忘古,或需要實(shí)現(xiàn)自定義View,也知道從何下手诅诱。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末髓堪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子娘荡,更是在濱河造成了極大的恐慌干旁,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炮沐,死亡現(xiàn)場離奇詭異争群,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)大年,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門换薄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翔试,你說我怎么就攤上這事轻要。” “怎么了垦缅?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵冲泥,是天一觀的道長。 經(jīng)常有香客問我失都,道長柏蘑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任粹庞,我火速辦了婚禮咳焚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘庞溜。我一直安慰自己革半,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布流码。 她就那樣靜靜地躺著又官,像睡著了一般。 火紅的嫁衣襯著肌膚如雪漫试。 梳的紋絲不亂的頭發(fā)上六敬,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音驾荣,去河邊找鬼外构。 笑死普泡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的审编。 我是一名探鬼主播撼班,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼垒酬!你這毒婦竟也來了砰嘁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勘究,失蹤者是張志新(化名)和其女友劉穎矮湘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體口糕,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡板祝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了走净。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡孤里,死狀恐怖伏伯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捌袜,我是刑警寧澤说搅,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站虏等,受9級特大地震影響弄唧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霍衫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一候引、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敦跌,春花似錦澄干、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惧笛,卻和暖如春从媚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背患整。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工拜效, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喷众,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓拂檩,卻偏偏與公主長得像侮腹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子稻励,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355