Custom Controls for Android Development (2) --- onLayout

Source: Internet
Author: User

Custom Controls for Android Development (2) --- onLayout

 

 

When talking about a beggar watching a programmer write a program, the programmer encounters a problem and cannot solve it, then the Beggar said that the programmer solved the problem based on the result and asked: how do you know? Beggars smiled and said: I did this before. Through this joke, we learned that the host that cannot sing is not a good driver. So the question is, what do we want to learn today?

You will learn through this blog

① Source code analysis of onLayout in custom controls

② Meaning of getLeft, getRight, getWidth, and getHeight

③ An example is used to understand the onLayout process of a custom control.

④ Difference between getMeasureWidth and getWidth

If you have any mistakes, please correct them. If you have any questions, please leave a message. Thank you.

1. Simple Review

In the previous article, we explained the onMeasure method in detail. First, let's review the previous article. If you haven't read it yet, please read it first (custom control for Android development (1) --- onMeasure ), in the previous article, we talked about the onMeasure process. In the onMeasure method, we finally called the setMeasuredDimension method to determine the control size. If we customized a View, we just needed to measure its size, for a ViewGroup, You need to traverse all its sub-views and measure the size of each sub-View. Two parameters are required to measure the sub-View. The values of measureWidth and measureHeight are transmitted from the root layout, that is, the parent View and the sub-View determine the size of the sub-View.

 

2. Source Code Analysis

Today, let's take a look at the second step onLayout of the custom control to determine the position of the control. In the previous article, we mentioned that host will be called in the javasmtraversals method. the measure method. After the host is called. after the measure method, the host is called. layout locates the View, which we will discuss today.

First, let's take a look at the source code of layout.

public final void layout(int l, int t, int r, int b) {        boolean changed = setFrame(l, t, r, b);        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {            if (ViewDebug.TRACE_HIERARCHY) {                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);            }            onLayout(changed, l, t, r, b);            mPrivateFlags &= ~LAYOUT_REQUIRED;        }        mPrivateFlags &= ~FORCE_LAYOUT;    }

The source code for calling the setFrame method is as follows:

Protected boolean setFrame (int left, int top, int right, int bottom) {boolean changed = false; if (mLeft! = Left | mRight! = Right | mTop! = Top | mBottom! = Bottom) {changed = true ;... Omit part of the code... MLeft = left; mTop = top; mRight = right; mBottom = bottom ;... Omit part of the code... } Return changed ;}

 

In the setFrame method, save the left, top, right, and bottom values. That is to say, in the setFrame method of layout, the left, top, right, and bottom values of the Child View relative to the parent View are saved, the four values determine the position of the child View in the parent View. After carefully reading the source code of the layout method, you will find that the onLayout method is called in layout like the measure method. Hurry and check the onLayout logic of the View.

View -- onLayout

 

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {    }

Ah? Nothing. What are you doing? In fact, if you think about it, you will understand it. Because onLayout aims to determine the position of the child View in the parent View, this step must be determined by the parent View, therefore, onLayout is an empty implementation in View. In this case, let's look at the source code of onLayout in ViewGroup.

ViewGroup -- onLayout

@Override    protected abstract void onLayout(boolean changed,            int l, int t, int r, int b);

We can see that it is an abstract method. We all know that the abstract method must be implemented when a class is inherited. This means that we must implement the onLayout method when customizing ViewGroup. In the previous article, we mentioned that onLayout is used to determine the position of the subview. How does it determine the position of the subview? In fact, it uses four parameters, l, t, r, and B, to indicate the distance between the upper left and lower right of the parent View.

MLeft, mTop, mRight, and mBottom

MLeft -- View. getLeft (): the distance between the left boundary of the Child View and the left boundary of the parent View

 

// Obtain the distance from the left boundary of the Child View to the left boundary of the parent View to the public final int getLeft () {return mLeft ;}

 

MTop -- View. getTop (): the distance from the top of the Child View to the top of the parent View

MRight -- View. getRight (): the distance between the right boundary of the Child View and the left boundary of the parent View

MBottom -- View. getBottom (): the distance from the bottom of the Child View to the top of the parent View

Their performance in source code is as follows:

 

