How to define your own ViewGroup

Source: Internet
Author: User

In development, there are some requirements that can sometimes be met. The layout and control system not only provides the use to meet our development, so this time on the line, usually your own custom layout (ViewGroup) and control (View) that. I am here, we will use a simple example, when they explain their definition viewgroup basic flow, I hope to help friends do not understand the process.

First, we want to implement a layout diagram such as the following:

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvd3v6aglwzw5nmtk5mq==/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma== /dissolve/70/gravity/southeast ">

This looks very simple, with the system provided by the layout can achieve this effect, there is no need to define their own viewgroup to achieve it!!

。 Just, let's say you try to do it yourself with a system layout. You'll find some problems. Question 1: To achieve the effect of each view stagger, you must set different fixed margin parameters for them. This may be the problem is: different phones. The display effect may be different. That's the problem with the adaptation! Question 2: Assuming that you want to add more views, you also need to calculate the margin parameters for each view. Very pit dad, again, here is mainly to explain their own definition of the basic flow of viewgroup, so, the simpler the sample, the better understand!

First, we are able to define our own ViewGroup desired properties, here I have defined two properties for ViewGroup, horizontal_spacing (horizontal spacing of the view in the layout) and Vertical_ Spacing (The vertical spacing of the view in the layout); In addition, a layout parameter attribute is defined, layout_vertical_spacing. This property can be used for view in our own definition of viewgroup.

Content of Attrs.xml:

<?xml version= "1.0" encoding= "Utf-8"?

><resources> <declare-styleable name= "Mycustomlayout" > <attr name= "Horizontal_spacing" format= "Dimension"/> <attr name= "vertical_spacing" format= "Dimension"/> </declare-styleable > <declare-styleable name= "Mycustomlayout_layoutparams" > <attr name= "layout_vertical_spacing "Format=" Dimension "/> </declare-styleable></resources>

The default value for two properties is defined in Dimens.xml.

Content of Dimens.xml:

<?

XML version= "1.0" encoding= "Utf-8"?><resources> <dimen name= "horizontal_spacing" >10dp</ dimen> <dimen name= "vertical_spacing" >10dp</dimen></resources>

Then, the most basic steps come. First look at our own definition of viewgroup.

Here is the source code:

