Measure calculation process of View in Android

Source: Internet
Author: User

Measure calculation process of View in Android

 

In Android, Veiw goes through three phases in sequence from memory to display on the UI: Traffic calculation-> Layout-> drawing, for details about the overall mechanism of View calculation, layout, and drawing, see the layout and Drawing Mechanism of View in Android. Volume is the basis of layout and drawing, so it is an important part. This article will analyze the View's quantitative calculation process from the source code perspective, which involves some key classes and key methods.

The purpose of measuring the View is to let the parent control of the View know the size of the View.

Overview of the traffic calculation process

If the View to be calculated is of the ViewGroup type, the ViewGroup will traverse the sub-views in the onMeasure method to calculate the values in sequence. This article focuses on the process of calculating the views of non-ViewGroup views, because once we understand the View calculation process of a non-ViewGroup, The ViewGroup's quantitative calculation is much simpler, mainly because the ViewGroup executes the quantitative calculation of the Child views in sequence.

The starting point of the application's traffic calculation is the ViewRootImpl class, which starts to calculate the traffic of the Child View in turn. If the child View is a ViewGroup, the Child View of the ViewGroup will be traversed for traffic calculation in turn. That is to say, the quantitative calculation is performed from the root node of the View tree to the vertical recursion, so as to calculate the number of views of the View tree from top to bottom until the calculation of the View of the leaf node is completed.

So how to calculate a View? Android calculates the size of a View by calling the measure () method of the View, so that the parent control of the View can know the size and space of the View.

Specifically, ViewGroup, the parent control of View, will call the measure method of View, and ViewGroup will pass some width and height constraints to the measure method of View.

The measure method of View first reads the previously cached traffic calculation result from the member variable. If the cached value can be found, it is basically done. If no cache value is found, then, the measure method will execute the onMeasure callback method, and the measure method will pass the preceding width and height constraints to the onMeasure method in turn. The onMeasure method completes the specific quantitative calculation, and saves the calculation result to the member variables mMeasuredWidth and mMeasuredHeight of the View by calling the setMeasuredDimension method of the View.

After the measurement is completed, the View parent control can call the getMeasuredWidth, getMeasuredState, and getMeasuredWidthAndState methods to obtain the measurement result of the View.

The above is the overall process of non-ViewGroup View calculation.

Introduction to MeasureSpec

As mentioned above, when ViewGroup calls the View's measure method, it will pass in the ViewGroup's restriction on the width and height of the View. This is reasonable. For example, ViewGroup has limited space, it needs to tell the child View the maximum size of the calculated size.

The size restriction mentioned above is MeasureSpec, which can be expressed by an Int value. The Int value contains two types of information at the same time: mode and size, that is, the mode and size. We know that the Int type value in Java is 4 bytes, Android uses the first high byte storage mode, and then uses the remaining three bytes to store the size.

View has a static internal class MeasureSpec, which has several static methods and static constants, we can use these methods to package mode and size into an Int value or parse the mode and size from an Int value.

Assume that we have an Int value named MeasureSpec that contains the measureSpec information.

By calling MeasureSpec. getSize (int measureSpec) parses the size information contained in three bytes from measureSpec. This method returns the Int type, that is to say, the size we get is actually set to 0 for the 8 binary bits of the original high byte of measureSpec. The returned value size of this method is also a four-byte Int value, however, the mode information is completely excluded.

By calling MeasureSpec. getMode (int measureSpec) parses the mode information contained in the high byte from measureSpec. This method returns the Int type, that is to say, the mode we get is actually set to 0 for the 24 binary codes of the three low bytes of the original measureSpec. The return mode of this method is also a four-byte Int value, but it does not contain the size information.

We understand the size well, for example, indicating a width value or a height value. So what is mode?

There are three modes:

MeasureSpec. AT_MOST, that is, 0x80000000. This value indicates that the maximum size of a View can be specified by its parent ViewGroup. For example, there is an Int value widthMeasureSpec, viewGroup passes it to the View's measure method. If the mode Value in widthMeasureSpec is AT_MOST and the size is 200, the maximum width of View is 200.

