自定義view布局
1.確定每個view的位置和尺寸
2.作用:為繪製和觸控範圍做支援
1.對於繪製:知道自己需要在**繪製。
2.對於觸控反饋:知道使用者的點是在**。
自定義view布局的工作內容
自定義view的工作分為兩個階段:測量階段和布局階段
測量流程:從上到下遞迴呼叫每個view或者viewgroup的measure()方法,測量他們的尺寸並計算他們的位置。
布局階段:從上到下遞迴地呼叫每個view或者viewgroup的layout()方法,把測量得到的他們的尺寸和位置賦值給他們。
view或者viewgroup的布局過程
1.測量階段:measure()方法被父view呼叫,在measure()中做一些準備和優化工作後,呼叫onmeasure()來進行實際的自我測量。onmeasure()做的事情,在view和viewgroup中是不一樣的。
1.view:view在onmeasure()中會計算出自己的尺寸然後儲存;
2.viewgroup:viewgroup在onmeasure()中會呼叫所有子view的measure()讓他們進行自我測量,並根據子view計算出的期望尺寸來計算出他們的實際尺寸(實際上99.99%的父view都會使用子view給出的期望尺寸來作為實際尺寸),然後儲存。
2.布局階段:layout()方法被父view呼叫,在layout()中他會儲存父view傳進來的自己的位置和尺寸,並且呼叫onlayout()來進行實際的內部布局。onlayout()做的事,view和viewgroup也不一樣:
1.view:由於沒有子view,所以view的onlayout()什麼也不需要做。
2.viewgroup:viewgroup在onlayout()中會呼叫自己的所有的子view的layout()方法,把它們的尺寸和位置傳遞給他們,並且讓他們自己完成自己內部的布局。
布局過程自定義的方式
布局過程自定義的方式有三類
1.重寫onmeasure()來修改已有的view的尺寸。
2.重寫onmeasure()來全新定製自定義view的尺寸。
3.重寫onmeasure()和onlayout()來全新定製自定義viewgroup的內部布局。
具體做法
繼承已有的 view,簡單改寫它們的尺⼨寸:重寫 onmeasure():squareimageview
重寫 onmeasure()
⽤用 getmeasuredwidth() 和 getmeasuredsize() 獲取到測量量出的尺⼨寸 3. 計算出最終要的尺⼨寸
⽤用 setmeasureddimension(width, height) 把結果儲存
protected void onmeasure(int widthmeasurespec, int heightmeasurespec)
對⾃自定義 view 完全進⾏行行⾃自定義尺⼨寸計算:重寫 onmeasure():circleview
重寫 onmeasure()
計算出⾃自⼰己的尺⼨寸
⽤用 resolvesize() 或者 resolvesizeandstate() 修正結果
3.1resolvesize() / resolvesizeandstate() 內部實現(⼀一定讀⼀一下**,這個極少需要⾃自 ⼰己寫,但⾯面試時很多時候會考):
3.1.1⾸首先⽤用 measurespec.getmode(measurespec) 和 measurespec.getsize(measurespec) 取出⽗父 對⾃自⼰己的尺⼨寸限制型別和具體限制 尺⼨寸;
3.1.2如果 measure spec 的 mode 是 exactly,表示⽗父 view 對⼦子 view 的尺⼨寸做出 了了精確限制,所以就放棄計算出的 size,直接選⽤用 measure spec 的 size;
3.1.3如果 measure spec 的 mode 是 at_most,表示⽗父 view 對⼦子 view 的尺⼨寸只限 制了了上限,需要看情況:
3.1.4.1如果計算出的 size 不不⼤大於 spec 中限制的 size,表示尺⼨寸沒有超出限制, 所以選⽤用計算出的 size;
3.1.4.2而如果計算出的 size ⼤大於 spec 中限制的 size,表示尺⼨寸超限了了,所以選⽤用 spec 的 size,並且在 resolvesizeandstate() 中會新增標誌 measured_state_too_small(這個標誌可以輔助⽗父 view 做測量量和布 局的計算;
3.1.5如果 measure spec 的 mode 是 unspecified,表示⽗父 view 對⼦子 view 沒有任 何尺⼨寸限制,所以直接選⽤用計算出的 size,忽略略 spec 中的 size。
使⽤用 setmeasureddimension(width, height) 儲存結果
protected void onmeasure(int widthmeasurespec, int heightmeasurespec)
⾃自定義 layout:重寫 onmeasure() 和 onlayout():taglayout
1. 重寫 onmeasure()
1. 遍歷每個⼦子 view,⽤用 measurechildwidthmargins() 測量量⼦子 view
• 需要重寫 generatelayoutparams() 並返回 marginlayoutparams 才能使⽤用 measurechildwithmargins() ⽅方法
• 有些⼦子 view 可能需要重新測量量(⽐比如換⾏行行處)
• 測量量完成後,得出⼦子 view 的實際位置和尺⼨寸,並暫時儲存
protected void onmeasure(int widthmeasurespec, int
heightmeasurespec)
// 計算⾃自⼰己的尺⼨寸,並儲存
int width = ...;
int height = ...; setmeasureddimension(resolvesizeandstate(width,
widthmeasurespec, 0),
resolvesizeandstate(height, heightmeasurespec,
0)); }
• measurechildwidthmargins() 的內部實現(⼀一定讀⼀一下**,這個極少需要⾃自 ⼰己寫,但⾯面試時很多時候會考):
通過 getchildmeasurespec(int spec, int padding, int childdimension) ⽅方 法計算出⼦子 view 的 widthmeasurespec 和 heightmeasurespec,然後調 ⽤用 child.measure() ⽅方法來讓⼦子 view ⾃自我測量量;
// viewgroup.measurechildwithmargins() 原始碼 protected void measurechildwithmargins(view child, int parentwidthmeasurespec, int widthused,
int parentheightmeasurespec, int heightused)
getchildmeasurespec(int spec, int padding, int childdimension) ⽅方法的內部 實現是,結合開發者設定的 layoutparams 中的 width 和 height 與⽗父 view ⾃自 ⼰己的剩餘可⽤用空間,綜合得出⼦子 view 的尺⼨寸限制,並使⽤用 measurespec.makemeasurespec(size, mode) 來求得結果:
自定義布局控制項
本文介紹一種自定義控制項的方法,由控制項布局和控制項 2部分組成。效果為乙個自定義標題欄,由乙個按鈕 乙個文字 乙個按鈕組成,並定義了各子件的事件。一 title布局如下 二 如下。重寫構造器,在其中展開布局,找到子控制項繫結事件 public class titlelayout extends l...
FlowLayout 自定義布局
在本次,我們延續qt 7 的學習,再次對layout的繼承進行學習。參考在此之前,我們對qt編譯中碰到的一些問題進行記錄 問題1 編譯中出現make g 沒有找到 對於ubuntu可以使用apt get install g 但是在採用yum的系統,例如meego,沒有g 的包,yum那裡採用了另外的...
自定義Toast實現自定義Toast布局
平時我們使用toast的時候都是這樣的一種方法 toast toast toast.maketext context,duration 現在我們來自定義下toast的布局,首先看下toast建立時的源 public static toast maketext context context,char...