Custom View (v), onlayout

Source: Internet
Author: User

Transfer from http://blog.csdn.net/a396901990/article/details/38129669Brief introduction:

When customizing the view, it's really simple, just know the 3 steps:
1. Measurement--onmeasure (): Determines the size of the view
2. Layout--onlayout (): Determines the location of the view in ViewGroup
3. Draw--ondraw (): How to draw this view.

and the 3rd step of the OnDraw system has been packaged very well, basically do not worry about us, only need to focus on 1, 22 steps in the good.
The first step of the measurement, can refer to my previous article: (Android Custom View--onmeasure process, Measurespec detailed)
And this article is about the second step: "Layout"

Knowledge Point review:
Before talking about how to use the OnLayout method, let's recall the knowledge point briefly:

View structure:
View views can be a single one, such as TextView, or a view group (ViewGroup) such as LinearLayout.
For multi-view views His structure is a tree-shaped structure, the topmost is viewgroup,viewgroup may have more than one viewgroup or view.


The concept of this tree is important because whether we are measuring size or adjusting the layout, we start at the top of the tree, one branch at a time ( tree-shaped recursion ).

Measure Brief review:

The function of measure is to calculate the actual size for the entire view tree, and by the introduction of the view tree just now, to calculate the size of the entire view tree, it is necessary to recursively calculate the size of each sub-view (layout is the same).
For each view, the actual high (mmeasuredheight) and wide (mmeasurewidth) incoming onmeasure are computed after a series of measurement flows through the method. The Setmeasureddimension () method completes the measurement of a single view, and if the measured view is viewgroup, each of these sub-views can be computed recursively by the Measurechild method. The actual width and height of each view is determined by the parent view and its own view .

Layout (source analysis):

The function of layout is to calculate the actual location for the entire view tree, and by the introduction of the view tree just now, to calculate the location of the entire view tree, you need to recursively calculate the location of each sub-view (measure).

It is very simple to determine this position and only need to Mleft,mtop,mright,mbottom four values (Note: These 4 values are the values of the child view relative to the parent view, which is described in more detail below).

How do you set these 4 values in your code?
First, whether it's a system-provided linearlayout or our custom view view, he needs to inherit from the ViewGroup class, and all that's required is to rewrite the OnLayout method (because onlayout is defined as an abstract method in ViewGroup).

Viewgroup-onlayout:

@Override protected abstract void onlayout(boolean changed, int L, int t, int r, int b) ;

OnLayout is defined as an abstract method, so you must override the method when inheriting ViewGroup (Onmeasure is not required). This method is also overridden by the override method, which overrides the OnLayout method in its parent view.

View-onlayout:

    /** * Called by layout when the view and its sub-view are assigned a size and position.     * @param changed the size and position of the current view has changed * @param left position (relative to Parent view) * @param top position (relative to Parent view) * @param Right position (relative to Parent view) * @param Bottom Bottom position (relative to Parent view) */     protected void onlayout(boolean changed, int left, int Top, int right, int bottom) {}

The annotation says: When the view and its sub-view are assigned a size and position, it is called by layout. So let's go and see what's been done in layout. (The annotations are not translated completely in English and are omitted)

