Android Art Development Exploration Fourth Chapter--view working principle (Part I)

Source: Internet
Author: User
Tags call back

This chapter is more fun, the main introduction of the work of the view, as well as the implementation of Custom view, in Android, view is a very important role, simply speaking, view is the visual representation of Android, On the interface Android provides a complete set of GUI library, there are a lot of controls, but sometimes not satisfied with the requirements, so only the custom view, we will simply say the process, and then to practice in addition to the view of the three processes, view common callback method must be mastered , such as construction methods, Onattach,onvisibilitychanged,ondetach, and for some custom view with sliding effects, as well as dealing with sliding events and sliding conflicts, there are several fixed types of custom view in general. View or viewgroup, some directly rewrite the native control, this depends on the demand, OK, let's go directly!
  First of all, we still need to understand some basic concepts before we viewroot and formally introduce the three major processes of view, so this chapter will say Viewroot and correspond to Impl class, he is the link between WindowManager and Decorview, and the three processes of view are done through, In Activitythread, when the activity is created, the Decorview is added to the window duty fee, the Impl object is created, and the Impl object is connected to the Decorview, This can be referred to the official website: 1212View drawing process starting from Viewroot's Perfromtraversals method, he warns Measure,layout and draw three processes to draw the view out, where measure measurement, Layout determines the location of the view in the container, draw starts to draw on the screen, for perfromtraversals of the approximate flow, you can see the picture here to write the image description of the perfromtraversals will call Perfrommeasure in turn, Perfromlayout,perfromdraw, they complete the top-level view of the measure,layout and draw three processes, wherein the measure method is called in Perfrommeasure, In the measure method called onmeasure, this time measure flow from the parent container passed to the child element, so that the completion of a measure process, and then the child element will repeat the parent container measure process, so repeatedly completed the entire view tree traversal, Similarly, the other two is the same, the only difference is that the Perfromdraw transfer process is in draw repeatedly through the dispatchdraw to achieve, but there is no essential difference between the way the view is determined by the width of the high, After the measure is complete, the getmeasurewidth and getmeasureheight can be used to obtain the height and width of the view measurement, and in all cases the tower is almost equal to the final width, except in exceptional cases, after that, The layout process determines the coordinates of the four vertices of the view and the width of the actual view, after completion, obtained through Gettop,getleft,getright,getbottom, draw determines the display of the view, only after the draw method is completed, The view is displayed on the screen, such as top-level view Decorview, in general he will contain a vertical direction of the linearlayout, there are two parts, which is the title bar, here is the content, in activity, we can set the layout file through Setcontentview is placed in the content, and the contents of the ID is content, so we could understand that is actually in Setview, then how to get content? You can viewgroup content = Findviewbyid (Android., how to get the view we set: Content.getchildat (0), at the same time, through the source we can know, Deaorview is actually a framelayout, View layer events are passed Decorview first and then sent to view here to write a picture description two. Understanding in order to better understand the measurement process of the view, we also need to understand measurespec, from the name, Measurespec looks like "measurement specifications" or " Measurement specification ", no matter how the translation, he seems to be more or less decided the view of the measurement process, through the source can be found, Measurespec indeed participated in the measurement process of the view, the reader may have doubts, Measurespec is what? Measurespec to a large extent determines the size of a view, which is largely because the process also receives the image of the parent container, because the parent container image Measurespec is created during the measurement process, The system will convert the view's layoutparams according to the rules applied by the parent container to the corresponding Measurespec, and then according to the Measurespec to measure the width of the view, Measurespec looks a bit complicated, in fact, his implementation is very simple, Let's break it down. Represents a 32-bit int value, the high two-bit represents Specmode, the low 30-bit represents the Specsize,specmode refers to the measurement mode, and specsize refers to the size of a measurement mode, the following first look at some of the internal constants defined, It's not hard to understand how this works.}}}} 123456789101112131415161718192021222324123456789101112131415161718192021222324 avoid excessive object memory allocation by packaging Specmode and specsize into an int value , in order to facilitate operation, it provides the role of packaging and unpacking, Specmode and Specsize is also an int value, has been specmode and specsize can be packaged into one, one can be unpacked in the form of its original specmode and SpecsizE, it is important to note that this refers to the int value represented, not itself.
  There are three categories, each of which has a special meaning that the parent container does not have any restrictions on the view, to how large, this situation is generally used inside the system, indicating that a measurement of the state of the parent container has detected a view of the required precision size, this time the final size of the view is specsize specified value, It corresponds to the match_parent in the Layoutparams, and the specific value of the two modes of the parent container specifies an available size, that is, the size of Specsize,view can not be greater than this value, specifically what values to see the specific implementation of different view, It corresponds to the layoutparams and layoutparams in the internal system is the measurement of the view through the Measurespec, but under normal circumstances we use the view of the measurement, But under normal circumstances we use view to specify Measurespec, but nonetheless we can set the view to Layoutparams, when the view is measured, The system converts the Layoutparams to the corresponding measurespec under the constraints of the parent container, and then according to the Measurespec to determine the width height after the view measurement, it is important to note that Measurespec is not the only layoutparams decision, Layoutparams need to decide with the parent container the measurespec of the view to further determine the width of the view, For top view (Decorview) and normal view, the Measurespec conversion process is somewhat different, and for Decorview, its measurespec is determined by the measurespec of the parent container and its own layoutparams , Measurespec once determined, Measurespec can go to the view to measure for the Decorview, in the Measurehierarchy method in Viewrootimpl has such a piece of code. He showed Decorviwew's measurespec creation process, Where Desiredwindowwidth and desiredwindowheight are screen size 123123 next look at the implementation of the Getrootmeasurespec method:}} 12345678910111213141516171819201234567891011121314151617181920 through the above code, the Decorview of the Mesourspec process is very clear, In particular, it complies with the following format, according to the width of the layoutparams parameters to divide the precise mode, size isThe maximum size of the window, variable size, but not the size of the screen fixed size (such as 100DP): precise mode, the size specified in layoutparams for normal view, here is the view in our layout, The measure process of view is passed by ViewGroup, first look at ViewGroup Measurechildwithmargis method} 12345678910111213141234567891011121314 the above method will measure the child element, Before invoking the measure method of a child element, the mesurespec of the child element is obtained by means of the Getchildmeasurespec method, which, from the code perspective, is clearly The creation of the mesurespec of the child element is related to the mesurespec of the parent container and the layoutparams of the child element, and also to the margin of the view, which can be seen ViewGroup Getchildmeasurespec method}} }}}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636 4656667686912345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596 0616263646566676869 the above method is not difficult to understand, his main role is based on the parent container Measurespec combined with the view itself to Layoutparams to determine the mesurespec of the child elements, The pading in the parameter refers to the size of the control that is already occupied in the parent container, so that the child element can use the size of the parent container minus pading. The specific code 123123 clearly shows the general view of the Measurespec at the same time combined with the view itself layoutparams to determine the meaurespec of the child elements of the creation rules, clearer understanding of the logic, here to provide a table, The working principle of the table is combed, and the parentsize in the table refers to the size that is currently available in the parent container: This table is temporarily not drawn, you can go to the book 182 pages for this table, here to do a description. As mentioned earlier, for normal view, its measurespec by the parent container's measureSpec and its own layoutparams to jointly decide, then for the different parent container and Viev itself different layoutparams,view can have a variety of measurespec. Briefly here, when the view is fixed width/height, regardless of the parent container's Measurespec, the measurespee of the view is the exact mode, then the view is also the precision mode and its size is the remaining space of the parent container, if the parent container is the maximum mode, Then view is also the maximum mode and its size does not exceed the remaining space of the parent container. When the width/height of the view is wrap_content, regardless of whether the parent container's mode is accurate or maximized, the view mode is always maximized, and the size cannot exceed the remaining space of the parent container, and the reader may find that the unspecified pattern has been omitted from our analysis. That's because this pattern is primarily used for multiple measure within the system, and in general, we don't need to focus on this pattern.
