Respect originality: Http://blog.csdn.net/yuanzeyao/article/details/40264433
I haven't written any articles for a long time. Now I can summarize some knowledge over the weekend to help me better understand it. Today I will learn how to implement custom viewgroup.
Commonly used layout, framelayout, and relativelayout layout in Android... These la s are inherited from viewgroup. With these la S, we can almost develop all interfaces in Android. However, for some common and complex la s, we will spend a lot of time on repetitive work. Can we imitate these basic la S and implement our own la s based on our own needs, what can I do if I need it in the future? Of course.
Layout similar to playing cards
In the landlords game, we often encounter a layout similar to this. I will call this layout cascade layout. This layout can be made using relativelayout and margin, however, it is not very convenient. Today we will explain this requirement in the context of custom viewgroup.
Before learning about custom la S, you 'd better first understand how Android la s seem to have been painted. I suggest you read about them: they are all articles on the official website.
1. http://developer.android.com/guide/topics/ui/how-android-draws.html
2. http://developer.android.com/reference/android/view/ViewGroup.html
3. http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html
Through the above articles, we need to understand the knowledge:
1. The layout is composed of two processes: the measurement process and the layout process. The measurement process is completed using the measure (INT, INT) method. After the traversal is completed, the size of all views is determined, and the layout method is used to complete the layout process. The size of the view determines where the view is placed, however, the measure and layout methods in the source code are of the final type, so we cannot rewrite them. The final method is defined to avoid developers' damage to the layout painting process, however, the measurement and layout details can be implemented by rewriting onmeasure and onlayout.
2. viewgroup
As I mentioned earlier, all la s in Android are inherited from viewgroup, and viewgroup is a view container. We can place the view of the task in it, we can define it through onmeasure and onlayout. onmeasure is called in measure, while onlayout is called in layout.
3. viewgroup. layoutparams
This class is mainly used by view to tell its parent container how to display it, such as width, height, and center. The two most important parameters in viewgroup. layoutparams are width and height. If you want to use the margin attribute, you must use the viewgroup. marginlayoutparams class, which inherits from viewgroup. layoutparams. Added support for the margin attribute. If you want to add more attributes, you can define a layoutparams class to add the desired attributes. In fact, the layout such as linearlayout is inherited from the viewgroup. marginlayoutparams and add the required attributes.
Implement your own layout cascadelayout. Java
/*** Custom Layout for playing card effect * COM. myviewgroup. cascadelayout * @ author yuanzeyao <br/> * Create at October 19, 2014 4:15:42 */public class cascadelayout extends viewgroup {/*** horizontal offset distance */private int horizontal_space; /*** vertical offset distance */private int vertical_space; Public cascadelayout (context) {super (context);} public cascadelayout (context, attributeset attrs, int defstyle) {super (context, attrs, defstyle); initattribute (context, attrs);} public cascadelayout (context, attributeset attrs) {super (context, attrs); initattribute (context, attrs);}/*** assign values to horizontal_space and vertical_space Based on the attributes in the XML file * @ Param context * @ Param attrs */private void initattribute (context, attributeset attrs) {typedarray A = context. obtainstyledattributes (attrs, R. styleable. cascadelayout); horizontal_space =. getdimensionpixelsize (R. styleable. cascadelayout_horizontal_space, this. getresources (). getdimensionpixelsize (R. dimen. cascade_horizontal_spacing); vertical_space =. getdimensionpixelsize (R. styleable. cascadelayout_vertical_space, this. getresources (). getdimensionpixelsize (R. dimen. cascade_vertical_spacing);. recycle ();}/*** onmeasure is called in measure. The parameters are the width and height of cascadelayout */@ override protected void onmeasure (INT widthmeasurespec, int heightmeasurespec) {// use measurechildren to measure all the children. You can also use the for loop and get out of it. Get a measurechild function to measure measurechildren (widthmeasurespec, heightmeasurespec ); // assign the width and height to the measurewidth and measureheight variables setmeasureddimension (widthmeasurespec, heightmeasurespec) of cascadelayout );} /*** add how to arrange the logic of each view in this function */@ override protected void onlayout (Boolean changed, int L, int T, int R, int B) {for (INT I = 0; I <getchildcount (); I ++) {// traverse the child node view child = getchildat (I) in sequence ); // marginlayoutparams MLP = (marginlayoutparams) child. getlayoutparams (); layoutparams Lp = child. getlayoutparams (); // calculate the distance between the left and top: int left = horizontal_space * I; int Top = vertical_space * I; child. layout (left, top, left + child. getmeasuredwidth (), top + child. getmeasuredheight () ;}}/*** rewrite the layoutparams Generation Method */@ override protected layoutparams generatelayoutparams (layoutparams p) {// return Super. generatelayoutparams (p); // return New viewgroup. marginlayoutparams (P. width, P. height); return New viewgroup. layoutparams (P. width, P. height) ;}@ override public layoutparams generatelayoutparams (attributeset attrs) {// return Super. generatelayoutparams (attrs); // return New viewgroup. marginlayoutparams (this. getcontext (), attrs); return New viewgroup. layoutparams (this. getcontext (), attrs );}}
In cascadelayout, we define two attributes, horizontal_space and vertical_space, which are used to record the vertical distance and horizontal distance before each sub-view in the layout. They are all initialized in the constructor. Since attributes are added, the attrs. xml file is defined in RES/values.
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="CascadeLayout"> <attr name="horizontal_space" format="dimension"></attr> <attr name="vertical_space" format="dimension"></attr> </declare-styleable></resources>
Use cascadelayout in the layout File
<com.myviewgroup.CascadeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cascade ="http://schemas.android.com/apk/res/com.myviewgroup" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" cascade:horizontal_space="40dip" cascade:vertical_space="40dip" > <View android:layout_width="200dip" android:layout_height="200dip" android:background="@color/view1" /> <View android:layout_width="200dip" android:layout_height="200dip" android:background="@color/view2" /> <View android:layout_width="200dip" android:layout_height="200dip" android:background="@color/view3" /></com.myviewgroup.CascadeLayout>
The running effect is as follows:
Custom layoutparams in cascadelayout, we use viewgroup. layoutparams class, but this class only has the width and height attributes. If we want to add other attributes, we need to define our own layoutparams class.
Next we will customize our own layoutparams class. This class inherits viewgroup. marginlayoutparams, so my custom layoutprams has the margin attribute.
The following layoutparams class is defined in cascadelayout:
Public static class layoutparams extends viewgroup. marginlayoutparams {/*** defines the vertical offset distance, which can overwrite the vertical_space attribute */private int layout_vertical_spacing in cascadelayout; Public layoutparams (context c, attributeset attrs) {super (C, attrs); typedarray A = C. obtainstyledattributes (attrs, R. styleable. cascadelayout_layoutparams); try {layout_vertical_spacing =. getdimensionpixelsize (R. styleable. cascadelayout_layoutparams_layout_vertical_spacing,-1);} finally {. recycle () ;}} public layoutparams (INT width, int height) {super (width, height );}}
This layoutparams supports the layout_vertical_spaceing attribute.
Well, let's write it here first. If you have any questions, please leave a message...
Define your own viewgroup