MeasureSpec. EXACTLY, that is, 0x40000000. This value indicates that the View must use the size specified by its parent ViewGroup, or take widthMeasureSpec as an example. If the mode value is EXACTLY, the size is 200, the View width must be 200.

MeasureSpec. UNSPECIFIED, that is, 0x00000000. This value indicates that the View's parent ViewGroup does not set a restriction on the size of the View. In this case, the View can ignore the size in measureSpec, view can take the desired value as the size of the quantitative calculation.

For more information, see the API documentation android/view/View. MeasureSpec.

Measure Method

The method signature for measure () ispublic final void measure(int widthMeasureSpec, int heightMeasureSpec).

When the ViewGroup, the parent control of the View, computes the View, the View's measure method is called, and the ViewGroup passes in widthMeasureSpec and heightMeasureSpec, it represents the limitations of the parent control on the width and height of the View.

The source code of the measure method is as follows:

Public final void measure (int widthMeasureSpec, int heightMeasureSpec) {// first, judge whether the layoutMode of the current View is a special case; boolean optical = isLayoutModeOptical (this); if (optical! = IsLayoutModeOptical (mParent) {// LAYOUT_MODE_OPTICAL_BOUNDS is a special case. Insets insets = getOpticalInsets (); int oWidth = insets are rare. left + insets. right; int oHeight = insets. top + insets. bottom; widthMeasureSpec = MeasureSpec. adjust (widthMeasureSpec, optical? -OWidth: oWidth); heightMeasureSpec = MeasureSpec. adjust (heightMeasureSpec, optical? -OHeight: oHeight);} // calculate the key value based on widthMeasureSpec and heightMeasureSpec. The key value is used as the key below, and the result of our calculation is long key = (long) widthMeasureSpec <32 | (long) heightMeasureSpec & 0 xffffffffL; // mMeasureCache is a member variable of the LongSparseLongArray type, // It caches the results calculated by Views under different widthMeasureSpec and heightMeasureSpec. // if mMeasureCache is empty, a new object is assigned to mMeasureCache if (mMeasureCache = null) mMeasureCache = new LongSparseLongArray (2); // mOldW IdthMeasureSpec and mOldHeightMeasureSpec indicate the widthMeasureSpec and heightMeasureSpec of the last View calculation. // when the View's measure method is executed, view always checks whether it is really necessary to spend a lot of effort to do real quantitative calculations // mPrivateFlags is an Int type value, it records various View status bits // If (mPrivateFlags & PFLAG_FORCE_LAYOUT) = PFLAG_FORCE_LAYOUT, // It indicates that the current View needs to be forcibly layout (for example, the forceLayout method of the View is executed ), therefore, in this case, you need to calculate the volume. // if the new widthMeasureSpec/heightMeasureSpec and the mOldWidthMeasureSpec/mOldHeightMeasure Spec, // so that the parent ViewGroup of the View changes the size limit of the View. In this case, if (mPrivateFlags & PFLAG_FORCE_LAYOUT) = PFLAG_FORCE_LAYOUT | widthMeasureSpec! = MOldWidthMeasureSpec | heightMeasureSpec! = MOldHeightMeasureSpec) {// reset the View status mPrivateFlags through the bitwise operation and mark it as mPrivateFlags & = ~ PFLAG_MEASURED_DIMENSION_SET; // perform special resolveRtlPropertiesIfNeeded () on Arabic, Hebrew, and other languages written and laid out from the right to the left; // before the View calculates the actual amount, view also wants to further confirm whether the cached traffic calculation result can be read from the existing cache mMeasureCache. // if it is caused by force layout, set cacheIndex to-1, that is, do not read the calculation result from the cache. // if the calculation result is not caused by force layout, then we use the key value calculated based on measureSpec as the cache index cacheIndex. Int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) = PFLAG_FORCE_LAYOUT? -1: mMeasureCache. indexOfKey (key); // sIgnoreMeasureCache is a boolean member variable whose value is calculated in the View constructor, in addition, it is only calculated once. // some old apps hope that the onMeasure method will always be called during a layou process. // specifically, the value is calculated as follows: sIgnoreMeasureCache = targetSdkVersion <KITKAT; // if the API version of targetSdkVersion is earlier than KITKAT, that is, the API level is less than 19, then sIgnoreMeasureCache is true if (cacheIndex <0 | sIgnoreMeasureCache) {// if it is run here, it indicates that we have not found the calculated size from the cache or the value of sIgnoreMeasureCache is true, which causes us to ignore the cache knot. If // The onMeasure method is called here, And the size restriction conditions widthMeasureSpec and heightMeasureSpec are passed in, // The onMeasure method will perform the actual amount calculation, save the calculation result to the member variable onMeasure (widthMeasureSpec, heightMeasureSpec); // After onMeasure is executed, reset the View status mPrivateFlags through the bit operation, mark it as the status mPrivateFlags3 that does not need to be calculated before layout ~ PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;} else {// if it is run here, this indicates that the current condition allows the View to read the calculated result from the cached member variable mMeasureCache // use the cacheIndex obtained above to retrieve the value from the cached mMeasureCache, you do not have to calculate long value = mMeasureCache by calling the onMeasure method. valueAt (cacheIndex); // once we read the value from the cache, we can call setMeasuredDimensionRaw to setMeasuredDimensionRaw (int) (value> 32), (int) value); mPrivateFlags3 | = PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;} // If the custom View The onMeasure method is overwritten, but the setMeasuredDimension () method is not called. // an exception is thrown here, reminding developers to call setMeasuredDimension () in the onMeasure method () method // how does Android know if we call the setMeasuredDimension () method in the onMeasure method? // The method is very simple, or by parsing the status bit mPrivateFlags. // In the setMeasuredDimension () method, mPrivateFlags is set to the PFLAG_MEASURED_DIMENSION_SET status, that is, the calculated status, // check whether mPrivateFlags contains the PFLAG_MEASURED_DIMENSION_SET status to determine whether setMeasuredDimension is called if (mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET )! = PFLAG_MEASURED_DIMENSION_SET) {throw new IllegalStateException (View with id + getId () +: + getClass (). getName () + # onMeasure () did not set the + measured dimension by calling + setMeasuredDimension ();} mPrivateFlags | = PFLAG_LAYOUT_REQUIRED ;} // mOldWidthMeasureSpec and gauge store the latest MeasureSpec during the calculation. // After the calculation, assign the new MeasureSpec to them: mOldWidthMeasureSpec = widthMeasureSpec; required = heightMeasureSpec; // use the key calculated above as the key and the calculation result as the value. Put the key-value pair in the member variable mMeasureCache, // In this way, the result of this calculation is cached, so that the next time the measure method is executed, it may be directly read from it, // thus eliminating the need for the actual calculation step mMeasureCache. put (key, (long) mMeasuredWidth) <32 | (long) mMeasuredHeight & 0 xffffffffL );}

The above comments describe each line of code in detail. If you read them carefully, I believe it will be clear at a glance. Here we will briefly summarize what the measure method has done based on the above comments:

First of all, we need to know that it is not only necessary for the View's measure method to be executed that the View must be silly and really do the amount calculation work. The View also prefers to be lazy. If the View finds that there is no need to calculate the amount, then it will not really do the work of quantitative calculation.

Specifically, View first checks whether the force calculation is required and whether the MeasureSpec passed in this measurement is the same as the last measurement. If the force calculation is not performed or the MeasureSpec is the same as the last measurement, the View does not need to be calculated.

If the preceding conditions are not met, View will consider performing quantitative calculation. However, before the quantitative calculation, View still wants to be lazy. It uses the key value calculated by MeasureSpec as the key to find whether the calculation result of the corresponding key has been cached in the member variable mMeasureCache, if this parameter can be found, you can simply call the setMeasuredDimensionRaw method to save the calculated results from the cache to the member variables mMeasuredWidth and mMeasuredHeight.

If you cannot read the cached volume calculation results from mMeasureCache, you can only call the onMeasure method to complete the actual volume calculation, and pass the size restriction conditions widthMeasureSpec and heightMeasureSpec to the onMeasure method. The onMeasure method is described in detail below.

No matter which branch of the above Code goes, the final View will get the result of the quantitative calculation and cache the result to the member variable mMeasureCache, so that the cache value can be read from the next execution of the measure method.

It should be noted that the View has a member variable mPrivateFlags, which is used to save various status bits of the View. Before the calculation starts, it is set to the not calculated status, after the calculation is complete, it is set to the calculated status.

OnMeasure Method

As mentioned above, when View finds that it has to perform actual quantitative calculation in the measure method, it will call the onMeasure method, the size restriction conditions widthMeasureSpec and heightMeasureSpec are passed to the onMeasure method as parameters. The onMeasure method of View is not an empty method. It provides a default implementation.
The onMeasure method code is as follows:

Protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {// onMeasure calls the setMeasuredDimension method. // setMeasuredDimension also needs to call the getDefaultSize method, // getDefaultSize you need to call the counter and counter methods setMeasuredDimension (getDefaultSize (partial (), widthMeasureSpec), getDefaultSize (getSuggestedMinimumHeight (), heightMeasureSpec ));}

We found that the onMeasure method will call the setMeasuredDimension method. The setMeasuredDimension method also needs to call the getDefaultSize method, and the getSuggestedMinimumWidth and getSuggestedMinimumHeight methods must be called.
SetMeasuredDimension-> getDefaultSize-> getSuggestedMinimumWidth/Height

Then we will first study getSuggestedMinimumWidth/Height, and then study getDefaultSize and setMeasuredDimension in sequence, so that we can understand the onMeasure method. In fact, the implementation logic of getSuggestedMinimumWidth is basically the same as that of getSuggestedMinimumHeight. Here we only study the getSuggestedMinimumWidth method.

GetSuggestedMinimumWidth Method

GetSuggestedMinimumWidth is used to return the minimum width recommended by the View. The Code is as follows:

Protected int getSuggestedMinimumWidth () {// if the background is not set for the View, the minimum width of the View is returned. // if the background is set for the View, return (mBackground = null )? MMinWidth: max (mMinWidth, mBackground. getMinimumWidth ());}

If no background is set for the View, the minimum mMinWidth of the View is returned.

If a background is set for the View, the maximum value of the minimum width of the View and the minimum width of the background is obtained.

Then you may be wondering where the minimum mMinWidth value saved in the View comes from? In fact, there are two ways to set the minimum width for the View.

The first case is that mMinWidth is assigned in the View constructor. View sets the minimum width of the View by reading the minWidth value defined in XML, the following code snippet is the section for parsing minWidth in the View constructor:

// Traverse the minWith attribute case R defined in XML. styleable. view_minWidth: // read the attribute value defined in XML as mMinWidth. If not defined in XML, set it to 0 mMinWidth =. getDimensionPixelSize (attr, 0); break;

The second case is to call the setMinimumWidth method of the View to assign a value to the minimum width mMinWidth of the View. The code of the setMinimumWidth method is as follows:

public void setMinimumWidth(int minWidth) {    mMinWidth = minWidth;    requestLayout();}

In this way, we can understand how the getSuggestedMinimumWidth method is executed. The getSuggestedMinimumHeight method is completely consistent with its logic, except that the width is changed to the height, so we will not repeat it here.

GetDefaultSize

We found in the onMeasure method that onMeasure will execute the following two lines of code: getDefaultSize (getSuggestedMinimumWidth (), widthMeasureSpec)
GetDefaultSize (getSuggestedMinimumHeight (), heightMeasureSpec)

We have studied getSuggestedMinimumWidth/Height, knowing that it will return the minimum width and Height of the View. Now we will study the getDefaultSize method.

Android will pass measureSpec to the getDefaultSize method for the desired size of the View and its parent control's size restriction information. This method calculates the final calculated size based on the comprehensive information.

The source code is as follows:

Public static int getDefaultSize (int size, int measureSpec) {// size indicates the size information of the View, such as the minimum width or the minimum height int result = size; // parse the specMode information int specMode = measureSpec from MeasureSpec. getMode (measureSpec); // parse the specSize information from measureSpec. Do not mix the specSize with the preceding size variable. int specSize = MeasureSpec. getSize (measureSpec); switch (specMode) {// If the mode is UNSPECIFIED, the View's parent ViewGroup does not set the restriction condition case MeasureSpec for the View. UNSPECIFIED: // when mode is UNSPECIFIED, View directly uses the desired size as the result of the quantitative calculation. result = size; break; // If mode is UNSPECIFIED, the maximum size that the parent ViewGroup can specify for the View. // If the mode is EXACTLY, the View must use the size specified by the parent ViewGroup. case MeasureSpec. AT_MOST: case MeasureSpec. EXACTLY: // when the mode is UNSPECIFIED or EXACTLY, View uses the size specified by its parent ViewGroup as the result of the quantitative calculation. result = specSize; break;} return result ;}

Through the above Code, we will find that the role of the View's parent ViewGroup's restriction condition measureSpec passed to the View is fully embodied in this method.

First, parse the corresponding specMode and specSize according to measuredSpec.

When the mode is UNSPECIFIED, the View directly uses the desired size as the result of the quantitative calculation.

When the mode is UNSPECIFIED or EXACTLY, the View uses the size specified by its parent ViewGroup as the result of the quantitative calculation.

In the end, View obtains the final size calculated based on the measuredSpec restrictions.

In this way, in the onMeasure method,
When getDefaultSize (getSuggestedMinimumWidth (), widthMeasureSpec) is executed, we get the final width value;
When getDefaultSize (getSuggestedMinimumHeight (), heightMeasureSpec) is executed, we get the final calculated height value.

SetMeasuredDimension

When studying the onMeasure method, we can see that setMeasuredDimension will call the getDefaultSize method, and pass the calculated width and height values as parameters to the setMeasuredDimension method. We will study this method.

The source code is as follows:

Protected final void setMeasuredDimension (int measuredWidth, int measuredHeight) {boolean optical = isLayoutModeOptical (this); if (optical! = IsLayoutModeOptical (mParent) {// layoutMode is a special case of LAYOUT_MODE_OPTICAL_BOUNDS. We do not consider Insets insets = getOpticalInsets (); int opticalWidth = insets. left + insets. right; int opticalHeight = insets. top + insets. bottom; measuredWidth + = optical? OpticalWidth:-opticalWidth; measuredHeight + = optical? OpticalHeight:-opticalHeight;} // call the setMeasuredDimensionRaw method to pass the calculation result to setMeasuredDimensionRaw (measuredWidth, measuredHeight );}

This method will determine whether layoutMode is a special case of LAYOUT_MODE_OPTICAL_BOUNDS. This exception is rare and we will ignore it directly.

The setMeasuredDimension method finally passes the result of the quantitative calculation to the setMeasuredDimensionRaw method. Let's take a look at the setMeasuredDimensionRaw method.

SetMeasuredDimensionRaw

SetMeasuredDimensionRaw receives two parameters, namely, the width and height of the calculated parameters.

The source code is as follows:

Private void setMeasuredDimensionRaw (int measuredWidth, int measuredHeight) {// Save the measured width measuredWidth to the mMeasuredWidth member variable in the View; // Save the measured height measuredHeight to the mMeasuredHeight member variable in the View; // Finally, set the status bit mPrivateFlags of the View to mPrivateFlags | = running ;}

We found that three things were done in this method:

Save the measured width measuredWidth to the mMeasuredWidth member variable of the View.

Save the measured height measuredHeight to the mMeasuredHeight member variable of the View.

Finally, set the View status bit mPrivateFlags to the calculated status.

State of the completed size

So far, the View's quantitative calculation process has been completed, but how does the View's parent ViewGroup read the View's quantitative calculation results?

View provides three methods:
1. getMeasuredWidth and getMeasuredHeight Methods
2. getMeasuredWidthAndState and getMeasuredHeightAndState
3. getMeasuredState Method

Some may wonder if the first group of methods is available? What are the functions of the following two groups of methods?

Here, we will take a closer look at the member variables mMeasuredWidth and mMeasuredHeight of the inventory calculation results in the View. The following discussions only discuss the width and understand the width processing method, the height is also the same.

MMeasuredWidth is an Int value, which consists of four bytes.

Let's assume that mMeasuredWidth only stores the width of the calculated width, and the View's parent ViewGroup can get this value through relevant methods. However, when a View is measured, the specMode value in the widthMeasureSpec passed to the parent ViewGroup is AT_MOST, And the specSize value is 100, but the minimum width of the View is 200, obviously, the specSize specified by the parent ViewGroup cannot meet the View Size. However, because the specMode value is AT_MOST, the View has to be compromised in the getDefaultSize method and can only set the final width of the quantitative calculation to 100. Then, when its parent ViewGroup obtains the 100 width of the View in some ways, ViewGroup thinks that only 100 is required for the sub-View, and finally gives the space of the sub-View with 100 width, this leads to a very narrow View on the UI interface and poor user experience.

To get more information from its View parent control, Android has made great efforts in mMeasuredWidth. Although it is an Int value, it wants to store more information, specifically, mMeasuredWidth is divided into two parts:

The first byte in its high position is the first part. It is used to mark whether the size after the calculation has reached the desired width of the View. We call this information the state information of the calculation. The lower three bytes are the second part, which is used to store the width calculated by actual traffic.

From this we can see that Android is actually the best use. A variable can contain two pieces of information, which is similar to the measureSpec principle, but the two are different:

MeasureSpec is to pass the Restricted Condition mode from ViewGroup to its subview. MMeasuredWidth and mMeasuredHeight are used to pass the state flag information with the calculation result from the View to its parent ViewGroup.

So you may ask, In this article we have not seen any special processing of the High-byte mMeasuredWidth? Let's take a look at the resolveSizeAndState method in the View.

ResolveSizeAndState

The resolveSizeAndState method is similar to the getDefaultSize method. Its internal implementation logic is the same, but there are differences. getDefaultSize only returns the final calculated size information, however, in addition to the final size information, the resolveSizeAndState may return the state flag information of the quantity calculation.

The source code of the resolveSizeAndState method is as follows:

Public static int resolveSizeAndState (int size, int measureSpec, int childMeasuredState) {final int specMode = MeasureSpec. getMode (measureSpec); final int specSize = MeasureSpec. getSize (measureSpec); final int result; switch (specMode) {case MeasureSpec. AT_MOST: if (specSize <size) {// when specMode is AT_MOST and the size specified by the parent control is smaller than the size specified by the View, // We will use the mask MEASURED_STATE_TOO_SMALL to add a label with a small size to the calculation result. // then, the parent ViewGroup can use this label to indicate that its size for the subview is too small, // a larger size may be allocated to the subview result = specSize | MEASURED_STATE_TOO_SMALL;} else {result = size;} break; case MeasureSpec. EXACTLY: result = specSize; break; case MeasureSpec. UNSPECIFIED: default: result = size;} return result | (childMeasuredState & MEASURED_STATE_MASK );}

When specMode is AT_MOST and the size specified by the parent control is smaller than the size specified by the View, the system adds a small mark to the result of the MEASURED_STATE_TOO_SMALL vector calculation with the mask, in this way, the parent ViewGroup can mark that the size of the Child View is too small, and then assign a larger size to the Child View.

The getDefaultSize method is only the default Implementation of obtaining the final size in the onMeasure method. It returns less information than the resolveSizeAndState method. When will the resolveSizeAndState method be called? There are two main scenarios:

Many layout classes in Android call the resolveSizeAndState method. For example, LinearLayout calls the resolveSizeAndState method instead of the getDefaultSize method during the amount calculation process. When implementing a custom View or ViewGroup, We can override the onMeasure method and call the resolveSizeAndState method in this method. GetMeasuredXXX Methods

Now let's look back at the following three methods:

GetMeasuredWidth and getMeasuredHeight Methods
This group of methods only returns the size information in the calculation result, removing the state information of the high byte. The getMeasuredWidth method is used as an example. Its source code is as follows:

Public final int getMeasuredWidth () {// The value of MEASURED_SIZE_MASK is 0x00ffffff. mMeasuredWidth and MEASURED_SIZE_MASK are used for bitwise AND operation, // you can set the 8 bits in the returned values to 0, removing the state information of the high byte. return mMeasuredWidth & MEASURED_SIZE_MASK ;}

The value of MEASURED_SIZE_MASK is 0x00ffffff. bitwise AND operation are performed using mMeasuredWidth and the mask MEASURED_SIZE_MASK. The 8 bits in the high byte values in the returned values are set to 0, removing the state information of the high

GetMeasuredWidthAndState and getMeasuredHeightAndState
The calculation results returned by the group of methods contain both the size and state information (if the state exists). The getMeasuredWidthAndState method is used as an example. The source code is as follows:

Public final int getMeasuredWidthAndState () {// This method directly returns the member variable mMeasuredWidth, because mMeasuredWidth itself already contains the size and possible state information return mMeasuredWidth ;}

This method directly returns the member variable mMeasuredWidth, because mMeasuredWidth already contains the size and possible state information.

GetMeasuredState Method
The Int value returned by this method also contains the state of the width calculation and the state of the height calculation, and does not contain any size information. The source code is as follows:

Public final int getMeasuredState () {// store the state of the width calculation in the first byte of the Int value, that is, the first byte in the high position // store the state in the third byte of the Int value return (mMeasuredWidth & MEASURED_STATE_MASK) | (mMeasuredHeight> MEASURED_HEIGHT_STATE_SHIFT) & (MEASURED_STATE_MASK> MEASURED_HEIGHT_STATE_SHIFT ));}

Let's analyze the above Code:

The value of the mask MEASURED_STATE_MASK is constant 0xff000000. The 8 bits of the high byte are all 1, and the 24 bits of the three remaining low byte are all 0.

The value of MEASURED_HEIGHT_STATE_SHIFT is constant 16.

When mMeasuredWidth & MEASURED_STATE_MASK is executed, bitwise AND operation are performed on mMeasuredWidth and MEASURED_STATE_MASK. The value of this expression is high in bytes and the state of the width is retained, filtered out the size of the three low-byte storage.

Because we have stored the state of the width after the calculation with the first byte at the upper level, the state at the height cannot be stored in the first byte at the upper level. Android intends to store it in the third byte. (MMeasuredHeight> MEASURED_HEIGHT_STATE_SHIFT) indicates that the mMeasuredHeight is shifted to 16 bits to the right, so that the height of the state byte is shifted from the first byte to the third byte, because the state at the height moves to the right, the corresponding mask also moves accordingly. (MEASURED_STATE_MASK> MEASURED_HEIGHT_STATE_SHIFT) The Mask of state also shifts 16 bits from the first byte to the third byte, that is, the mask changes from 0xff000000 to 0x0000ff00. Then, the bitwise AND operation are performed with the right-shifted state and the right-shifted mask, so that the state information at the height is retained in the third byte, and the information in the 1st, 2, and 4 bytes is filtered out. The 24 bits in the three bytes are 0.

Finally, the state of the obtained width and the state of the height are bitwise OR operated, so that the state of the width and height are saved in an Int value: the state of the first byte storage width and the state of the third byte storage height.


Related Article

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.