安卓TagLayout标签布局实现

  • Post author:
  • Post category:其他


在这里插入图片描述

最近要使用一个这样的标签流式布局,网上很多资源,自己试着自定义了一下效果图如上。

实现逻辑分析:

1.这是一个自定义的TagLayout肯定要继承自ViewGroup。

2.要自动换行,那容器的宽和高是不固定的需要根据子View的多少的宽高来确定自己的宽高。

3.继承ViewGroup肯定是要实现它的OnLayout去摆放子View的位置。

大概逻辑就是以上三部,可以总结出来需要重写ViewGroup的onMeasure()和onLayout()方法。

先重写onMeasure()方法:

1.获取子View的数量。

2.for循环测量每个子View的宽高。

3.记录每个子View的宽度进行累加,当宽度大于一行的宽度时,高度需要加上子View的高度。

4.记录累加的宽高值设置容器的宽高。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //记录值,靠这个值判断是否宽度不够了
        int width = 0;
        myWidth = MeasureSpec.getSize(widthMeasureSpec);
        myHeight = 0;
        //1.获取布局中有多少个子View
        int childCount = getChildCount();
        int maxHeight = 0;
        for (int i = 0; i < childCount; i++) {
            //获取每个子View
            View childView = getChildAt(i);
            //2.测量每个子View
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
            //3.记录每个子View的宽度进行累加,当宽度大于一行的宽度时,高度需要加上子View的高度。
            if (width + childView.getMeasuredWidth() > myWidth) {
                myHeight += childView.getMeasuredHeight();
                width = 0;
            } else {
                width += childView.getMeasuredWidth();
                maxHeight = Math.max(childView.getMeasuredHeight(), myHeight);
            }
        }
        myHeight += maxHeight;
        //4.记录累加的宽高值设置容器的宽高。
        setMeasuredDimension(myWidth, myHeight);
    }

在重写onLayout()方法:

1.获取容器中的子View数量。

2.for循环控制每个子View的摆放位置。

3.摆放每个子View。

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int w = 0;
        int left = 0;
        int top = 0;
        //1.获取布局中有多少个子View
        int childCount = getChildCount();
        //2.for循环控制每个子View的摆放位置
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            int MeasuredWidth = childView.getMeasuredWidth();
            int MeasuredHeight = childView.getMeasuredHeight();
            if (w + MeasuredWidth > myWidth) {//需要换行
                left = 0;
                top += MeasuredHeight;
                w = 0;
            }
            //3.摆放每个子View
            childView.layout(left, top, left + MeasuredWidth, top + MeasuredHeight);
            left += MeasuredWidth;
            w += MeasuredWidth;
        }
    }

关键逻辑都在这两个方法中。

以下就是全部代码:

package com.zg.viewdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

public class TagLayout extends ViewGroup {
    int myWidth;
    int myHeight;

    public TagLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //记录值,靠这个值判断是否宽度不够了
        int width = 0;
        myWidth = MeasureSpec.getSize(widthMeasureSpec);
        myHeight = 0;
        //1.获取布局中有多少个子View
        int childCount = getChildCount();
        int maxHeight = 0;
        for (int i = 0; i < childCount; i++) {
            //获取每个子View
            View childView = getChildAt(i);
            //2.测量每个子View
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
            //3.记录每个子View的宽度进行累加,当宽度大于一行的宽度时,高度需要加上子View的高度。
            if (width + childView.getMeasuredWidth() > myWidth) {
                myHeight += childView.getMeasuredHeight();
                width = 0;
            } else {
                width += childView.getMeasuredWidth();
                maxHeight = Math.max(childView.getMeasuredHeight(), myHeight);
            }
        }
        myHeight += maxHeight;
        //4.记录累加的宽高值设置容器的宽高。
        setMeasuredDimension(myWidth, myHeight);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int w = 0;
        int left = 0;
        int top = 0;
        //1.获取布局中有多少个子View
        int childCount = getChildCount();
        //2.for循环控制每个子View的摆放位置
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            int MeasuredWidth = childView.getMeasuredWidth();
            int MeasuredHeight = childView.getMeasuredHeight();
            if (w + MeasuredWidth > myWidth) {//需要换行
                left = 0;
                top += MeasuredHeight;
                w = 0;
            }
            //3.摆放每个子View
            childView.layout(left, top, left + MeasuredWidth, top + MeasuredHeight);
            left += MeasuredWidth;
            w += MeasuredWidth;
        }
    }
}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <com.zg.viewdemo.TagLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="1.asjdklasjdklasj" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="2.哈哈哈是" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="3.5846546546546947564564654564" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.哈哈哈是哈哈哈是哈哈哈是哈哈哈是" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="5.584654654654564" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="6.哈哈是" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="7.58465454564" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="8.哈哈是" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="9.5846546546554564" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.卡机三大神快鹿鼎记卢萨卡经典款拉萨角度" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.dsadssdasadasdadsa" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.of降温" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.阿水大神大神" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.啊" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="4.萨达四大大神大神的的顶顶顶顶顶" />
        </com.zg.viewdemo.TagLayout>

    </LinearLayout>
</RelativeLayout>



版权声明:本文为qq77485042原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。