本文翻譯自《50 android hacks》
按照慣例。先從乙個樣例說起。
非常easy,3張撲克牌疊在一起顯示。
這個布局效果該怎樣實現呢?有的同學該說了,這非常easy啊,用relativelayout或framelayout,然後為每乙個撲克牌設定margin就能實現了。
ok,那就看一下通過這樣的方式是怎樣實現的。
**例如以下:
效果圖
沒錯,通過這樣的方式是能夠實現的。
可是。不認為這樣的方式有點low嗎?!
讓我們用高階一點的方式去實現它,提公升一下自己的逼格!
定製viewgroup之前,我們須要先理解幾個概念。
android繪製檢視的方式
這裡我不會涉及太多的細節,可是須要理解android開發文件中的一段話:
「繪製布局由兩個遍歷過程組成:測量過程和布局過程。
測量過程由measure(int, int)方法完畢,該方法從上到下遍歷檢視樹。
在遞迴遍歷過程中。每乙個檢視都會向下層傳遞尺寸和規格。當measure方法遍歷結束,每乙個檢視都儲存了各自的尺寸資訊。第二個過程由layout(int,int,int,int)方法完畢,該方法也是由上而下遍歷檢視樹。在遍歷過程中,每乙個父檢視通過測量過程的結果定位全部子檢視的位置資訊。
簡而言之,第一步是測量viewgroup的寬度和高度,在onmeasure()方法中完畢,viewgroup遍歷全部子檢視計算出它的大小。第二步是依據第一步獲取的尺寸去布局全部子檢視,在onlayout()中完畢。
建立cascadelayout
最終到了定製viewgroup的階段了。
假設我們已經定製了乙個cascadelayout的容器。我們會這樣使用它。
首先,定義屬性。在values目錄以下建立attrs.xml。**例如以下:
同一時候,為了嚴謹一些,定義一些預設的垂直距離和水平距離,以防在布局中沒有提供這些屬性。
在dimens.xml中加入例如以下**:
10dp
10dp
準備工作已經做好了。接下來看一下cascadelayout的源**,稍微有點長,後面幫助大家分析一下。
public class cascadelayout extends viewgroup finally
} @override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec)
width += child.getmeasuredwidth();
height += verticalspacing;
}width += getpaddingright();
height += getchildat(getchildcount() - 1).getmeasuredheight()
+ getpaddingbottom();
setmeasureddimension(resolvesize(width, widthmeasurespec),
resolvesize(height, heightmeasurespec));
} @override
protected void onlayout(boolean changed, int l, int t, int r, int b)
} @override
protected boolean checklayoutparams(viewgroup.layoutparams p)
@override
protected layoutparams generatedefaultlayoutparams()
@override
public layoutparams generatelayoutparams(attributeset attrs)
@override
protected layoutparams generatelayoutparams(viewgroup.layoutparams p)
public static class layoutparams extends viewgroup.layoutparams
public layoutparams(int w, int h)
}}
首先,分析建構函式。
public cascadelayout(context context, attributeset attrs) finally
}
假設在布局中使用casecadelayout,系統就會呼叫這個建構函式,這個大家都應該知道的吧。這裡不解釋why。有興趣的能夠去看源**,重點看系統是怎樣解析xml布局的。
建構函式非常easy,就是通過布局檔案裡的屬性,獲取水平距離和垂直距離。
然後。分析自己定義layoutparams。
public static class layoutparams extends viewgroup.layoutparams
public layoutparams(int w, int h)
}
除此之外。還須要重寫一些方法。checklayoutparams()、generatedefaultlayoutparams()等,這種方法在不同viewgroup之間往往是同樣的。
接下來。分析onmeasure()方法。
@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec)
width += child.getmeasuredwidth();
height += verticalspacing;
}width += getpaddingright();
height += getchildat(getchildcount() - 1).getmeasuredheight()
+ getpaddingbottom();
// 使用計算所得的寬和高設定整個布局的測量尺寸
setmeasureddimension(resolvesize(width, widthmeasurespec),
resolvesize(height, heightmeasurespec));
}
最後,分析onlayout()方法。
@override
protected void onlayout(boolean changed, int l, int t, int r, int b)
}
邏輯非常easy。用onmeasure()方法計算出的值為引數迴圈呼叫子view的layout()方法。
為子檢視加入自己定義屬性
作為演示樣例。以下將加入子檢視重寫垂直間距的方法。
第一步是向attrs.xml中加入乙個新的屬性。
這裡的屬性名是layout_vertical_spacing,由於該屬性名字首是layout_。同一時候,又不是view固有的屬性。所以該屬性會被加入到layoutparams的屬性表中。在cascadelayout類的建構函式中讀取這個新屬性。
public static class layoutparams extends viewgroup.layoutparams finally
}public layoutparams(int w, int h)
}
那怎麼使用這個屬性呢?so easy!
參考資料
怎樣給filter加入自己定義介面
給乙個filter加入介面,過程例如以下 1 建立乙個宣告介面的標頭檔案 inte ce.h 內容包含指定介面的guid 使用guidgen.exe 以及介面函式的宣告。記得加 initguid.h 的include,不然使用時會出現 無法解析的外部符號 iid 錯誤 2 在cfilter類的標頭檔...
iOS中怎樣加入自己定義的字型
蘋果對於開發,確實在細節方面下了非常大的功夫,只是不管乙個平台下多大的功夫,仍然會有些需求是無法涵蓋的。比方字型吧。我們的應用為了能更加個性化。會須要不同的字型。有時候有些字型是非常特殊的。甚至是購買的。那麼這些字型怎樣加到專案中去呢?在準備好了字型檔檔案後,就能夠加到專案中了,是把ttf檔案增加到...
移動開發 如何自定義ViewGroup
本文翻譯自 50 android hacks 依照慣例,先從乙個例子說起。很簡單,3張撲克牌疊在一起顯示。這個布局效果該如何實現呢?有的同學該說了,這很簡單啊,用relativelayout或framelayout,然後為每乙個撲克牌設定margin就能實現了。ok,那就看一下通過這種方式是如何實現...