Through this table can be seen, as long as the parent container measurespec and child elements of the layoutparams, can quickly determine the measurespec of the child elements, with the Measurespec can further determine the size of the sub-Pro measurement. It is important to note that the table is not a summary of the experience, it is just this method presented in a tabular manner of the workflow view workflow is mainly referred to measure, layout, draw the three processes, namely, measurement, placement and drawing, wherein measure determines the measurement width of the view /high, layout determines the position of the final width/height and four vertices of the view, while Draww draws the view to the screen.
Process to the situation, if it is only a primitive view, then through the method can be completed its measurement process, if it is a viewgroup, in addition to the completion of their own measurement process, but also to go through the call all the child elements of the method, the child elements and then recursion to execute the process, The measure process for the measure process discussed in the following two scenarios is done by its measure method, the measure method is a final type method, which means that subclasses cannot override this method. In the view measure method to call the view's Onmesure method, so only need to see onmeasure implementation, the Onmesure method of view is as follows:}12345671234567 The above code is very brief, but simplicity does not mean simple, Setmeasureddimension will set the view width/height measurement, so we just need to getdefaultsize the method.
}}1234567891011121314151612345678910111213141516 can see, getdefaultsize this logic is very simple, for us, we only need to see At_most and exactly these two situations, Simple understanding, in fact, the size of the getdefaultsize return is mesourspec in the specsize, and this specsize is the size of the view, here many times mentioned the size after the measurement, because the final size of the view, is in the layout stage, So there must be a distinction here, but in almost all cases the measurement and final size of the view is equal to the case of unspecified, which is generally used within the system's internal measurement process, in which case The first parameter of the view's size getdefaultsize is size, which is the return value of Getsuggestedminimumwidth and Getsuggestedminimumheight () for each of the two methods of the width height:}} 123456789123456789 here only the implementation of the Getsuggestedminimumwidth method is analyzed, getsuggestedminimumheight and his principle are the same. As you can see from the Getsuggestedminimumwidth code, if the view is not set to a background, the view width is mminwidth, and mminwidth corresponds to the value specified by the Android:minwidth property. The width of the view is therefore the value specified by the Android:minwidth property. If this property is not specified, then minwidth defaults to 0, and if the view specifies a background, then the width of the view is the mminwidthh meaning we already know, so what is mbackground.getminimumwidth ()? Let's take a look at the Getminimumwidth method of Drwable, as follows:}12341234 can see that Getminimumwidth returns the original width of drawable, provided that the drawable has the original width, otherwise it returns 0. So, under what circumstances do drawable have the original width? Here first to give an example, Shapedrawable no original width/height, and bitmapdrawable has the original width/height (picture size), the detailed content will be introduced in the 6th chapter.
Here is a summary of getsuggestedminimumwidth logic: If the view does not set the background, then return the value specified by the Android:minwidth property, this value can be 0: if the view has a background, then back to Android: The maximum value of the minwidth and the minimum width of the background, the return value of Getsuggestedminimumwidth and Getsuggestedminimumheight is the measurement width/height of the view in the unspecified case.
Judging from the implementation of the Getdefaulsize method, the width/height of the view is determined by specsize, so we can conclude that the custom control that inherits the view directly needs to override the Onmeasure method and set the size of the wrapcontent itself. Otherwise, using wrap_content in the layout is equivalent to using Matchparent. Why? This reason requires a combination of the above code and the previous table to better understand. From the above code we know that if the view in the layout using Wrapcontent, then its specmode is At_most mode, in this mode, its width/higher than the specsize; look at table 4-1. In this case, the specsize of view is Parentsize, and parentsize is the size currently available in the parent container, that is, the current amount of space left by the parent container. Obviously, the width/height of the view is equal to the amount of space currently remaining in the parent container, and this effect is exactly the same as using match_parent in the layout. How to solve this problem? It is also very simple, as shown in the code below.
}}1234567891011121314151612345678910111213141516 in the above code, we only need to specify a default internal width/height (mwidth and mheight) for the view. and set this width/height when wrapcontent. For non-wrapcontent cases, we follow the measurement of the system can be, as to the default internal width/height of how to specify the size, this is not a fixed basis, according to the need to flexibly specify. If you look at TextView, ImageView and other sources can be known, for Wrapcontent situation, their onmeasure methods have done special treatment, readers can view their own source code.
The measure process for viewgroup, in addition to the completion of their own measure process, will also traverse to invoke all the child elements of the measure method, the various child elements return to perform this process. Unlike view, ViewGroup is an abstract class, so it does not override the view's Onmeasure method, but it provides a call}}}12345678910111234567891011 from the above code to see, At the time of ViewGroup's measure, each sub-element is measured, so this method is well understood}12345678910111234567891011 obviously, The idea of Measurechild is to take out the layoutparams of the child elements and then create the measurespec of the child elements through Getchidmeasurespec, The Measurespec is then passed directly to the view's measure method for measurement. The working process of Getchildmeasurespec has been analyzed in detail above.
We know that ViewGroup does not define the specific process of its measurement, because ViewGroup is an abstract class, and the Onmeasure method of its measurement process requires each subclass to be implemented specifically, such as Linearlayout,relativelayout, Why ViewGroup not like view of its Onmeasure method to do a unified implementation of it? That is because different viewgroup subclasses have different layout characteristics, which results in different measurement details, such as Lineartayout and relativel.ayout, the layout characteristics of the two are obviously distinct, so viewgroup can not do a unified implementation. The following is a LinearLayout Onmeasure method to analyze the measure process of viewgroup, and other layout type readers can analyze their own.
  First, let's take a look at LinearLayout's Onmeasure method}}1234567812345678 the above code is very simple we choose one to see, such as the selection of the vertical direction of the linearlayout measurement process, That is measurevertical, his source is still relatively long, we see:}}} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950511234567891011121314151617181 92021222324252627282930313233343536373839404142434445464748495051 from the above code can be seen, The system iterates through the child elements and executes the Measurechildbeforelayout method on each child element, which invokes the measure method of the child element, so that each child element begins to enter the measure process sequentially. And the system by mtotallength this variable to store linearlayout in the vertical direction of the preliminary height, no measurement of a sub-element, Mtotallength will increase, the increase of the main include the height of the child element and the vertical direction of the margin, etc. When the child element is measured, linearlayout will measure its size, see the Source:}}}}}}} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 66www.gouyifl.cn676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 1131141151161171181191201211221234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 51525354555657585960616263646566676869707www.gouyiflb.cn172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 here to the above The code illustrates that when the child element is measured, linearlayout will measure its size according to the child elements, and for vertical linearlayout, his horizontal measurement process follows the measurement process of the view, and the measurement process in the vertical direction is somewhat different from the view. , in particular, if the height of his layout is match_parent or specific values, then his drawing process and view consistent, that is, the height of specsize, if his layout in the height of the use of warp_content, Then her height is the height of all the sub-elements occupied by the high synthesis, but still cannot exceed his parent container space, but his final height still need to consider other vertical direction of the pading, this process further see source:}}} The onmeasure of 123456789101112131415161718192021123456789101112131415161718192021View is one of the most complex of the three major processes, and after measure is completed, The measurement width/height of the view can be obtained correctly by Getmeasurewidth/height. It should be noted that in some extreme cases measure can determine the final measurement width/height, in which case the system may have to call the measure method several times to measure, in which case the measured values obtained in the Onmeasure method are likely to be inaccurate. A good habit is to get the measurement width/height or the final width/height of the view in the OnLayout method.
