分析v7中的LinearLayoutCompat类

   LinearLayoutCompat是个很神奇的类,在我们写布局的时候我们经常用用view这个空间来画一条线,导致布局中有很多这样的无用布局,但是不写又不符合界面设置规范,用listview来写,条目很少,没必要,各种纠结。让我们来认识下LinearLayoutCompat这个类吧,原生的,带你飞起来,你会有相见恨晚的感觉。

效果图:
这里写图片描述

** <android.support.v7.widget.LinearLayoutCompat
        android:layout_width="match_parent"
       android:divider="@android:drawable/divider_horizontal_bright"
        android:showDividers="middle"
        android:orientation="vertical"
        android:layout_height="match_parent">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="listPop"
            android:text="listPop"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
    </android.support.v7.widget.LinearLayoutCompat>**

好想LinearLayout也可以在4.0以上,具体没尝试;大家可以试试;直接用LinearLayout;不用着个v7兼容包的类。
————————————————-正式进入源码分析————————————
第一步我们打开v7包在android.support.v7.widget.LinearLayoutCompat中的源码(源码在哪,你能来看就不要问我了,对吧!!

然后,先看头部注释;这个很重用,一般这个注释都归纳了这个类的作用、用法等
A Layout that arranges its children in a single column or a single row. The direction of
the row can be set by calling {@link #setOrientation(int) setOrientation()}.
You can also specify gravity, which specifies the alignment of all the child elements by
calling {@link #setGravity(int) setGravity()} or specify that specific children
grow to fill up any remaining space in the layout by setting the weight member of
{@link LinearLayoutCompat.LayoutParams LinearLayoutCompat.LayoutParams}.
The default orientation is horizontal.
Also see {@link LinearLayoutCompat.LayoutParams} for layout attributes
这里主要讲的是这个类是一个布局,可以将其放置在一个单独列或一行中,可以设置方向,对齐方式等。。

我们在往下看:构造函数—实现3个函数,在最后一个构造函数中实现初始化;
在看看onDraw方法,这是这个类效果绘制的方法;

  @Override
    protected void onDraw(Canvas canvas) {
    //这里要设置mDivider要注意,不设置是是不会画后面的线的
        if (mDivider == null) {
            return;
        }
    //根据方向画线
        if (mOrientation == VERTICAL) {
            drawDividersVertical(canvas);
        } else {
            drawDividersHorizontal(canvas);
        }
    }
    //画垂直线
  void drawDividersVertical(Canvas canvas) {
      //拿全部的子控件数
        final int count = getVirtualChildCount();
        for (int i = 0; i < count; i++) {
        //具体的子控件
            final View child = getVirtualChildAt(i);
            if (child != null && child.getVisibility() != GONE) {
                if (hasDividerBeforeChildAt(i)) {
                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                    final int top = child.getTop() - lp.topMargin - mDividerHeight;
                    drawHorizontalDivider(canvas, top);
                }
            }
        }

        if (hasDividerBeforeChildAt(count)) {
            final View child = getLastNonGoneChild();
            int bottom = 0;
            if (child == null) {
                bottom = getHeight() - getPaddingBottom() - mDividerHeight;
            } else {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                bottom = child.getBottom() + lp.bottomMargin;
            }
            drawHorizontalDivider(canvas, bottom);
        }
    }
    //调用Drawable这个工具类来画图
  void drawHorizontalDivider(Canvas canvas, int top) {
  //在看这个类的时候,我们要注意一些方法:Drawable类最前面的注释;基本上你就能大体掌握这个类,下次我专门搞个详解;
        mDivider.setBounds(getPaddingLeft() + mDividerPadding, top,
                getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight);
        mDivider.draw(canvas);
    }
    //画横线
  void drawDividersHorizontal(Canvas canvas) {
        final int count = getVirtualChildCount();
        final boolean isLayoutRtl = ViewUtils.isLayoutRtl(this);
        for (int i = 0; i < count; i++) {
            final View child = getVirtualChildAt(i);

            if (child != null && child.getVisibility() != GONE) {
                //判断子控件位置 
                if (hasDividerBeforeChildAt(i)) {
                    final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                    final int position;
                    if (isLayoutRtl) {
                        position = child.getRight() + lp.rightMargin;
                    } else {
                        position = child.getLeft() - lp.leftMargin - mDividerWidth;
                    }
                    drawVerticalDivider(canvas, position);
                }
            }
        }

        if (hasDividerBeforeChildAt(count)) {
            final View child = getVirtualChildAt(count - 1);
            int position;
            if (child == null) {
                if (isLayoutRtl) {
                    position = getPaddingLeft();
                } else {
                    position = getWidth() - getPaddingRight() - mDividerWidth;
                }
            } else {
                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (isLayoutRtl) {
                    position = child.getLeft() - lp.leftMargin - mDividerWidth;
                } else {
                    position = child.getRight() + lp.rightMargin;
                }
            }
            drawVerticalDivider(canvas, position);
        }
    }
    //上面已经说了
    void drawVerticalDivider(Canvas canvas, int left) {
        mDivider.setBounds(left, getPaddingTop() + mDividerPadding,
                left + mDividerWidth, getHeight() - getPaddingBottom() - mDividerPadding);
        mDivider.draw(canvas);
    }
 /**
     * Determines where to position dividers between children.
     *(判断子控件位置;也就是我们在xml中(begin|end|middle|none}))
     * @param childIndex Index of child to check for preceding divider
     * @return true if there should be a divider before the child at childIndex
     * @hide Pending API consideration. Currently only used internally by the system.
     */
    protected boolean hasDividerBeforeChildAt(int childIndex) {
        if (childIndex == 0) {
            return (mShowDividers & SHOW_DIVIDER_BEGINNING) != 0;
        } else if (childIndex == getChildCount()) {
            return (mShowDividers & SHOW_DIVIDER_END) != 0;
        } else if ((mShowDividers & SHOW_DIVIDER_MIDDLE) != 0) {
            boolean hasVisibleViewBefore = false;
            for (int i = childIndex - 1; i >= 0; i--) {
                if (getChildAt(i).getVisibility() != GONE) {
                    hasVisibleViewBefore = true;
                    break;
                }
            }
            return hasVisibleViewBefore;
        }
        return false;
    }

好了,看了这么多的源码,你总改有所了解了吧

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值