自定义控件ViewGroup视频里流式布局在Layout里面放子类View 的时候,子类只能显示一行,打Log运行出来currentBottom已经自加了
这是MainActivity java代码
package com.yucha.customcontrolactivity;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import com.yucha.customcontrolactivity.flows.FlowLayout;
import com.yucha.customcontrolactivity.inputnumber.InputNumberView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity
{
    private static final String TAG ="MainActivity" ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FlowLayout flowLayout = this.findViewById(R.id.flow_layout);
        List<String> data =new ArrayList<>();
        data.add("键盘");
        data.add("显示器");
        data.add("鼠标");
        data.add("ipad");
        data.add("手机");
        data.add("键盘");
        data.add("春夏秋冬");
        data.add("迪丽热巴");
        data.add("古力娜扎");
        data.add("马尔扎哈");
        data.add("春夏秋冬超值款");
        data.add("春夏秋冬超值款");
        data.add("春夏秋冬超值款");
        data.add("春夏秋冬超值款");
        data.add("春夏秋冬超值款");
        data.add("迪丽热巴");
        data.add("古力娜扎");
        flowLayout.setTextList(data);
    }
这是FlowLayout.java代码
package com.yucha.customcontrolactivity.flows;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.yucha.customcontrolactivity.R;
import java.util.ArrayList;
import java.util.List;
public class FlowLayout extends ViewGroup {
    private static final String TAG = "FlowLayout";
    public static int DEFAULT_LINES = 3;
    public static int DEFAULT_HORIZONTAL_MARGIN = 5;//后面需要转单位  现在是px 不适配
    public static int DEFAULT_VERTICAL_MARGIN = 5;//后面需要转单位  现在是px 不适配
    public static int DEFAULT_BORDER_RADIUS = 5;//后面需要转单位  现在是px 不适配
    public static int DEFAULT_TEXT_MAX_LENGTH = 20;//后面需要转单位  现在是px 不适配
    private int mMaxLines;
    private float mHorizontalMargin;
    private float mVerticalMargin;
    private int mMaxLengthText;
    private int mColorText;
    private int mColorBoarder;
    private float mRadiusBoarder;
    private List<String> mData = new ArrayList<>();
    public FlowLayout(Context context) {
        this(context, null);
    }
    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //
        initAttrs(context, attrs);
    }
    public void setTextList(List<String> data) {
        this.mData.clear();
        this.mData.addAll(data);
        //根据数据创建子View 并且添加进来
        setUpChildren();
    }
    private void setUpChildren() {
        //清空原有内容
        removeAllViews();
        //添加子View
        for (String datum : mData) {
            TextView textView = new TextView(getContext());
            textView.setText(datum);
            //设置textView的属性
            addView(textView);
        }
    }
    private List<List<View>> mLines = new ArrayList<>();
    /**
     * 测量
     * 这两个值来自父控件 包含值和模式
     * int类型---->4个字节 ---> 4*8 bit  32位
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int parentWidthSize = MeasureSpec.getSize(widthMeasureSpec);
        int parentHeightSize = MeasureSpec.getSize(heightMeasureSpec);
        int childCount = getChildCount();
        if (childCount == 0) {
            return;
        }
        //先清空
        mLines.clear();
        //添加默认行
        List<View> line = new ArrayList<>();
        mLines.add(line);
        int childWidthSpec = MeasureSpec.makeMeasureSpec(parentWidthSize, MeasureSpec.AT_MOST);
        int childHeightSpec = MeasureSpec.makeMeasureSpec(parentHeightSize, MeasureSpec.AT_MOST);
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() != VISIBLE) {
                continue;
            }
            //测量孩子
            measureChild(child, childWidthSpec, childHeightSpec);
            if (line.size() == 0) {
                //可以添加
                line.add(child);
            } else {
                //判断是否可以添加
                boolean canBeAdd = checkChildCanBEAdd(line, child, parentWidthSize);
                if (canBeAdd) {
                    line.add(child);
                } else {
                    line = new ArrayList<>();
                    line.add(child);
                    Log.d(TAG,"canBeAdd--->"+canBeAdd);
                }
            }
        }
        //根据尺寸计算所有行高
        View child = getChildAt(0);
        int childHeight = child.getMeasuredHeight();
        int parentHeightTargetSize = childHeight * mLines.size();
        setMeasuredDimension(parentWidthSize, parentHeightTargetSize);
    }
    private boolean checkChildCanBEAdd(List<View> line, View child, int parentWidthSize) {
        int measuredWidth = child.getMeasuredWidth();
        int totalWidth = 0;
        for (View view : line) {
            totalWidth += view.getMeasuredWidth();
        }
        totalWidth += measuredWidth;
        //如果超出限制宽度,则不可以再添加
        // 否则可以添加
        return totalWidth <= parentWidthSize;
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        View firstChild = getChildAt(0);
        int currentLeft = 0;
        int currentRight = 0;
        int currentTop = 0;
        int currentBottom = firstChild.getMeasuredHeight();
        Log.d(TAG,"currentBottom--->"+currentBottom);
        for (List<View> line : mLines) {
            for (View view : line) {
                //布局每一行
                int width = view.getMeasuredWidth();
                int height = view.getMeasuredHeight();
                currentRight += width;
                view.layout(currentLeft, currentTop, currentRight, currentBottom);
                currentLeft = currentRight ;
            }
            currentLeft =0;
            currentRight = 0;
            currentTop += firstChild.getMeasuredHeight();
            currentBottom += firstChild.getMeasuredHeight();
            Log.d(TAG,"currentBottom--->" + currentBottom);
        }
    }
    public int getMaxLines() {
        return mMaxLines;
    }
    public void setMaxLines(int maxLines) {
        mMaxLines = maxLines;
    }
    public float getHorizontalMargin() {
        return mHorizontalMargin;
    }
    public void setHorizontalMargin(float horizontalMargin) {
        mHorizontalMargin = horizontalMargin;
    }
    public float getVerticalMargin() {
        return mVerticalMargin;
    }
    public void setVerticalMargin(float verticalMargin) {
        mVerticalMargin = verticalMargin;
    }
    public int getMaxLengthText() {
        return mMaxLengthText;
    }
    public void setMaxLengthText(int maxLengthText) {
        mMaxLengthText = maxLengthText;
    }
    public int getColorText() {
        return mColorText;
    }
    public void setColorText(int colorText) {
        mColorText = colorText;
    }
    public int getColorBoarder() {
        return mColorBoarder;
    }
    public void setColorBoarder(int colorBoarder) {
        mColorBoarder = colorBoarder;
    }
    public float getRadiusBoarder() {
        return mRadiusBoarder;
    }
    public void setRadiusBoarder(float radiusBoarder) {
        mRadiusBoarder = radiusBoarder;
    }
    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
        mMaxLines = a.getInt(R.styleable.InputNumberView_max, DEFAULT_LINES);
        mHorizontalMargin = a.getDimension(R.styleable.FlowLayout_itemHorizontalMargin, DEFAULT_HORIZONTAL_MARGIN);
        mVerticalMargin = a.getDimension(R.styleable.FlowLayout_itemVerticalMargin, DEFAULT_VERTICAL_MARGIN);
        mMaxLengthText = a.getInt(R.styleable.FlowLayout_textMaxLength, DEFAULT_TEXT_MAX_LENGTH);
        mColorText = a.getColor(R.styleable.FlowLayout_textColor, getResources().getColor(R.color.text_grey));
        mColorBoarder = a.getColor(R.styleable.FlowLayout_borderColor, getResources().getColor(R.color.text_grey));
        mRadiusBoarder = a.getDimension(R.styleable.FlowLayout_borderRadius, DEFAULT_BORDER_RADIUS);
        Log.d(TAG, "mMaxLines----->" + mMaxLines);
        Log.d(TAG, "mHorizontalMargin----->" + mHorizontalMargin);
        a.recycle();
    }
}
这是UI布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:sob ='http://schemas.android.com/apk/res-auto'
    android:layout_width="match_parent"
    android:background="#ffffff"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <com.yucha.customcontrolactivity.flows.FlowLayout
        android:layout_width="match_parent"
        android:id="@+id/flow_layout"
        android:layout_height="match_parent">
    </com.yucha.customcontrolactivity.flows.FlowLayout>
</LinearLayout>
这是Logcat
2021-01-01 20:50:13.679 6566-6566/? I/controlactivit: Not late-enabling -Xcheck:jni (already on)
2021-01-01 20:50:13.699 6566-6566/? I/controlactivit: Unquickening 12 vdex files!
2021-01-01 20:50:13.700 6566-6566/? W/controlactivit: Unexpected CPU variant for X86 using defaults: x86
2021-01-01 20:50:13.937 6566-6566/com.yucha.customcontrolactivity D/NetworkSecurityConfig: No Network Security Config specified, using platform default
2021-01-01 20:50:13.938 6566-6566/com.yucha.customcontrolactivity D/NetworkSecurityConfig: No Network Security Config specified, using platform default
2021-01-01 20:50:14.053 6566-6605/com.yucha.customcontrolactivity D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
2021-01-01 20:50:14.056 6566-6605/com.yucha.customcontrolactivity D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
2021-01-01 20:50:14.154 6566-6605/com.yucha.customcontrolactivity D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
2021-01-01 20:50:14.390 6566-6566/com.yucha.customcontrolactivity W/controlactivit: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
2021-01-01 20:50:14.391 6566-6566/com.yucha.customcontrolactivity W/controlactivit: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
2021-01-01 20:50:14.419 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: mMaxLines----->3
2021-01-01 20:50:14.419 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: mHorizontalMargin----->5.0
2021-01-01 20:50:14.485 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: canBeAdd--->false
2021-01-01 20:50:14.485 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: canBeAdd--->false
2021-01-01 20:50:14.501 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: canBeAdd--->false
2021-01-01 20:50:14.501 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: canBeAdd--->false
2021-01-01 20:50:14.502 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: currentBottom--->51
2021-01-01 20:50:14.503 6566-6566/com.yucha.customcontrolactivity D/FlowLayout: currentBottom--->102
2021-01-01 20:50:14.505 6566-6600/com.yucha.customcontrolactivity D/HostConnection: HostConnection::get() New Host Connection established 0xf5f278b0, tid 6600
2021-01-01 20:50:14.511 6566-6600/com.yucha.customcontrolactivity D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0 
2021-01-01 20:50:14.513 6566-6600/com.yucha.customcontrolactivity W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
2021-01-01 20:50:14.531 6566-6600/com.yucha.customcontrolactivity D/EGL_emulation: eglCreateContext: 0xf5f26b20: maj 3 min 0 rcv 3
2021-01-01 20:50:14.563 6566-6600/com.yucha.customcontrolactivity D/EGL_emulation: eglMakeCurrent: 0xf5f26b20: ver 3 0 (tinfo 0xf62765b0) (first time)
2021-01-01 20:50:14.592 6566-6600/com.yucha.customcontrolactivity I/Gralloc4: mapper 4.x is not supported
2021-01-01 20:50:14.593 6566-6600/com.yucha.customcontrolactivity D/HostConnection: createUnique: call
2021-01-01 20:50:14.594 6566-6600/com.yucha.customcontrolactivity D/HostConnection: HostConnection::get() New Host Connection established 0xf5f265e0, tid 6600
2021-01-01 20:50:14.594 6566-6600/com.yucha.customcontrolactivity D/goldfish-address-space: allocate: Ask for block of size 0x100
2021-01-01 20:50:14.595 6566-6600/com.yucha.customcontrolactivity D/goldfish-address-space: allocate: ioctl allocate returned offset 0x3fc5be000 size 0x2000
2021-01-01 20:50:14.618 6566-6600/com.yucha.customcontrolactivity D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0
老师我发现错误了,测量有一行代码写错了
眼睛找瞎了。
对于自定义ViewGroup来说,重点是两个。一个是测量,一个是布局。
你看到的现象是只有一行文字显示了。
要么没有测量够,要么就是布局不对。
布局有没有自动换行呢?从代码上看是有的
currentTop += firstChild.getMeasuredHeight();
currentBottom += firstChild.getMeasuredHeight();
不熟悉的话,这些也log出来。
那么是不是行数不对呢?是不是加一些log可以判断出来呢?
如果行数不对,是不是测量又不对呢?
一步一步逆推回去。
附上我的运行实际效果