It provides common implementations of several viewgroup in Android, including LinearLayout, Relativeayout, Framelayout, and so on. These viewgroup can meet our general development needs, but for the interface requirements complex, these several layouts appear to be stretched. So the custom viewgroup is ubiquitous in the applications we've been exposed to.
The first step in implementing a custom ViewGroup is to learn to customize the attributes, which will give us more flexibility in configuring the layout files. A custom attribute is a attrs.xml file declared under the value directory.
<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
<declare-styleable name= " Cascadeviewgroup ">
<attr name=" verticalspacing "format=" Dimension "/> <attr-name=
" Horizontalspacing "format=" Dimension "/>
</declare-styleable>
<declare-styleable name=" Cascadeviewgroup_layoutparams ">
<attr name=" Layout_paddingleft "format=" Dimension "/>
<attr Name= "Layout_paddintop" format= "Dimension"/>
</declare-styleable>
</resources>
Here we declare two custom attribute sets, and the properties in Cascadeviewgroup are set for our custom Cascadeviewgroup component, that is, you can <CascadeViewGroup> in the layout file The properties that can be used in the label. Another cascadeviewgroup_layoutparams is the property that is set for the child view in Cascadeviewgroup.
Before writing the code, we also set a default width and height for cascadelayout to use. These two properties are defined in Dimens.xml.
<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
<dimen name= "default_horizontal_spacing ">10dp</dimen>
<dimen name=" default_vertical_spacing ">10dp</dimen>
</resources >
The following is the beginning of writing a custom component cascadelayout.
Package com.app.CustomViewMotion;
Import Android.content.Context;
Import Android.content.res.TypedArray;
Import Android.util.AttributeSet;
Import Android.view.View;
Import Android.view.ViewGroup;
/** * Created by Charles on 2015/8/13.
*/public class Cascadeviewgroup extends ViewGroup {//Custom layout set width and height private int mhoriztonalspacing;
private int mverticalspacing;
Public Cascadeviewgroup {This (context, NULL);
Public Cascadeviewgroup (context, AttributeSet attrs) {This (context, attrs, 0);
Public Cascadeviewgroup (context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle);
TypedArray a = Context.obtainstyledattributes (Attrs, R.styleable.cascadeviewgroup); try {//Get set width mhoriztonalspacing = a.getdimensionpixelsize (r.styleable.cascadeviewgroup_horizontalspacing, th
Is.getresources (). Getdimensionpixelsize (r.dimen.default_horizontal_spacing)); Gets the height of the setting mverticalspacing = A.getdimensionpixelsiZe (r.styleable.cascadeviewgroup_verticalspacing, this.getresources (). Getdimensionpixelsize (R.dimen.default_
vertical_spacing));
catch (Exception e) {e.printstacktrace ();
finally {a.recycle (); } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {Final int count = This.getchil
DCount ();
int width = This.getpaddingleft ();
int height = this.getpaddingtop ();
for (int i = 0; i < count; i++) {final View CurrentView = This.getchildat (i);
This.measurechild (CurrentView, Widthmeasurespec, Heightmeasurespec);
Cascadeviewgroup.layoutparams LP = (cascadeviewgroup.layoutparams) currentview.getlayoutparams ();
if (lp.msettingpaddingleft!= 0) {width +=lp.msettingpaddingleft;
} if (lp.msettingpaddingtop!= 0) {height +=lp.msettingpaddingtop;
} lp.x = width;
lp.y = height;
width + + mhoriztonalspacing;
Height + = mverticalspacing; } Width +=getchildat (This.getchildcount ()-1). getmeasuredwidth() + this.getpaddingright ();
Height + = Getchildat (This.getchildcount ()-1). Getmeasuredheight () + This.getpaddingbottom ();
This.setmeasureddimension (resolvesize (width, widthmeasurespec), resolvesize (height, heightmeasurespec)); @Override protected void OnLayout (Boolean b, int l, int i1, int i2, int i3) {Final int count = This.getchildcount (
);
for (int i = 0; i < count; i++) {final View CurrentView = This.getchildat (i);
Cascadeviewgroup.layoutparams LP = (cascadeviewgroup.layoutparams) currentview.getlayoutparams ();
Currentview.layout (lp.x, lp.y, lp.x + currentview.getmeasuredwidth (), Lp.y + currentview.getmeasuredheight ());
} public static class Layoutparams extends Viewgroup.layoutparams {int x;
int y;
int msettingpaddingleft;
int msettingpaddingtop;
Public Layoutparams (Context C, AttributeSet Attrs) {super (C, attrs);
TypedArray a = C.obtainstyledattributes (Attrs, r.styleable.cascadeviewgroup_layoutparams); MsettingpaddiNgleft = a.getdimensionpixelsize (r.styleable.cascadeviewgroup_layoutparams_layout_paddingleft, 0);
Msettingpaddingtop = a.getdimensionpixelsize (r.styleable.cascadeviewgroup_layoutparams_layout_paddintop, 0);
A.recycle ();
public layoutparams (int width, int height) {Super (width, height);
Public Layoutparams (Viewgroup.layoutparams source) {super (source); }} @Override protected Viewgroup.layoutparams generatedefaultlayoutparams () {return new Layoutparams (Layoutparams.
Wrap_content, layoutparams.wrap_content); } @Override protected Viewgroup.layoutparams generatelayoutparams (Viewgroup.layoutparams p) {return new layoutparams
(p); @Override public viewgroup.layoutparams generatelayoutparams (AttributeSet attrs) {return new Layoutparams (this.get
Context (), attrs);
}
}
The code has a slightly longer advantage, but the structure is still clear.
1 The value of the configuration property in the constructor method or in the XML file. get the properties we set in the layout layout using the methods in Typedarray and save them in the member variable.
2 Constructs a custom internal class layoutparams. constructing this inner class makes it easy for us to save their property values when we measure our child view so that we can lay out the layout phase.
3) Generatelayoutparams (), Generatedefaultparams () and other methods. return our custom Layoutparams in these methods. As for why you should rewrite these methods, it is clear that you can view the AddView () method of the ViewGroup class.
4) Measure stage. in the measure phase, we measure our size, we also measure the size of the child view, and we keep the information of the child view in the Layoutparams.
5) Layout stage. according to the information of each child view, layout their position.
Finally, add the layout file.
<?xml version= "1.0" encoding= "Utf-8"?> <!--Add custom attributes to viewgroup--> <!--the suffix of the newly added namespace must remain consistent with the package name declared in. XML--
> <com.app.customviewmotion.cascadeviewgroup xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:ts= "Http://schemas.android.com/apk/res/com.app.CustomViewMotion" android:layout_width= "Match_parent" android:layout_height= "Match_parent" ts:horizontalspacing= "15DP" ts:verticalspacing= "15DP" > <textview Android:layout_width= "100DP" android:layout_height= "100DP" android:gravity= "center" android:text= "Text1" a ndroid:background= "#668B8B"/> <textview android:layout_width= "100DP" android:layout_height= "100DP" Android : gravity= "center" android:text= "Text2" android:background= "#FFDAB9"/> <textview android:layout_width= "100d P "android:layout_height=" 100DP "android:gravity=" center "android:text=" Text3 "android:background=" #43CD80 "/> <!--This child view adds a custom view property--> <textview andRoid:layout_width= "100DP" android:layout_height= "100DP" android:gravity= "center" android:text= "Text4" ts:l ayout_paddingleft= "100DP" ts:layout_paddintop= "100DP" android:background= "#00CED1"/> </com.app.customviewmo tion.
Cascadeviewgroup>
The effect of the implementation is as follows:
The above is the whole content, I hope to give you a reference, but also hope that we support the cloud habitat community.