概述
先放效果图:
代码如下:
public class ZFlowLayout extends ViewGroup {
// 储存所有的View
private ArrayList<ArrayList<View>> mAllViews = new ArrayList<>();
// 储存每一行的高度
private ArrayList<Integer> mLineHeight = new ArrayList<>();
private LayoutInflater mInflater;
public ZFlowLayout(Context context) {
this(context, null);
}
public ZFlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ZFlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// mInflater = LayoutInflater.from(getContext());
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 父控件传进来的宽度和高度以及对应的测量模式
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
// 如果当前ViewGroup的宽高为wrap_content的情况
int width = 0;// 自己测量的 宽度
int height = 0;// 自己测量的高度
// 记录每一行的宽度和高度
int lineWidth = 0;
int lineHeight = 0;
// 得到内部元素的个数
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
// 测量子View的宽和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
// 得到LayoutParams
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
// 子view的占据的宽度
int childWidth = child.getMeasuredWidth() + lp.leftMargin
+ lp.rightMargin;
// 子view占据的高度
int childHeight = child.getMeasuredHeight() + lp.topMargin
+ lp.bottomMargin;
// 换行
if (lineWidth + childWidth > sizeWidth - getPaddingLeft()
- getPaddingRight()) {
// 对比得到最大的宽度
width = Math.max(width, lineWidth);
// 重置lineWidth
lineWidth = childWidth;
// 记录行高
height += lineHeight;
lineHeight = childHeight;
} else {
// 未换行
// 叠加行宽
lineWidth += childWidth;
// 得到当前最大高度
lineHeight = Math.max(lineHeight, childHeight);
}
// 最后一个控件
if (i == count - 1) {
width = Math.max(lineWidth, width);
height += lineHeight;
}
}
// Log.i("test", "sizeWidth" + sizeWidth);
// Log.i("test", "sizeHeight" + sizeHeight);
setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth
: width + getPaddingLeft() + getPaddingRight(),
modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height
+ getPaddingTop() + getPaddingBottom());
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 清除一下list集合
mAllViews.clear();
mLineHeight.clear();
// 得到viewGroup当前宽度
int width = getWidth();
int lineWidth = 0;
int lineHeight = 0;
ArrayList<View> lineViews = new ArrayList<>();
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
// 如果需要换行
if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width
- getPaddingLeft() - getPaddingRight()) {
// 记录当前行高
mLineHeight.add(lineHeight);
// 记录当前行的view
mAllViews.add(lineViews);
// 重置行宽和行高
lineWidth = 0;
lineHeight = childHeight + lp.topMargin + lp.bottomMargin;
// 重置lineViews集合
lineViews = new ArrayList<>();
}
lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
lineHeight = Math.max(lineHeight, childHeight + lp.topMargin
+ lp.bottomMargin);
lineViews.add(child);
}
// 处理最后一行
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
// 设置子view的位置
int left = getPaddingLeft();
int top = getPaddingTop();
// 有多少行
int lineNum = mLineHeight.size();
for (int i = 0; i < lineNum; i++) {
// 获取当前行的view
lineViews = mAllViews.get(i);
// 当前行高
lineHeight = mLineHeight.get(i);
int lineViewSize = lineViews.size();
for (int j = 0; j < lineViewSize; j++) {
View child = lineViews.get(j);
// 判断子view的状态
if (child.getVisibility() == View.GONE) {
continue;
}
MarginLayoutParams lp = (MarginLayoutParams) child
.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int lc = left + lp.leftMargin;
int tc = top + lp.topMargin;
int rc = lc + childWidth;
int bc = tc + childHeight;
// 为子view布局
child.layout(lc, tc, rc, bc);
// 同一行view坐起点坐标的变换
left += childWidth + lp.leftMargin + lp.rightMargin;
}
// 换行时将left重置
left = getPaddingLeft();
// top要加上上一行的行高
top += lineHeight;
}
}
/**
* 与当前ViewGroup对应的LayoutParams
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
}
在布局里调用
<com.zuihou.drunkenmonkey.widget.view.ZFlowLayout
android:id="@+id/flowLayout_hot"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
代码里调用
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutParams.setMargins(25, 5, 15, 15);
if (hotSearch.getData().getHotSearch().size() > 0 && hotSearch.getData().getHotSearch() != null) {
for (int i = 0; i < hotSearch.getData().getHotSearch().size(); i++) {
final TextView textView = new TextView(SearchActivity.this);
textView.setTag(i);
textView.setTextSize(14);
textView.setText(hotSearch.getData().getHotSearch().get(i).getWord_word());
textView.setPadding(15, 15, 15, 15);
textView.setTextColor(Color.parseColor("#3e4346"));
textView.setBackgroundResource(R.drawable.flow_drawable);
flowLayoutHot.addView(textView, layoutParams);
// 标签点击事件
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
}
这样就可以了
最后
以上就是清爽河马为你收集整理的Android FlowLayout流布局的全部内容,希望文章能够帮你解决Android FlowLayout流布局所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复