View-layout:

    /** * Assigns a size and position to the view and all its child view * This is the second stage of the layout (the first stage is measurement). At this stage, each parent view needs to call layout to determine the location for all of his child views * Derived subclasses should not override the layout method, should override the OnLayout method, and the layout of each view should be called in the OnLayout method */    Public   void layout(int l, int t, int r, int b)  {//Record the current view with the old value (the new L,t,r,b value passed in the parameter) to the top right        intOLDL = Mleft;intOldt = Mtop;intOldb = Mbottom;intOldr = Mright;the function of the//Setframe method is to assign the new incoming LTRB property to the view and then determine if the current view size and position have changed and return        BooleanChanged = Setframe (L, T, R, b);if(Changed | | (Mprivateflags & pflag_layout_required) = = pflag_layout_required) {//Call the OnLayout callback method, implemented by the subclass of the ViewGroup that overrides the OnLayout method (detailed later)OnLayout (changed, L, T, R, b); Mprivateflags &= ~pflag_layout_required;//Call all the methods that override the Onlayoutchange listener to notify the view that the size and position have changedListenerinfo li = mlistenerinfo;if(Li! =NULL&& Li.monlayoutchangelisteners! =NULL) {arraylist<onlayoutchangelistener> listenerscopy = (arraylist<onlayoutch angelistener>) Li.mOnLayoutChangeListeners.clone ();intNumlisteners = Listenerscopy.size (); for(inti =0; i < numlisteners; ++i) {listenerscopy.get (i). Onlayoutchange ( This, L, T, R, B, Oldl, Oldt, Oldr, OLDB);    }}} mprivateflags &= ~pflag_force_layout; }

In this code we just need to know: if the size and position of the view changes, the OnLayout method we analyzed earlier is called.
The final implementation of the OnLayout method relies entirely on the onlayout that we rewrite in the custom ViewGroup class to implement.

Calculate View Location:

In the overridden OnLayout method, the only purpose is to:
Sets their specific position in the parent view for the current view and all its child views (determining this position depends on the four values of Mleft,mtop,mright,mbottom)
As described earlier, the Mleft,mtop,mright,mbottom four values represent the location of the child view relative to the parent view. I'll see what I've done with the pictures below.



, the yellow area is our parent view, and the middle dark area is our sub view.
So for this view, I'll list how it calculates and related functions relative to the individual values of the parent view:

Mleft,mtop,mright,mbottom:
View.getleft ()--mleft: The distance from the left edge of the child view to the left edge of the parent view
Public final int GetLeft () {
return mleft;
}
View.gettop ()--mtop: The distance from the upper boundary of the child view to the top edge of the parent view
View.getright ()--mright: The distance from the right edge of the child view to the left edge of the parent view
View.getbottom ()--mbottom: The distance from the bottom margin of the child view to the top edge of the parent view

View Width Height:
The view width view.getwidth (); The right edge of the child view-the left edge of the child view.
Public final int getwidth () {
return mright-mleft;
}
View height view.getheight (); bottom boundary of child view-upper border of child view.
Public final int getheight () {
return mbottom-mtop;
}

Measuring the width of the height:
View.getmeasuredwidth (); Mmeasuredwidth returned during measure
Public final int Getmeasuredwidth () {
return Mmeasuredwidth & Measured_size_mask;
}
View.getmeasuredheight (); Mmeasuredheight returned during measure
Public final int Getmeasuredheight () {
return Mmeasuredheight & Measured_size_mask;
}

Finally introduce the difference between Getwidth/height and getmeasuredwidth/height:
These functions, such as getwidth, and GetLeft, are the positions of the view relative to its parent view. And Getmeasuredwidth,getmeasuredheight is the actual value of the view after the measurement (a bit around, excerpt from the blog JAFSLDKFJ written in the explanation).
In fact, when the screen can wrap the content, their values are equal, only when the view beyond the screen to see their differences:
Getmeasuredheight () is the size of the actual view, regardless of the screen, and the size of the getheight is now the size of the screen.
When the screen is exceeded, getmeasuredheight () equals getheight () plus the size not shown outside the screen

When calculating the position of a child view in the parent view, it is primarily the application of the above functions. Here's a look at how to rewrite onlayout.

OnLayout:

The idea of overriding OnLayout is the same as overriding Onmeasure:
If you only need to measure a single view, you can measure it yourself alone. If the view you want to measure has a sub-view below it, you need to measure all of its child view.

Take the above view as an example, he is the most outside of a yellow parent view, the middle of a center of the dark sub-view.
My idea is as follows:
If you want to draw a view, you need to calculate its l,t,r,b value. and passed to OnLayout (L, T, R, b);
Mright = View.getwidth + mleft;
Mbottom = View.getheight + mtop;
So the last can be passed in the following form: OnLayout (L, T, L+width, t+height);

The rest of the task just need to know its mleft value, Mtop value, plus long, wide value on the line.
The length and width values are simple and can be used with getwidth/height and getmeasuredwidth/height.
Since this view needs to be centered, the remaining question is how to calculate the view's Mleft value and Mtop value. My idea is as follows:
R (Mright of Parent view) = Mleft + width + mleft (as left and right spacing)
B (Mbottom of parent view) = mtop + height + mtop (as up and down spacing)

My code is as follows:

    @Override     protected void onlayout(boolean changed, int l, int T, int R, int b) {//Loop all child view         for(intI=0; I<getchildcount (); i++) {View child = Getchildat (i);//Remove current child view length width            intwidth = Child.getmeasuredwidth ();intHeight = child.getmeasuredheight ();//Calculates the current Mleft and Mtop values (R,b is the mright and Mbottom values of the parent view passed in)            intMleft = (r-width)/2;intMtop = (b-height)/2;//Call layout and pass the computed parameters as child view layoutChild.layout (Mleft, mtop, Mleft + width, mtop + height); }    }

The layout file is as follows:

< Com.gxy.text.CostomViewGroup  xmlns:android  =< Span class= "Hljs-value" style= "color: #48b685;" > "http://schemas.android.com/apk/res/android"   Android:layout_width  = "wrap_content"  android:layout_height  = "Wrap_content"  android:background  =;     <button  android:text  = "Childview"  android:layout_width  = "200dip"  android:layout_height  = "200dip"  android:background  = "#333444"  android:id  = "@+id/textview2" /> </com.gxy.text.CostomViewGroup>


Summarize:

Onmeasure and onlayout The rough summary, in the custom view when the most critical is onlayout, because no matter how you measure the size of the view, the final decision is always in the hands of OnLayout, The onlayout determines the size and position of the specific view. Of course onmeasure is also very important, some situations control the width of high uncertainty or need to customize, this time we need to manually measure it. In complex custom view, many calculations also need to be done in onmeasure, and the values are recorded and reused in the onlayout (personal understanding, welcome correction).

Write Onmeasure and OnLayout when just want to summarize, tidy up ideas. Because there are too many written on the internet, here is recommended qinjuning this great God's blog, about the content of the view he summed up quite comprehensive and deep.

Custom View (v), onlayout

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.