The VIAW measure process has been analyzed in detail, and now consider a situation where we want to do a task when activity is started, but this task needs to get the width/height of a view, which the reader might say, it's simple, In OnCreate or onresume inside to get this view of the wide/High Line, the reader can try it, in fact, in OnCreate, OnStart, Onresume can not be the correct view of the width/height information, This is because the measure process of the view and the activity's life cycle method are not executed synchronously, so there is no guarantee that Activiy executes the OnCreate, OnStart, Onresume when a VICW is complete, if the view has not been measured, Then the obtained width/height is 0. Is there any way to solve the problem? The answer is yes, here are four ways to solve this problem:.
The meaning of this method is: The view has been initialized, the width/height is ready, this time to get wide/high is no problem. It is important to note that it is called multiple times and is called once when the activity's window gets focus and loses focus. Specifically, when activity resumes execution and pauses execution, it is called, and is frequently called if Onresume and OnPause are frequently performed. The typical code is as follows:}}}}12345678910111213141516171234567891011121314151617 (2)
Post can post a runnable to the message queue, and then wait until Lopper calls Runnable, the view is initialized, the typical code is as follows:}});} 123456789101112123456789101112 using Viewtreeobserver's many callbacks can do this function, such as using the Ongloballayoutlistener interface, When the state of the view tree changes or the visibility of the view inside the view tree changes, the Ongloballayout method will call back, so this is a good example of getting the width of the view, and it is important to note that this method will be called multiple times, along with the change in the view tree state. , the typical code is as follows}});} 12345678910111213141234567891011121314 by manually measuring the width of the view, this method is more complex, here to deal with the situation, according to the view of the layoutparams to deal with direct abandonment, can not measure the specific width of the height, According to the measurement process of the view, it is necessary to know the parentsize, that is, the remaining space of the parent container, and this time we cannot know the size of the parentsize, Measurespec So theoretically we can't measure the size of the view specific values such as the width is 100DP, then we can do this: 123123 as follows 123123 note (1<<30)-1, by analyzing the implementation of Measurespec can know, The size of the view is 30-bit binary representation, which means that the maximum is 30 1 (2^30-1), which is (1<30-1), In the largest mode, we can theoretically support the maximum value to construct the Mwasurespec is reasonable about the view of the measure, the network has two wrong usage, why is wrong, first of all it violates the system's internal implementation specifications (because the wrong mea Surespec to obtain reasonable specmode, which leads to measure process error, and next cannot guarantee mwasure the correct result)
  The first method of error: 123123 use of the second error 11 the function of the procedure is that ViewGroup is used to determine the role of the child element, and when the position of ViewGroup is confirmed, his layout will go through all the child elements and call the On method, In the layout method onlayou is called, layout process and the measure process is much simpler, the layout method determines the location of the view itself, and the on method will determine the location of all child elements, first look at the layout method of View}}}} The approximate flow of the 12345678910111213141516171819202122232425262728293031321234567891011121314151617181920212223242526272829303132 method is as follows , a Setframe method is first used to set the position of the four vertices of the view, that is, the four values of the initialization mleft,mtop,mright,mbottom, and once the four vertices of the view are determined, then the position of the view in the parent container is determined, and then the method is called. The purpose of this method is to call the parent container to determine the location of the child elements, and onmeasure similar to the specific location of the implementation of the same and specific layout, all view and viewgroup have no real implementation of the method, Let's take a look at LinearLayout}}1234567812345678 very well understand, yes, this and onmeasure a bit similar, we took layoutvertical, first read the Source:}}}}}} 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 6667686970717273747576777879808182123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 49505152535455565758596061626364656667686970717273747576777879808182 here to analyze the Layoutvertical code logic, you can see, This method iterates through all child elements and calls the Setchildframe methodTo specify the corresponding position for the child element, where the childtop will gradually become larger, which means that the subsequent child elements will be placed in the lower position, just in line with the direction of the linear layout, as for Setchildframe, he is merely invoking the elements of the layout method, Such a parent container in the layout method in the completion of their own positioning, through the OnLayout method to call, the child element will be through their own method to determine their position, Such a layer of pass through the entire view tree layout process, the Setchildframe method can be seen:}123123 we notice that the width and height of the setchildframe is actually a sub-element measurement of the height, From the following code can be seen in 123123 and in the layout method through the Setframe to set the four vertex position of the child element, there are a few sentences in the method: 1234512345 below we come back to the question before, the view of the measurement of the width of the height and the final width of the difference between, The question can now be answered specifically, what is the difference between the two methods of view Getmeasurewidth and getwidth? As for Getmeasureheight and GetHeight are exactly the same, in order to answer this question we first look at getwidth and getheight concrete implementation

Android Art Development Exploration fourth Chapter--view works (i)

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: 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.