privatestaticclassDependencyGraph { ... /** * Adds a view to the graph. * * @param view The view to be added as a node to the graph. */ voidadd(View view) { //因为是图 根据view生成一个节点 finalintid= view.getId(); finalNodenode= Node.acquire(view); //如果是有效的id 则将该节点添加到List中 if (id != View.NO_ID) { mKeyNodes.put(id, node); }
mNodes.add(node); }
/** * Builds a sorted list of views. The sorting order depends on the dependencies * between the view. For instance, if view C needs view A to be processed first * and view A needs view B to be processed first, the dependency graph * is: B -> A -> C. The sorted array will contain views B, A and C in this order. * * @param sorted The sorted list of views. The length of this array must * be equal to getChildCount(). * @param rules The list of rules to take into account. */ voidgetSortedViews(View[] sorted, int... rules) { //当前View找不到其它的可依赖的View时 作为root节点 final ArrayDeque<Node> roots = findRoots(rules); intindex=0;
final ArrayMap<Node, DependencyGraph> dependents = node.dependents; //dependents 依赖该node的node (A C依赖B 则B的dependents中存A C) finalintcount= dependents.size(); //遍历所有依赖自己的node for (inti=0; i < count; i++) { finalNodedependent= dependents.keyAt(i); //dependencies 是被依赖的的node的规则和node(A 依赖 B D 则dependencies存有B D ) final SparseArray<Node> dependencies = dependent.dependencies;
/** * Finds the roots of the graph. A root is a node with no dependency and * with [0..n] dependents. * * @param rulesFilter The list of rules to consider when building the * dependencies * * @return A list of node, each being a root of the graph */ private ArrayDeque<Node> findRoots(int[] rulesFilter) { //keyNodes为nodelist final SparseArray<Node> keyNodes = mKeyNodes; final ArrayList<Node> nodes = mNodes; finalintcount= nodes.size();
//初始化依赖该node的node和该node依赖的node相关参数 for (inti=0; i < count; i++) { finalNodenode= nodes.get(i); node.dependents.clear(); node.dependencies.clear(); }
//遍历所有node 存入当前view和他所依赖的关系 for (inti=0; i < count; i++) { finalNodenode= nodes.get(i);
/** * Get a measure spec that accounts for all of the constraints on this view. * This includes size constraints imposed by the RelativeLayout as well as * the View's desired dimension. * * @param childStart The left or top field of the child's layout params * @param childEnd The right or bottom field of the child's layout params * @param childSize The child's desired size (the width or height field of * the child's layout params) * @param startMargin The left or top margin * @param endMargin The right or bottom margin * @param startPadding mPaddingLeft or mPaddingTop * @param endPadding mPaddingRight or mPaddingBottom * @param mySize The width or height of this view (the RelativeLayout) * @return MeasureSpec for the child */ privateintgetChildMeasureSpec(int childStart, int childEnd, int childSize, int startMargin, int endMargin, int startPadding, int endPadding, int mySize) { intchildSpecMode=0; intchildSpecSize=0;
if (maxAvailable >= 0) { // We have a maximum size in this dimension. childSpecSize = Math.min(maxAvailable, childSize); } else { // We can grow in this dimension. childSpecSize = childSize; } } elseif (childSize == LayoutParams.MATCH_PARENT) { //如果子View是match模式 参照isUnspecified设置相关 childSpecMode = isUnspecified ? MeasureSpec.UNSPECIFIED : MeasureSpec.EXACTLY; childSpecSize = Math.max(0, maxAvailable); } elseif (childSize == LayoutParams.WRAP_CONTENT) { //在wrap进行设置 if (maxAvailable >= 0) { // We have a maximum size in this dimension. childSpecMode = MeasureSpec.AT_MOST; childSpecSize = maxAvailable; } else { // We can grow in this dimension. Child can be as big as it // wants. childSpecMode = MeasureSpec.UNSPECIFIED; childSpecSize = 0; } } }
// Use the top-start-most laid out view as the baseline. RTL offsets are // applied later, so we can use the left-most edge as the starting edge. ViewbaselineView=null; LayoutParamsbaselineParams=null; for (inti=0; i < count; i++) { finalViewchild= views[i]; if (child.getVisibility() != GONE) { finalLayoutParamschildParams= (LayoutParams) child.getLayoutParams(); if (baselineView == null || baselineParams == null || compareLayoutPosition(childParams, baselineParams) < 0) { baselineView = child; baselineParams = childParams; } } } mBaselineView = baselineView;
//如果是RTL(右到左显示)则再次修改 if (isLayoutRtl()) { finalintoffsetWidth= myWidth - width; for (inti=0; i < count; i++) { finalViewchild= views[i]; if (child.getVisibility() != GONE) { finalLayoutParamsparams= (LayoutParams) child.getLayoutParams(); params.mLeft -= offsetWidth; params.mRight -= offsetWidth; } } }
简单总结
RelativeLayout更加关注子View的left right top bottom值 并且优先级高于width和height
RelativeLayout的layout过程
对于RelativeLayout来的 layout过程更多的根据子View的left right top bottom值来设定位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14
protectedvoidonLayout(boolean changed, int l, int t, int r, int b) { // The layout has actually already been performed and the positions // cached. Apply the cached values to the children. finalintcount= getChildCount();
for (inti=0; i < count; i++) { Viewchild= getChildAt(i); if (child.getVisibility() != GONE) { RelativeLayout.LayoutParamsst= (RelativeLayout.LayoutParams) child.getLayoutParams(); child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom); } } }