imooc学习笔记——流式布局和热门标签

在看imooc打造Android中的流式布局和热门标签这个课程时,感觉没有什么太大难度,但是一练习就发现有很多问题会不断出现,于是就有了这个笔记…..

个人笔记,个人理解 , 如有错误欢迎指正

要想实现流式布局 Android中没有现成的控件,所以需要我们自己写,也就传说中的自定义View啦!

对自定义View的了解不是很多, 目前我的理解是

1、 继承View或者ViewGroup (或者其子类)
2、 根据需要重写其方法
3、 使用

其实这三点就是废话。。。。但也的确就是这样的=.=

继承

流式布局 应该都见过,它是要放控件的容器,所以不能继承View 必须继承ViewGroup或其子类
视频中继承的是ViewGroup 至于为什么不继承RelativeLayout、LinearLayout、FrameLayout 我也没有想太明白。。。。

继承后必须实现protected void onLayout(boolean changed, int l, int t, int r, int b) {} 和 几个构造器

onLayout 这个方法是设置子view的位置 ,那么设置位置的前提 是要知道要设置子view的大小吧
那么需要用到onMeasure方法, 这个是测量子View和自身的宽高
如果想要知道子View的一些参数那么得需要 子view.getLayoutParams这个方法,返回类型的是ViewGroup.LayoutParams
我们可能会需要子View的margin,然而能获取子ViewMargin 的是ViewGroup.MarginLayoutParams这个类,
所以我们子view的父容器(也就是我们自定义的ViewGroup)必须返回子View一个ViewGroup.MarginLayoutParams类型的LayoutParams,怎么返回呢
这个方法是在public LayoutParams generateLayoutParams(AttributeSet attrs) {}中返回的

OK,继承如下

public class MyGroupView extends ViewGroup {
    public MyGroupView(Context context) {
        this(context, null);
    }
    public MyGroupView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyGroupView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     super.onMeasure(widthMeasureSpec,heightMeasureSpec); 
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

    }
  @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return super.generateLayoutParams(attrs);
    }
 }

重写

1、重写generateLayoutParams,让其返回MarginLayoutParams类型,这样子View才可获取Margin

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

2、重写onMeasure,这样才可以知道ViewGroup应该绘制多大

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width_size = MeasureSpec.getSize(widthMeasureSpec);
        int height_size = MeasureSpec.getSize(heightMeasureSpec);
        int width_mode = MeasureSpec.getMode(widthMeasureSpec);
        int height_mode = MeasureSpec.getMode(heightMeasureSpec);
        int width = 0, height = 0, line_width = 0, line_height = 0;
        int mCount = getChildCount();
        int viewWidth = 0, viewHeight = 0;
        //遍历ChildView 获得 width 和height
        for (int i = 0; i < mCount; i++) {
            View view = getChildAt(i);
            measureChild(view, widthMeasureSpec, heightMeasureSpec);
            MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();

            viewWidth = params.leftMargin + params.rightMargin + view.getMeasuredWidth();
            viewHeight = params.topMargin + params.bottomMargin + view.getMeasuredHeight();

            if (line_width + viewWidth > width_size - getPaddingRight() - getPaddingLeft()) {//换行
                width = Math.max(width, line_width);//宽度为最宽的行宽
                height += line_height;//高度累加

                //清除以前的宽高
                line_width = viewWidth ;
                line_height = viewHeight;
            } else {//无需换行
                line_width += viewWidth;//累加
                line_height = Math.max(line_height, viewHeight);//高度为最高的行高
            }

            if (i == mCount - 1) {//最后一个控件
                width = Math.max(width, line_width);//宽度为最宽的行宽
                height += line_height;//高度累加
            }

        }

        setMeasuredDimension(//如果是EXACTLY设置原来大小,如果不是则设置计算后的大小
                width_mode == MeasureSpec.EXACTLY ? width_size : width + getPaddingRight() + getPaddingLeft(),//
                height_mode == MeasureSpec.EXACTLY ? height_size : height + getPaddingTop() + getPaddingBottom()//
        );

    }

3、重写onLayout,开始分配每个子View的位置

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int line_width = getPaddingLeft(), line_height = 0;
        int mCount = getChildCount();
        int left = 0, top = getPaddingTop();

        //遍历ChildView 
        for (int i = 0; i < mCount; i++) {
            View view = getChildAt(i);
        //获得子View属性
            MarginLayoutParams params = (MarginLayoutParams) view.getLayoutParams();
            int viewWidth = params.leftMargin + params.rightMargin + view.getMeasuredWidth();
            int viewHeight = params.topMargin + params.bottomMargin + view.getMeasuredHeight();

            if (line_width + viewWidth > getWidth() - getPaddingLeft()) {//换行
                left = getPaddingLeft();
                top += line_height;//高度累加
                view.layout(left + params.leftMargin, top + params.topMargin,
                        left + view.getMeasuredWidth() + params.rightMargin,
                        top + view.getMeasuredHeight() + params.bottomMargin);

                //清除宽高
                line_width = viewWidth + getPaddingLeft();
                line_height = viewHeight;

            } else {//无需换行
                left = line_width;
        //为
                view.layout(left + params.leftMargin, top + params.topMargin,
                        left + view.getMeasuredWidth() + params.rightMargin,
                        top + view.getMeasuredHeight() + params.bottomMargin);

                line_width += viewWidth;//累加行宽
                line_height = Math.max(line_height, viewHeight);//高度为最高的控件高度
            }
        }
    }

使用

使用方法很简单啦

就是在布局文件中添加进去就好了
<包名.自定义ViewGroup名>

比如我的就是这样
这里写图片描述

   <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <sunshine.myview.MyGroupView
        android:id="@+id/view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#f00"
        android:padding="20dp">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="New Button" />
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ccc">
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:background="#ca0"
                android:text="New Button" />
        </LinearLayout>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="111" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="111aa1a11111" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="111" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="111" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ccc"
            android:gravity="center"
            android:padding="10dp"
            android:text="aaaaaaaa" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="NNNNNNNNNNNNssssNNNNaaaaaaaaaaaaaaaaNNNaaaa" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="111" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Neon" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#cc0"
            android:gravity="center"
            android:padding="10dp"
            android:text="aaaa" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#ccc"
            android:gravity="center"
            android:padding="10dp"
            android:text="aaaaaaaaaaaaaaaaaaaaassaaaaassddddaa" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="New Button" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="New Button" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="NBonssss" />
    </sunshine.myview.MyGroupView>
</LinearLayout>

GitHub地址

少年,加油吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值