1 implementation of Measurespec. 1.1 measure is how to implement the measurement control's width height and control mode. In order to facilitate analysis, I put it all the source code, are copied out:
public static class Measurespec {private static final int mode_shift = 30; private static final int mode_mask = 0x3 << mode_shift; /** * Measure Specification Mode:the parent have not imposed any constraint * on the child. It can be whatever size it wants. */public static final int UNSPECIFIED = 0 << mode_shift; /** * Measure Specification mode:the parent have determined an exact size * for the child. The child was going to being given those bounds regardless * of how big it wants to be. */public static final int exactly = 1 << mode_shift; /** * Measure Specification Mode:the child can is as large as it wants up * to the specified size. */public static final int at_most = 2 << mode_shift; /** * Creates a measure specification based on the supplied size and mode. * * The mode must always Be one of the following: * <ul> * <li>{@link android.view.view.measurespec#unspecified}</ li> * <li>{@link android.view.view.measurespec#exactly}</li> * <li>{@link ANDROID.V Iew. view.measurespec#at_most}</li> * </ul> * * <p><strong>Note:</strong> On API level and lower, makemeasurespec ' s * implementation is such that the order of arguments do not matter * and overflow in either value could impact the resulting measurespec. * {@link android.widget.RelativeLayout} is affected by this bug. * Apps targeting API levels greater than + would get the fixed, more strict * behavior.</p> * * @param size The size of the measure specification * @param mode the mode of the measure specification * @return The measure specification based on size and mode */public static int MakemeaSurespec (int size, int mode) {if (Susebrokenmakemeasurespec) {return size + mode; } else {return (size & ~mode_mask) | (Mode & Mode_mask); }}/** * Extracts the mode from the supplied measure specification. * * @param measurespec The measure specification to extract the mode from * @return {@link android.view.Vi ew. Measurespec#unspecified}, * {@link android.view.view.measurespec#at_most} or * {@link Android oid.view.view.measurespec#exactly} */public static int getmode (int measurespec) {return (Measu Respec & Mode_mask); }/** * Extracts the size from the supplied measure specification. * * @param measurespec The measure specification to extract the size from * @return the size in pixels def Ined in the supplied measure specification */public staticint getsize (int measurespec) {return (Measurespec & ~mode_mask); } static int adjust (int measurespec, int delta) {return Makemeasurespec (GetSize (Measurespec + delta), G Etmode (Measurespec)); }
From the source can be known, mode_mask is a plastic. The height of two bits is used to measure the control's mode, and the remaining lows measure the size of the control. (2^30, the phone's screen size is limited, so it is not possible to have a phone with a long or wide pixel over this number) today, the important reason is that I found that many people now have this kind of, I personally think the wrong idea: how to get the length and width of the control in OnCreate. Many people will say with view.onmeasure this method ah. But can this really get the size of the view? All accreditations, next look at the source code.
Public final void measure (int widthmeasurespec, int. Heightmeasurespec) {Boolean optical = islayoutmodeoptical (this ); if (Optical! = islayoutmodeoptical (mparent)) {Insets Insets = Getopticalinsets (); int owidth = Insets.left + insets.right; int oheight = insets.top + insets.bottom; Widthmeasurespec = Measurespec.adjust (Widthmeasurespec, optical?-owidth:owidth); Heightmeasurespec = Measurespec.adjust (Heightmeasurespec, optical?-oheight:oheight); }//Suppress sign extension for the low bytes long key = (long) Widthmeasurespec << 32 | (long) Heightmeasurespec & 0xffffffffL; if (Mmeasurecache = = null) Mmeasurecache = new Longsparselongarray (2); if ((Mprivateflags & pflag_force_layout) = = Pflag_force_layout | | Widthmeasurespec! = Moldwidthmeasurespec | | Heightmeasurespec! = Moldheightmeasurespec) {//first clears the MEasured Dimension flag Mprivateflags &= ~pflag_measured_dimension_set; Resolvertlpropertiesifneeded (); int cacheindex = (Mprivateflags & pflag_force_layout) = = Pflag_force_layout? -1:mmeasurecache.indexofkey (key); if (CacheIndex < 0 | | signoremeasurecache) {//measure ourselves, this should set the measured Dimensio N Flag back Onmeasure (Widthmeasurespec, Heightmeasurespec); MPRIVATEFLAGS3 &= ~pflag3_measure_needed_before_layout; } else {Long value = Mmeasurecache.valueat (CacheIndex); Casting a long to int drops the high of bits, no mask needed setmeasureddimension (int) (Value >> (int.), (int) value); MPRIVATEFLAGS3 |= pflag3_measure_needed_before_layout; }//Flag not set, Setmeasureddimension () is not invoked, we raise//a exception to warn the deVeloper if ((Mprivateflags & pflag_measured_dimension_set)! = Pflag_measured_dimension_set) { throw new IllegalStateException ("onmeasure () do not set the" + "measured dimension by calling" + "setmeasureddimension ()"); } mprivateflags |= pflag_layout_required; } Moldwidthmeasurespec = Widthmeasurespec; Moldheightmeasurespec = Heightmeasurespec; Mmeasurecache.put (Key, ((long) mmeasuredwidth) << 32 | (long) Mmeasuredheight & 0xffffffffL); Suppress sign Extension}
This is called in the Onmeasure method.
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) { setmeasureddimension (getdefaultsize ( Getsuggestedminimumwidth (), Widthmeasurespec), getdefaultsize (Getsuggestedminimumheight (), HeightMeasureSpec )); }
Let's take a look at this getsuggestedminimumwidth method, as the name implies, it should be the minimum width of the control.
protected int Getsuggestedminimumwidth () { return (Mbackground = = null)? Mminwidth:max (Mminwidth, Mbackground.getm Inimumwidth ()); }
Then take a look at the Getdefaultsize method.
public static int getdefaultsize (int size, int measurespec) { int result = size; int specmode = Measurespec.getmode (measurespec); int specsize = measurespec.getsize (measurespec); Switch (specmode) {case measurespec.unspecified: result = size; break; Case Measurespec.at_most: Case measurespec.exactly: result = specsize; break; } return result; }
This method works as follows: If mode is unspecified, the default size is used. If not, the specified size is used.
Next, call Setmeasureddimension this method to set the size.
Okay, that's the whole view.measure process.
But did we notice that during this time, can we get the actual size of the view? (I'm talking about the actual size of the view at this point: the note) is obviously not possible.
Google design, this measure this method must be to let the parent view call this method.
On the finishing of measure in Measurespec,view