Package Com.customlayout.mycustomlayout;import Android.content.context;import Android.content.res.TypedArray; Import Android.util.attributeset;import Android.view.view;import Android.view.viewgroup;public class MyCustomLayout    Extends ViewGroup {private int mhorizontalspacing;    private int mverticalspacing;        Public Mycustomlayout (context context, AttributeSet Attrs) {Super (context, attrs);        TypedArray ta = context.obtainstyledattributes (attrs, r.styleable.mycustomlayout); mhorizontalspacing = Ta.getdimensionpixelsize (r.styleable.mycustomlayout_horizontal_spacing, GetResources ()        . Getdimensionpixelsize (r.dimen.horizontal_spacing)); mverticalspacing = Ta.getdimensionpixelsize (r.styleable.mycustomlayout_vertical_spacing, GetResources (). Get        Dimensionpixelsize (r.dimen.vertical_spacing));    Ta.recycle (); } @Override protected Boolean checklayoutparams (Viewgroup.layoutparams p) {//TODO auto-generated Method StUB return P! = NULL; } @Override protected Layoutparams generatelayoutparams (Viewgroup.layoutparams p) {//TODO auto-generated Me    Thod stub return (layoutparams) p; } @Override Public Layoutparams generatelayoutparams (AttributeSet attrs) {return new Layoutparams (getcontext    (), attrs); } @Override protected Layoutparams generatedefaultlayoutparams () {return new Layoutparams (LAYOUTPARAMS.WRAP_    CONTENT, layoutparams.wrap_content);        } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {int width = 0;        int height = getpaddingtop ();        int verticalspacing;        Final int count = Getchildcount ();            for (int i = 0; i < count; i++) {View child = Getchildat (i);            Measurechild (Child, Widthmeasurespec, Heightmeasurespec);            verticalspacing = mverticalspacing;            Layoutparams LP = (layoutparams) child.getlayoutparams (); if (lP.verticalspacing > 0) {verticalspacing + = lp.verticalspacing;            } width = getpaddingleft () + mhorizontalspacing * i;            lp.x = width;            lp.y = height;            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) {Final int count = Getchild        Count ();            for (int i = 0; i < count; i++) {View child = Getchildat (i);            Layoutparams LP = (layoutparams) child.getlayoutparams ();        Child.layout (lp.x, lp.y, lp.x + child.getmeasuredwidth (), Lp.y + child.getmeasuredheight ()); }} public static class Layoutparams extends Viewgroup.layoutparams {public int x;        public int y;        public int verticalspacing;            Public Layoutparams (Context C, AttributeSet attrs) {super (C, attrs);            TypedArray ta = c.obtainstyledattributes (attrs, r.styleable.mycustomlayout_layoutparams);            verticalspacing = Ta.getdimensionpixelsize (r.styleable.mycustomlayout_layoutparams_layout_vertical_spacing,-1);        Ta.recycle ();        } public Layoutparams (int w, int h) {super (W, h); }    }}
First of all, we start with the construction method of Mycustomlayout.java.

Public Mycustomlayout (context context, AttributeSet Attrs) {        Super (context, attrs);        TypedArray ta = context.obtainstyledattributes (attrs, r.styleable.mycustomlayout);        mhorizontalspacing = Ta.getdimensionpixelsize (r.styleable.mycustomlayout_horizontal_spacing,                getResources (). Getdimensionpixelsize (r.dimen.horizontal_spacing));        mverticalspacing = Ta.getdimensionpixelsize (r.styleable.mycustomlayout_vertical_spacing,                getResources (). Getdimensionpixelsize (r.dimen.vertical_spacing));        Ta.recycle ();    }
This construction method has two parameters, in which Attrs is a collection of properties for our layout, with this number of parameters. We were able to get the related properties set in the layout file XML.

Next, talk about the Onmeasure method. Name implies. This method is a measurement method. It works by traversing each view in the layout. Measure each view (call the Measurechild method), and then set the Layoutparams for the view. Sets the location of the view, which is the X on the screen. The y-coordinate. For use in OnLayout methods. The layoutparams here is what we rewrite, where int x and int y hold the coordinates of the view in the layout. Note: When overriding the Layoutparams class. Checklayoutparams (Viewgroup.layoutparams p), Generatelayoutparams (Viewgroup.layoutparams p), ViewGroup in the Generatelayoutparams (AttributeSet attrs), Generatedefaultlayoutparams () is overridden, otherwise an exception will occur ...

Next. The OnLayout method is to deploy all the view locations in the layout. As you can see from the method body, it uses a traversal to deploy the layout method on each view in the layouts.


Well, here's a little summary: define the ViewGroup process yourself. The most important is to rewrite the two methods of Onmeasure and OnLayout. Onmeasure by traversing the view in the layout. Measured size for each view, calculation of layout parameters, and so on. OnLayout is the placement of each view by traversing the view in the layout.

Use our own defined ViewGroup in Activity_main.xml:

<com.customlayout.mycustomlayout.mycustomlayout xmlns:android= "Http://schemas.android.com/apk/res/android" xmlns:customlayout= "Http://schemas.android.com/apk/res-auto" android:id= "@+id/layout" android:layout_width= "fill _parent "android:layout_height=" fill_parent "android:background=" @android: Color/white "customlayout:horizontal_sp acing= "65DP" customlayout:vertical_spacing= "85DP" > <view android:layout_width= "100DP" Android:la yout_height= "150DP" android:background= "#00ff00"/> <view android:layout_width= "100DP" Andro        id:layout_height= "150DP" android:background= "#0000ff"/> <view android:layout_width= "100DP"        android:layout_height= "150DP" android:background= "#ff0000"/> <view android:layout_width= "100DP" android:layout_height= "150DP" android:background= "#0ff000"/> <view android:layout_width= "100d P "android:layout_height=" 150DP "android:background=" #00f0f0 "/></com.customlayout.mycustomlayout.mycustomlayout> 


Source code for Mainactivity.java:

Package Com.customlayout.mycustomlayout;import Android.app.activity;import Android.graphics.rectf;import Android.os.bundle;import Android.view.animation.alphaanimation;import Android.view.animation.animation;import Android.view.animation.animationset;import Android.view.animation.bounceinterpolator;import Android.view.animation.layoutanimationcontroller;import Android.view.animation.translateanimation;public Class    Mainactivity extends Activity {mycustomlayout layout;    Layoutanimationcontroller Layoutanimationcontroller;        @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (R.layout.activity_main);        Layout = (mycustomlayout) Findviewbyid (r.id.layout);        Animationset set = new Animationset (true);        Alphaanimation a = new Alphaanimation (0f, 1f);        A.setduration (500); Translateanimation t = new Translateanimation (animation.relative_to_self, -1f, Animation.relativE_to_self, 0f, Animation.relative_to_self, 0f, Animation.relative_to_self, 0f);        T.setduration (500);        Set.addanimation (t);        Set.addanimation (a);        Layoutanimationcontroller = new Layoutanimationcontroller (set);    Layout.setlayoutanimation (Layoutanimationcontroller); }}

At last. Talk about the layout animation. In the ViewGroup class, there is a property called Layoutanimation, which is known as the layout animation. Just to assign an animation to this property, each of the ViewGroup can be animated in the layout. In the OnCreate () method above. I have specified an animation collection and set it to my own defined mycustomlayout.

Execute the program and see it online. Mycustomlayout each view will be in order and my movie has now been designated mycustomlayout in, its effect is very cool!

In conjunction with this simple example, give yourself a simple introduction to the ViewGroup method that defines it; we use other complex layouts, all using the methods I described above that will be implemented. Their calculations will be more complex than many of the above examples, but the rationale remains.

How to define your own ViewGroup

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.