1 效果
bitmap_screenshot_0(2).png
2.1 onMeasure() 指定宽高
2.1.1 for循环测量子View
2.1.2 根据子View计算和指定自己的布局
//2.1 onMeasure() 指定宽高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//避免onMeasure被调用多次的情况.
mChildViews.clear();
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = getPaddingTop() + getPaddingBottom();
//一行宽度
int lineWidth = getPaddingLeft();
// 2.1.1 for循环测量子View
//高度不一致,计算最大的高度.
int maxHeight = 0;
int childCount = getChildCount();
ArrayList<View> childViews = new ArrayList<>();
mChildViews.add(childViews);
for (int i = 0; i < childCount; i++) {
//获取子View
View childView = getChildAt(i);
// 这段话执行之后就可以获取子View的宽高,因为会调用子View的onMeasure
measureChild(childView, widthMeasureSpec, heightMeasureSpec);
// margin值 ViewGroup.LayoutParams 没有 就用系统的MarginLayoutParams
// 想想 LinearLayout为什么有?
// LinearLayout有自己的 LayoutParams 会复写一个非常重要的方法generateLayoutParams
MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();
//2.1.2根据子View计算自己布局的宽高度
// // 什么时候需要换行,一行不够的情况下 考虑 margin
if (lineWidth + childView.getMeasuredWidth() + params.leftMargin + params.rightMargin > width) {
//换行
//高度累加
height += maxHeight;
//一行宽度重置
lineWidth = getPaddingLeft() + params.leftMargin + params.rightMargin;
childViews = new ArrayList<>();
mChildViews.add(childViews);
} else {
//不换行
// 宽度累加
lineWidth += childView.getMeasuredWidth() + params.leftMargin + params.rightMargin;
maxHeight = Math.max(childView.getMeasuredHeight() + params.topMargin + params.bottomMargin, maxHeight);
}
childViews.add(childView);
}
height += maxHeight;
width = resolveSize(width, widthMeasureSpec);
height = resolveSize(height, heightMeasureSpec);
// 2.1.3 指定自己的布局
setMeasuredDimension(width, height);
}
@Override
public MarginLayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
2.2 onLayout()
for循环摆放所有的子View
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// for循环摆放所有的子View
int left, top = 0, right, bottom;
for (List<View> childViews : mChildViews) {
//高度不一致,计算最大的高度.
int maxHeight = 0;
left = getPaddingLeft();
for (View childView : childViews) {
MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();
left += params.leftMargin;
int childTop = top + params.topMargin;
right = left + childView.getMeasuredWidth();
bottom = childTop + childView.getMeasuredHeight();
// 摆放
childView.layout(left, childTop, right, bottom);
//left 不断叠加
left += childView.getMeasuredWidth() + params.rightMargin;
int childHeight = childView.getMeasuredHeight() + params.topMargin + params.bottomMargin;
maxHeight = Math.max(childHeight, maxHeight);
}
//不断叠加Top
top += maxHeight;
}
}
2.3 onDraw() 不需要了
2.4 Adapter 设计模式 设置数据
package com.zsj.taglayout;
import android.view.View;
import android.view.ViewGroup;
/**
* @author 朱胜军
* @date 2018/7/2
* 描述 TODO
* <p>
* 更新者 $Author$
* 更新时间 $Date$
* 更新描述 TODO
*/
public abstract class BaseAdapter {
/**
* @return 条目数
*/
public abstract int getCount();
/**
* @param position 坐标
* @param parents 父类
* @return 子View
*/
public abstract View getView(int position, ViewGroup parents);
}
public class TagLayout extends ViewGroup {
public void setAdapter(BaseAdapter adapter) {
if (adapter == null) {
new NullPointerException("adapter 不能为空");
}
//如果多次设置Adapter清除所有的子view
removeAllViews();
mAdapter = null;
mAdapter = adapter;
//获取子view的个数
int childViewCount = mAdapter.getCount();
for (int i = 0; i < childViewCount; i++) {
View childView = mAdapter.getView(i, this);
addView(childView);
}
}
}
public class MainActivity extends AppCompatActivity {
private TagLayout mTagLayout;
private List<String> mItems = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTagLayout = (TagLayout) findViewById(R.id.tagLayout);
//假设从网络获取的数据
mItems.add("1111");
mItems.add("222222");
mItems.add("33333333");
mItems.add("444");
mItems.add("5555555555");
mItems.add("6666");
mItems.add("77777");
mTagLayout.setAdapter(new BaseAdapter() {
@Override
public int getCount() {
return mItems.size();
}
@Override
public View getView(int position, ViewGroup parents) {
TextView tvTag = (TextView) LayoutInflater.from(MainActivity.this).inflate(R.layout.tag_layout, parents, false);
tvTag.setText(mItems.get(position));
return tvTag;
}
});
}
}
完整代码:taglayout