文章目的:实现流式布局的效果,明白view的绘制流程
运行软件和环境:
- android Studio 3.5.1
- jdk1.8
效果图
11.jpg自定义viewgroup
自定义viewgroup对子view进行测量和布局
代码
/**
* author : Luuuzi
* e-mail : wang1143303@163.com
* date : 2020/2/26 0026 11:10
* desc : 自定义流式布局
*/
public class FlowLayout extends ViewGroup {
private String tag = getClass().getSimpleName();
private float dashWDefine = 0;//子view默认宽间距
private float dashHDefine = 0;//子view默认高间距
private ArrayList<ArrayList<View>> viewLines = null;
private ArrayList<Integer> viewHs = null;
public FlowLayout(Context context) {
super(context);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private void initMeasure() {
if (viewLines == null) {
viewLines = new ArrayList<>();
} else {
viewLines.clear();
}
if (viewHs == null) {
viewHs = new ArrayList<>();
} else {
viewHs.clear();
}
dashWDefine = 20;
dashHDefine = 30;
}
/**
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@SuppressLint("DrawAllocation")
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.i(tag, "onMeasure:");
initMeasure();
int pWMode = MeasureSpec.getMode(widthMeasureSpec);
int pHMode = MeasureSpec.getMode(heightMeasureSpec);
int pWSize = MeasureSpec.getSize(widthMeasureSpec);
int pHSize = MeasureSpec.getSize(heightMeasureSpec);
int currentUsedW = getPaddingLeft() + getPaddingRight();//记录已经用掉的宽度
//测量子view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childAt = getChildAt(i);
LayoutParams childLp = childAt.getLayoutParams();
int childWMS = getChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight(), childLp.width);
int childHMS = getChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom(), childLp.height);
childAt.measure(childWMS, childHMS);
//测量摆放空间(将子view 分行存储)
if (viewLines.isEmpty() || currentUsedW + childAt.getMeasuredWidth() + dashWDefine > pWSize) {//新的一行
ArrayList<View> views = new ArrayList<>();
views.add(childAt);
viewLines.add(views);
viewHs.add(childAt.getMeasuredHeight());//存高度
currentUsedW = getPaddingLeft() + getPaddingRight() + childAt.getMeasuredWidth() + (int) dashWDefine;
} else {//同一行
viewLines.get(viewLines.size() - 1).add(childAt);
//存一行中的最大高度
viewHs.set(viewHs.size() - 1, viewHs.get(viewHs.size() - 1) > childAt.getMeasuredHeight() ? viewHs.get(viewHs.size() - 1) : childAt.getMeasuredHeight());
currentUsedW += childAt.getMeasuredWidth() + dashWDefine;
}
}
//测量自己
int meW;
int meH;
// if (pWMode == MeasureSpec.EXACTLY) {
// meW = pWSize;
// } else {
meW = getCurrentMaxLineW();
// }
// if (pHMode == MeasureSpec.EXACTLY) {
// meH = pHSize;
// } else {
meH = getcountChildHeight();
// }
setMeasuredDimension(meW, meH);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (viewLines == null || viewHs == null) {
return;
}
int curTop = getPaddingTop();//view布局所对应的top坐标
for (int i = 0; i < viewHs.size(); i++) {//一行一行开始摆放
int curLeft = getPaddingLeft();//view布局所对应的left坐标
curTop += i == 0 ? 0 : viewHs.get(i - 1) + dashHDefine;
ArrayList<View> views = viewLines.get(i);
for (int j = 0; j < views.size(); j++) {//对每行子view进行布局
View child = views.get(j);
child.layout(curLeft, curTop, curLeft + child.getMeasuredWidth(), curTop + child.getMeasuredHeight());
curLeft += child.getMeasuredWidth() + dashWDefine;
}
}
}
// 获取所有行的最大宽度
private int getCurrentMaxLineW() {
if (viewLines.isEmpty()) {
return 0;
} else {
int max = 0;
for (int i = 0; i < viewLines.size(); i++) {
ArrayList<View> views = viewLines.get(i);
int w = 0;
for (int j = 0; j < views.size(); j++) {
w += views.get(j).getMeasuredWidth() + (int) dashWDefine;
}
max = Math.max(w, max);
}
return max + getPaddingLeft() + getPaddingRight();
}
}
private int getcountChildHeight() {
if (viewHs.isEmpty()) {
return 0;
} else {
int h = 0;
for (int i = 0; i < viewHs.size(); i++) {
h += viewHs.get(i) + dashHDefine;
}
return h + getPaddingTop() + getPaddingBottom();
}
}
}
使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="#fff"
android:orientation="vertical"
tools:context=".MainActivity">
<com.luuuzi.demo003.widget.FlowLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="苹果7手机壳"
android:textColor="#f00"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="道德经"
android:textColor="#f00"
android:textSize="16sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="美甲套装初学者家用"
android:textColor="#f00"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="阿玛尼"
android:textColor="#f00"
android:textSize="25sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="破壁机加热全自动"
android:textColor="#f00"
android:textSize="18sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="华为mate30"
android:textColor="#f00"
android:textSize="12sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="全自动洗衣机"
android:textColor="#f00"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="i5-9400f"
android:textColor="#f00"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="巨坑"
android:textColor="#f00"
android:textSize="13sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="安卓插件化"
android:textColor="#f00"
android:textSize="17sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="小米10"
android:textColor="#f00"
android:textSize="15sp" />
</com.luuuzi.demo003.widget.FlowLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="搜索历史"
android:gravity="center_vertical"/>
<com.luuuzi.demo003.widget.FlowLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="iphone XS"
android:textColor="#f00"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="老子"
android:textColor="#f00"
android:textSize="16sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="美甲套装初学者家用"
android:textColor="#f00"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="雅诗兰黛"
android:textColor="#f00"
android:textSize="25sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="九阳豆浆"
android:textColor="#f00"
android:textSize="18sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="华为mate30"
android:textColor="#f00"
android:textSize="12sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="全自动洗衣机"
android:textColor="#f00"
android:textSize="10sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="i5-9400f"
android:textColor="#f00"
android:textSize="15sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="巨坑"
android:textColor="#f00"
android:textSize="13sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="戴尔电脑"
android:textColor="#f00"
android:textSize="17sp" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_key"
android:padding="10dp"
android:text="小米10pro"
android:textColor="#f00"
android:textSize="15sp" />
</com.luuuzi.demo003.widget.FlowLayout>
</LinearLayout>
完成
项目地址:Demo003
网友评论