自定义控件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可以判断出来呢?
如果行数不对,是不是测量又不对呢?
一步一步逆推回去。
附上我的运行实际效果