/*** Top position of this view relative to its parent. ** @ return The top of this view, in pixels. * /// obtain the distance from the top of the Child View to the top of the parent View public final int getTop () {return mTop ;} // obtain the distance from the bottom of the Child View to the top of the parent View from public final int getBottom () {return mBottom ;} // obtain the distance from the left boundary of the Child View to the left boundary of the parent View to the public final int getLeft () {return mLeft ;} // obtain the distance from the right boundary of the Child View to the left boundary of the parent View to the public final int getRight () {return mRight;} public final int getWidth () {return mRight-mLeft ;} /*** Return the height of your view. ** @ return The height of your view, in pixels. */public final int getHeight () {return mBottom-mTop;}/*** The height of this view as measured in the most recent call to measure (). * This shoshould be used during measurement and layout calculations only. use * {@ link # getHeight ()} to see how tall a view is after layout. ** @ return The measured height of this view. * // obtain The measurement width public final int getMeasuredWidth () {return mMeasuredWidth;}/*** the width of this view as measured in The most recent call to measure (). * This shoshould be used during measurement and layout calculations only. use * {@ link # getWidth ()} to see how wide a view is after layout. ** @ return The measured width of this view. * // obtain the public final int getMeasuredHeight () {return mMeasuredHeight ;}
If you carefully read the source code above, you will see two methods in the above distance: getMeasureWidth, getMeasureHeight, and getWidth and getHeight. What are the differences between them? Many people may not particularly understand this problem. Here we take the getMeasureWidth and getWidth methods as examples to describe them,

 

① The getMeasureWidth () method can obtain its value after the measure () process ends, while the getWidth () method can only obtain the value after the layout () process ends. What is the basis for this? First, let's take a look at the returned value of the getMeasureWidth () method. It's mMeasureWidth. Are you familiar with it? This is the value set through the setMeasureDimension () method in the previous blog, while the returned value of getWidth () is mRight-mLeft, which is in layout () the value set in the setFrame method during the process, that is, it is determined after layout.

② The value in the getMeasureWidth () method is set using the setMeasuredDimension () method, while the value in the getWidth () method is calculated using the coordinate on the right of the view minus the coordinate on the left. The differences between the two methods are incorrect because many of them are on the Internet. I will use a blog to explain the differences between the two values in detail.

 

3. Small Example

Next, let's take a simple example to understand the latyout process. In this example, we define a ViewGroup to arrange its subviews horizontally in the middle of the screen, first, let's talk about its ideas. I think when you are doing something, you must carefully analyze its implementation process and design your own things according to your own ideas, no matter whether it is feasible or not, it is a good experience for yourself to try it, even if it is wrong. After a long time, you will find that your technology has improved a lot.

This is my idea.

Arrange the sub-views of a custom ViewGroup horizontally in the middle of the screen:

① Obtain the screen height

② Obtain the width and height of the sub-View, and calculate the distance from the sub-View to the top of the parent View in layout by the screen height and sub-View height.

③ Because the child View is horizontally arranged, you need to set a variable to indicate the distance from the Child View to the left boundary of the parent View, add the width of the sub-View in each loop to set the distance from the next sub-View to the left of the parent View.

First

This is the result. Let's take a look at the code. Follow the above analysis ideas and follow the code to see it.

 

Package com. example. customviewpractice; import android. app. activity; import android. content. context; import android. util. attributeSet; import android. util. displayMetrics; import android. view. view; import android. view. viewGroup; public class MyViewGroup extends ViewGroup {private Context mContext; private int comment h; public MyViewGroup (Context context, AttributeSet attrs) {super (context, attrs); mContext = context; // obtain the screen height using H = getScreenSize (Activity) mContext) [1] ;}@ Overrideprotected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {super. onMeasure (widthMeasureSpec, widthMeasureSpec); // measure the child ViewmeasureChildren (widthMeasureSpec, heightMeasureSpec);} @ Overrideprotected void onLayout (boolean changed, int l, int t, int r, int B) {// get the number of child views int childCount = getChildCount (); // set the distance from int mLeft = 0 to the left of the parent View to save a variable; // retrieve the child Viewfor (int I = 0; I <childCount; I ++) {View childView = getChildAt (I); // obtain the height of the Child View int childViewHeight = childView. getMeasuredHeight (); // get the width of the Child View int childViewWidth = childView. getMeasuredWidth (); // enables the Sub-View to be displayed in the vertical direction in the middle of the screen. int height = Hangzhou H/2-childViewHeight/2; // call layout to set the position mLeft, mTop, mRight, and mBottom for each subview. childView in the upper left and lower right. layout (mLeft, height, mLeft + childViewWidth, height + childViewHeight); // change the distance from the next child View to the left of the parent View, mLeft + = childViewWidth ;}} /*** get screen size */public static int [] getScreenSize (Activity activity) {DisplayMetrics metrics = new DisplayMetrics (); activity. getWindowManager (). getdefadisplay display (). getMetrics (metrics); return new int [] {metrics. widthPixels, metrics. heightPixels };}}
Layout File
 
  
  
  
  
 

After running, we can see the above. Note that in this small example, we didn't perform line feed processing. Here we just learned how to use layout, if you need to master the process of custom controls, you can define a FlowLayout.

 

4. Summary

Here, the basic knowledge about custom controls, onMeasure and onLayout, is finished. In fact, at the beginning, I was afraid of this part of content and it was very difficult, however, if you study hard and clear your thoughts carefully, you will find that it is not very difficult, with the basics of the last two articles, we can implement some small custom controls. The idea is very important when performing custom controls. Only by mastering the basics, in order to achieve the desired effect according to our design, learning programming is like this. It requires us to have an idea that is produced by our constant accumulation.

 

 

 

 

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.