• ViewGroup源码部分解析


    ViewGroup的官方解析是:

     A <code>ViewGroup</code> is a special view that can contain other views (called children.) The view group is the base class for layouts and views  containers. 

    其类定义如下:

    public abstract class ViewGroup extends View implements ViewParent, ViewManager

    首先是View的子类,并且实现两个接口,这两个接口中分别包含着极为重要的方法,可以说代表着ViewGroup的核心特性。

    ViewManager接口定义:

    复制代码
     1 package android.view;
     2 
     3 /** Interface to let you add and remove child views to an Activity. To get an instance
     4   * of this class, call {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
     5   */
     6 public interface ViewManager
     7 {
     8     public void addView(View view, ViewGroup.LayoutParams params);
     9     public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    10     public void removeView(View view);
    11 }
    复制代码

    ViewParent接口定义:

    复制代码
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.view;
     18 
     19 import android.graphics.Rect;
     20 
     21 /**
     22  * Defines the responsibilities for a class that will be a parent of a View.
     23  * This is the API that a view sees when it wants to interact with its parent.
     24  * 
     25  */
     26 public interface ViewParent {
     27     /**
     28      * Called when something has changed which has invalidated the layout of a
     29      * child of this view parent. This will schedule a layout pass of the view
     30      * tree.
     31      */
     32     public void requestLayout();
     33 
     34     /**
     35      * Indicates whether layout was requested on this view parent.
     36      *
     37      * @return true if layout was requested, false otherwise
     38      */
     39     public boolean isLayoutRequested();
     40 
     41     /**
     42      * Called when a child wants the view hierarchy to gather and report
     43      * transparent regions to the window compositor. Views that "punch" holes in
     44      * the view hierarchy, such as SurfaceView can use this API to improve
     45      * performance of the system. When no such a view is present in the
     46      * hierarchy, this optimization in unnecessary and might slightly reduce the
     47      * view hierarchy performance.
     48      * 
     49      * @param child the view requesting the transparent region computation
     50      * 
     51      */
     52     public void requestTransparentRegion(View child);
     53 
     54     /**
     55      * All or part of a child is dirty and needs to be redrawn.
     56      * 
     57      * @param child The child which is dirty
     58      * @param r The area within the child that is invalid
     59      */
     60     public void invalidateChild(View child, Rect r);
     61 
     62     /**
     63      * All or part of a child is dirty and needs to be redrawn.
     64      *
     65      * The location array is an array of two int values which respectively
     66      * define the left and the top position of the dirty child.
     67      *
     68      * This method must return the parent of this ViewParent if the specified
     69      * rectangle must be invalidated in the parent. If the specified rectangle
     70      * does not require invalidation in the parent or if the parent does not
     71      * exist, this method must return null.
     72      *
     73      * When this method returns a non-null value, the location array must
     74      * have been updated with the left and top coordinates of this ViewParent.
     75      *
     76      * @param location An array of 2 ints containing the left and top
     77      *        coordinates of the child to invalidate
     78      * @param r The area within the child that is invalid
     79      *
     80      * @return the parent of this ViewParent or null
     81      */
     82     public ViewParent invalidateChildInParent(int[] location, Rect r);
     83 
     84     /**
     85      * Returns the parent if it exists, or null.
     86      *
     87      * @return a ViewParent or null if this ViewParent does not have a parent
     88      */
     89     public ViewParent getParent();
     90 
     91     /**
     92      * Called when a child of this parent wants focus
     93      * 
     94      * @param child The child of this ViewParent that wants focus. This view
     95      *        will contain the focused view. It is not necessarily the view that
     96      *        actually has focus.
     97      * @param focused The view that is a descendant of child that actually has
     98      *        focus
     99      */
    100     public void requestChildFocus(View child, View focused);
    101 
    102     /**
    103      * Tell view hierarchy that the global view attributes need to be
    104      * re-evaluated.
    105      * 
    106      * @param child View whose attributes have changed.
    107      */
    108     public void recomputeViewAttributes(View child);
    109     
    110     /**
    111      * Called when a child of this parent is giving up focus
    112      * 
    113      * @param child The view that is giving up focus
    114      */
    115     public void clearChildFocus(View child);
    116 
    117     public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset);
    118 
    119     /**
    120      * Find the nearest view in the specified direction that wants to take focus
    121      * 
    122      * @param v The view that currently has focus
    123      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
    124      */
    125     public View focusSearch(View v, int direction);
    126 
    127     /**
    128      * Change the z order of the child so it's on top of all other children
    129      * 
    130      * @param child
    131      */
    132     public void bringChildToFront(View child);
    133 
    134     /**
    135      * Tells the parent that a new focusable view has become available. This is
    136      * to handle transitions from the case where there are no focusable views to
    137      * the case where the first focusable view appears.
    138      * 
    139      * @param v The view that has become newly focusable
    140      */
    141     public void focusableViewAvailable(View v);
    142 
    143     /**
    144      * Bring up a context menu for the specified view or its ancestors.
    145      * <p>
    146      * In most cases, a subclass does not need to override this.  However, if
    147      * the subclass is added directly to the window manager (for example,
    148      * {@link ViewManager#addView(View, android.view.ViewGroup.LayoutParams)})
    149      * then it should override this and show the context menu.
    150      * 
    151      * @param originalView The source view where the context menu was first invoked
    152      * @return true if a context menu was displayed
    153      */
    154     public boolean showContextMenuForChild(View originalView);
    155 
    156     /**
    157      * Have the parent populate the specified context menu if it has anything to
    158      * add (and then recurse on its parent).
    159      * 
    160      * @param menu The menu to populate
    161      */
    162     public void createContextMenu(ContextMenu menu);
    163 
    164     /**
    165      * This method is called on the parent when a child's drawable state
    166      * has changed.
    167      *
    168      * @param child The child whose drawable state has changed.
    169      */
    170     public void childDrawableStateChanged(View child);
    171     
    172     /**
    173      * Called when a child does not want this parent and its ancestors to
    174      * intercept touch events with
    175      * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
    176      * <p>
    177      * This parent should pass this call onto its parents. This parent must obey
    178      * this request for the duration of the touch (that is, only clear the flag
    179      * after this parent has received an up or a cancel.
    180      * 
    181      * @param disallowIntercept True if the child does not want the parent to
    182      *            intercept touch events.
    183      */
    184     public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
    185     
    186     /**
    187      * Called when a child of this group wants a particular rectangle to be
    188      * positioned onto the screen.  {@link ViewGroup}s overriding this can trust
    189      * that:
    190      * <ul>
    191      *   <li>child will be a direct child of this group</li>
    192      *   <li>rectangle will be in the child's coordinates</li>
    193      * </ul>
    194      *
    195      * <p>{@link ViewGroup}s overriding this should uphold the contract:</p>
    196      * <ul>
    197      *   <li>nothing will change if the rectangle is already visible</li>
    198      *   <li>the view port will be scrolled only just enough to make the
    199      *       rectangle visible</li>
    200      * <ul>
    201      *
    202      * @param child The direct child making the request.
    203      * @param rectangle The rectangle in the child's coordinates the child
    204      *        wishes to be on the screen.
    205      * @param immediate True to forbid animated or delayed scrolling,
    206      *        false otherwise
    207      * @return Whether the group scrolled to handle the operation
    208      */
    209     public boolean requestChildRectangleOnScreen(View child, Rect rectangle,
    210             boolean immediate);
    211 }
    复制代码

    可以看到addView, removeView, requestLayout, bringChildToFront等等重要的方法都在这两个借口里面得到定义

     

    一、addView方法

    所有的addView方法最后都集中到一个方法:

    复制代码
     1     /**
     2      * Adds a child view with the specified layout parameters.
     3      *
     4      * @param child the child view to add
     5      * @param index the position at which to add the child
     6      * @param params the layout parameters to set on the child
     7      */
     8     public void addView(View child, int index, LayoutParams params) {
     9         if (DBG) {
    10             System.out.println(this + " addView");
    11         }
    12 
    13         // addViewInner() will call child.requestLayout() when setting the new LayoutParams
    14         // therefore, we call requestLayout() on ourselves before, so that the child's request
    15         // will be blocked at our level
    16         requestLayout();
    17         invalidate();
    18         addViewInner(child, index, params, false);
    19     }
    复制代码

    requestLayout:当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent view重新调用他的onMeasure onLayout来对重新设置自己位置。这里首先安调用自己的requestLayout告诉自己的父View要求重新布局,然后调用invalidate(调用onDraw())要求重绘,然后调用addViewInner去调用child的requestLayout,这个方法的源码如下:

    复制代码
     1 private void addViewInner(View child, int index, LayoutParams params,
     2             boolean preventRequestLayout) {
     3 
     4         if (child.getParent() != null) {
     5             throw new IllegalStateException("The specified child already has a parent. " +
     6                     "You must call removeView() on the child's parent first.");
     7         }
     8 
     9         if (!checkLayoutParams(params)) {
    10             params = generateLayoutParams(params);
    11         }
    12 
    13         if (preventRequestLayout) {
    14             child.mLayoutParams = params;
    15         } else {
    16             child.setLayoutParams(params);
    17         }
    18 
    19         if (index < 0) {
    20             index = mChildrenCount;
    21         }
    22 
    23         addInArray(child, index);
    24 
    25         // tell our children
    26         if (preventRequestLayout) {
    27             child.assignParent(this);
    28         } else {
    29             child.mParent = this;
    30         }
    31 
    32         if (child.hasFocus()) {
    33             requestChildFocus(child, child.findFocus());
    34         }
    35 
    36         AttachInfo ai = mAttachInfo;
    37         if (ai != null) {
    38             boolean lastKeepOn = ai.mKeepScreenOn;
    39             ai.mKeepScreenOn = false;
    40             child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK));
    41             if (ai.mKeepScreenOn) {
    42                 needGlobalAttributesUpdate(true);
    43             }
    44             ai.mKeepScreenOn = lastKeepOn;
    45         }
    46 
    47         if (mOnHierarchyChangeListener != null) {
    48             mOnHierarchyChangeListener.onChildViewAdded(this, child);
    49         }
    50 
    51         if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
    52             mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE;
    53         }
    54     }
    复制代码

    这里可以看到我们写代码的时候经常看到的一个异常,也解释了index的具体含义。我们也可以看到:每一个View都保存了一个指向父View的指针。倒数第二段代码,也用到一个接口,可以监听子View的添加和删除:

    复制代码
     1 /**
     2      * Interface definition for a callback to be invoked when the hierarchy
     3      * within this view changed. The hierarchy changes whenever a child is added
     4      * to or removed from this view.
     5      */
     6     public interface OnHierarchyChangeListener {
     7         /**
     8          * Called when a new child is added to a parent view.
     9          *
    10          * @param parent the view in which a child was added
    11          * @param child the new child view added in the hierarchy
    12          */
    13         void onChildViewAdded(View parent, View child);
    14 
    15         /**
    16          * Called when a child is removed from a parent view.
    17          *
    18          * @param parent the view from which the child was removed
    19          * @param child the child removed from the hierarchy
    20          */
    21         void onChildViewRemoved(View parent, View child);
    22     }
    复制代码

     

    二、removeView

    removeView方法除了正常调用requestLayout和invalidate方法以外:

    复制代码
     1 /**
     2      * Removes the specified range of views from the group.
     3      *
     4      * @param start the first position in the group of the range of views to remove
     5      * @param count the number of views to remove
     6      */
     7     public void removeViews(int start, int count) {
     8         removeViewsInternal(start, count);
     9         requestLayout();
    10         invalidate();
    11     }
    复制代码

    但是看下面两个方法:

    复制代码
     1     /**
     2      * {@inheritDoc}
     3      */
     4     public void removeView(View view) {
     5         removeViewInternal(view);
     6         requestLayout();
     7         invalidate();
     8     }
     9 
    10     /**
    11      * Removes a view during layout. This is useful if in your onLayout() method,
    12      * you need to remove more views.
    13      *
    14      * @param view the view to remove from the group
    15      */
    16     public void removeViewInLayout(View view) {
    17         removeViewInternal(view);
    18     }
    复制代码

    后者没有调用requestLayout和invalidate,但是后者的说明里面提到是在onLayout()方法中调用这个方法的。所以如果没有猜错的话,在布局完成后调用后面一个方法对界面是没有影响的,好的转入正题:

    复制代码
     1 private void removeViewInternal(int index, View view) {
     2         boolean clearChildFocus = false;
     3         if (view == mFocused) {
     4             view.clearFocusForRemoval();
     5             clearChildFocus = true;
     6         }
     7 
     8         if (view.getAnimation() != null) {
     9             addDisappearingView(view);
    10         } else if (view.mAttachInfo != null) {
    11            view.dispatchDetachedFromWindow();
    12         }
    13 
    14         if (mOnHierarchyChangeListener != null) {
    15             mOnHierarchyChangeListener.onChildViewRemoved(this, view);
    16         }
    17 
    18         needGlobalAttributesUpdate(false);
    19 
    20         removeFromArray(index);
    21 
    22         if (clearChildFocus) {
    23             clearChildFocus(view);
    24         }
    25     }
    复制代码

    这里的删除貌似只是从Array中删除了一个元素(更加印证了前面提到的说法)。只有调用onLayout和onMeasure方法之后才会诱发界面重新布局。

     

    三、测量函数

    复制代码
     1 /**
     2      * Ask all of the children of this view to measure themselves, taking into
     3      * account both the MeasureSpec requirements for this view and its padding.
     4      * We skip children that are in the GONE state The heavy lifting is done in
     5      * getChildMeasureSpec.
     6      *
     7      * @param widthMeasureSpec The width requirements for this view
     8      * @param heightMeasureSpec The height requirements for this view
     9      */
    10     protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
    11         final int size = mChildrenCount;
    12         final View[] children = mChildren;
    13         for (int i = 0; i < size; ++i) {
    14             final View child = children[i];
    15             if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
    16                 measureChild(child, widthMeasureSpec, heightMeasureSpec);
    17             }
    18         }
    19     }
    20 
    21     /**
    22      * Ask one of the children of this view to measure itself, taking into
    23      * account both the MeasureSpec requirements for this view and its padding.
    24      * The heavy lifting is done in getChildMeasureSpec.
    25      *
    26      * @param child The child to measure
    27      * @param parentWidthMeasureSpec The width requirements for this view
    28      * @param parentHeightMeasureSpec The height requirements for this view
    29      */
    30     protected void measureChild(View child, int parentWidthMeasureSpec,
    31             int parentHeightMeasureSpec) {
    32         final LayoutParams lp = child.getLayoutParams();
    33 
    34         final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
    35                 mPaddingLeft + mPaddingRight, lp.width);
    36         final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
    37                 mPaddingTop + mPaddingBottom, lp.height);
    38 
    39         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    40     }
    复制代码

    前者只不过是告诉这个Group把自己所有的View全部测量一下,后者则是测量单个子View的大小。这边无疑涉及到一个方法:

    复制代码
     1 /**
     2      * Does the hard part of measureChildren: figuring out the MeasureSpec to
     3      * pass to a particular child. This method figures out the right MeasureSpec
     4      * for one dimension (height or width) of one child view.
     5      *
     6      * The goal is to combine information from our MeasureSpec with the
     7      * LayoutParams of the child to get the best possible results. For example,
     8      * if the this view knows its size (because its MeasureSpec has a mode of
     9      * EXACTLY), and the child has indicated in its LayoutParams that it wants
    10      * to be the same size as the parent, the parent should ask the child to
    11      * layout given an exact size.
    12      *
    13      * @param spec The requirements for this view
    14      * @param padding The padding of this view for the current dimension and
    15      *        margins, if applicable
    16      * @param childDimension How big the child wants to be in the current
    17      *        dimension
    18      * @return a MeasureSpec integer for the child
    19      */
    20     public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
    21         int specMode = MeasureSpec.getMode(spec);
    22         int specSize = MeasureSpec.getSize(spec);
    23 
    24         int size = Math.max(0, specSize - padding);
    25 
    26         int resultSize = 0;
    27         int resultMode = 0;
    28 
    29         switch (specMode) {
    30         // Parent has imposed an exact size on us
    31         case MeasureSpec.EXACTLY:
    32             if (childDimension >= 0) {
    33                 resultSize = childDimension;
    34                 resultMode = MeasureSpec.EXACTLY;
    35             } else if (childDimension == LayoutParams.MATCH_PARENT) {
    36                 // Child wants to be our size. So be it.
    37                 resultSize = size;
    38                 resultMode = MeasureSpec.EXACTLY;
    39             } else if (childDimension == LayoutParams.WRAP_CONTENT) {
    40                 // Child wants to determine its own size. It can't be
    41                 // bigger than us.
    42                 resultSize = size;
    43                 resultMode = MeasureSpec.AT_MOST;
    44             }
    45             break;
    46 
    47         // Parent has imposed a maximum size on us
    48         case MeasureSpec.AT_MOST:
    49             if (childDimension >= 0) {
    50                 // Child wants a specific size... so be it
    51                 resultSize = childDimension;
    52                 resultMode = MeasureSpec.EXACTLY;
    53             } else if (childDimension == LayoutParams.MATCH_PARENT) {
    54                 // Child wants to be our size, but our size is not fixed.
    55                 // Constrain child to not be bigger than us.
    56                 resultSize = size;
    57                 resultMode = MeasureSpec.AT_MOST;
    58             } else if (childDimension == LayoutParams.WRAP_CONTENT) {
    59                 // Child wants to determine its own size. It can't be
    60                 // bigger than us.
    61                 resultSize = size;
    62                 resultMode = MeasureSpec.AT_MOST;
    63             }
    64             break;
    65 
    66         // Parent asked to see how big we want to be
    67         case MeasureSpec.UNSPECIFIED:
    68             if (childDimension >= 0) {
    69                 // Child wants a specific size... let him have it
    70                 resultSize = childDimension;
    71                 resultMode = MeasureSpec.EXACTLY;
    72             } else if (childDimension == LayoutParams.MATCH_PARENT) {
    73                 // Child wants to be our size... find out how big it should
    74                 // be
    75                 resultSize = 0;
    76                 resultMode = MeasureSpec.UNSPECIFIED;
    77             } else if (childDimension == LayoutParams.WRAP_CONTENT) {
    78                 // Child wants to determine its own size.... find out how
    79                 // big it should be
    80                 resultSize = 0;
    81                 resultMode = MeasureSpec.UNSPECIFIED;
    82             }
    83             break;
    84         }
    85         return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
    86     }
    复制代码

    三种模式的判断,进行不同的赋值!这些值会传递给子View,告诉它们父View的大小。

     

    四、布局参数LayoutParams

    复制代码
      1 /**
      2      * LayoutParams are used by views to tell their parents how they want to be
      3      * laid out. See
      4      * {@link android.R.styleable#ViewGroup_Layout ViewGroup Layout Attributes}
      5      * for a list of all child view attributes that this class supports.
      6      *
      7      * <p>
      8      * The base LayoutParams class just describes how big the view wants to be
      9      * for both width and height. For each dimension, it can specify one of:
     10      * <ul>
     11      * <li>FILL_PARENT (renamed MATCH_PARENT in API Level 8 and higher), which
     12      * means that the view wants to be as big as its parent (minus padding)
     13      * <li> WRAP_CONTENT, which means that the view wants to be just big enough
     14      * to enclose its content (plus padding)
     15      * <li> an exact number
     16      * </ul>
     17      * There are subclasses of LayoutParams for different subclasses of
     18      * ViewGroup. For example, AbsoluteLayout has its own subclass of
     19      * LayoutParams which adds an X and Y value.
     20      *
     21      * @attr ref android.R.styleable#ViewGroup_Layout_layout_height
     22      * @attr ref android.R.styleable#ViewGroup_Layout_layout_width
     23      */
     24     public static class LayoutParams {
     25         /**
     26          * Special value for the height or width requested by a View.
     27          * FILL_PARENT means that the view wants to be as big as its parent,
     28          * minus the parent's padding, if any. This value is deprecated
     29          * starting in API Level 8 and replaced by {@link #MATCH_PARENT}.
     30          */
     31         @SuppressWarnings({"UnusedDeclaration"})
     32         @Deprecated
     33         public static final int FILL_PARENT = -1;
     34 
     35         /**
     36          * Special value for the height or width requested by a View.
     37          * MATCH_PARENT means that the view wants to be as big as its parent,
     38          * minus the parent's padding, if any. Introduced in API Level 8.
     39          */
     40         public static final int MATCH_PARENT = -1;
     41 
     42         /**
     43          * Special value for the height or width requested by a View.
     44          * WRAP_CONTENT means that the view wants to be just large enough to fit
     45          * its own internal content, taking its own padding into account.
     46          */
     47         public static final int WRAP_CONTENT = -2;
     48 
     49         /**
     50          * Information about how wide the view wants to be. Can be one of the
     51          * constants FILL_PARENT (replaced by MATCH_PARENT ,
     52          * in API Level 8) or WRAP_CONTENT. or an exact size.
     53          */
     54         @ViewDebug.ExportedProperty(mapping = {
     55             @ViewDebug.IntToString(from = MATCH_PARENT, to = "MATCH_PARENT"),
     56             @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
     57         })
     58         public int width;
     59 
     60         /**
     61          * Information about how tall the view wants to be. Can be one of the
     62          * constants FILL_PARENT (replaced by MATCH_PARENT ,
     63          * in API Level 8) or WRAP_CONTENT. or an exact size.
     64          */
     65         @ViewDebug.ExportedProperty(mapping = {
     66             @ViewDebug.IntToString(from = MATCH_PARENT, to = "MATCH_PARENT"),
     67             @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT")
     68         })
     69         public int height;
     70 
     71         /**
     72          * Used to animate layouts.
     73          */
     74         public LayoutAnimationController.AnimationParameters layoutAnimationParameters;
     75 
     76         /**
     77          * Creates a new set of layout parameters. The values are extracted from
     78          * the supplied attributes set and context. The XML attributes mapped
     79          * to this set of layout parameters are:
     80          *
     81          * <ul>
     82          *   <li><code>layout_width</code>: the width, either an exact value,
     83          *   {@link #WRAP_CONTENT}, or {@link #FILL_PARENT} (replaced by
     84          *   {@link #MATCH_PARENT} in API Level 8)</li>
     85          *   <li><code>layout_height</code>: the height, either an exact value,
     86          *   {@link #WRAP_CONTENT}, or {@link #FILL_PARENT} (replaced by
     87          *   {@link #MATCH_PARENT} in API Level 8)</li>
     88          * </ul>
     89          *
     90          * @param c the application environment
     91          * @param attrs the set of attributes from which to extract the layout
     92          *              parameters' values
     93          */
     94         public LayoutParams(Context c, AttributeSet attrs) {
     95             TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
     96             setBaseAttributes(a,
     97                     R.styleable.ViewGroup_Layout_layout_width,
     98                     R.styleable.ViewGroup_Layout_layout_height);
     99             a.recycle();
    100         }
    101 
    102         /**
    103          * Creates a new set of layout parameters with the specified width
    104          * and height.
    105          *
    106          * @param width the width, either {@link #WRAP_CONTENT},
    107          *        {@link #FILL_PARENT} (replaced by {@link #MATCH_PARENT} in
    108          *        API Level 8), or a fixed size in pixels
    109          * @param height the height, either {@link #WRAP_CONTENT},
    110          *        {@link #FILL_PARENT} (replaced by {@link #MATCH_PARENT} in
    111          *        API Level 8), or a fixed size in pixels
    112          */
    113         public LayoutParams(int width, int height) {
    114             this.width = width;
    115             this.height = height;
    116         }
    117 
    118         /**
    119          * Copy constructor. Clones the width and height values of the source.
    120          *
    121          * @param source The layout params to copy from.
    122          */
    123         public LayoutParams(LayoutParams source) {
    124             this.width = source.width;
    125             this.height = source.height;
    126         }
    127 
    128         /**
    129          * Used internally by MarginLayoutParams.
    130          * @hide
    131          */
    132         LayoutParams() {
    133         }
    134 
    135         /**
    136          * Extracts the layout parameters from the supplied attributes.
    137          *
    138          * @param a the style attributes to extract the parameters from
    139          * @param widthAttr the identifier of the width attribute
    140          * @param heightAttr the identifier of the height attribute
    141          */
    142         protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
    143             width = a.getLayoutDimension(widthAttr, "layout_width");
    144             height = a.getLayoutDimension(heightAttr, "layout_height");
    145         }
    146 
    147         /**
    148          * Returns a String representation of this set of layout parameters.
    149          *
    150          * @param output the String to prepend to the internal representation
    151          * @return a String with the following format: output +
    152          *         "ViewGroup.LayoutParams={ width=WIDTH, height=HEIGHT }"
    153          *
    154          * @hide
    155          */
    156         public String debug(String output) {
    157             return output + "ViewGroup.LayoutParams={ width="
    158                     + sizeToString(width) + ", height=" + sizeToString(height) + " }";
    159         }
    160 
    161         /**
    162          * Converts the specified size to a readable String.
    163          *
    164          * @param size the size to convert
    165          * @return a String instance representing the supplied size
    166          *
    167          * @hide
    168          */
    169         protected static String sizeToString(int size) {
    170             if (size == WRAP_CONTENT) {
    171                 return "wrap-content";
    172             }
    173             if (size == MATCH_PARENT) {
    174                 return "match-parent";
    175             }
    176             return String.valueOf(size);
    177         }
    178     }
    复制代码

    注解:

    1)从API-LEVEL8开始,FILL_PARENT被MATCH_PARENT代替;

    2)留下一个疑问:这些布局参数到底是如何变成布局尺寸的?

  • 相关阅读:
    小程序模板template问题记录
    datepicker 组件 的坑
    js实现 throttle 和 debounce
    vuex简单使用
    webpack 打包图片 缺失问题
    invalid prop `current` of type `string` supplied to `pagination`, expected `
    HTML5自定义属性之data-*
    vue组件传值方式介绍
    解决github.com 打不开问题
    git密令使用
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3581521.html
Copyright © 2020-2023  润新知