您的位置:首页 > 移动开发 > Android开发

我可能使用假的流式布局。自定义XFlowLayout

2017-02-08 09:59 309 查看
基础文章地址:http://blog.csdn.net/lmj623565791/article/details/38352503  感谢大神文章

因为要做那种流式布局标签,查了很多资料,都是大同小异。

有些没有解决FlowLayout的padding

的问题。很多都是直接转载的,而且FlowLayout里面的间隔都是靠子view的margin

来解决,感觉很不科学。所以自己的就在这个基础的封装自己的流式布局XFlowLayout自定义的水平间隔hgap和垂直间隔vgap

整个类都有注释,理解应该不困难

里面主要的就是onMeasure和onLayout方法,需要知道测量布局的三种模式,后面直接添加view就好

废话不多了,直接上代码 

主要类:

public class XFlowLayout extends ViewGroup {
//所有的子view
private List<List<View>> mAllChildViews = new ArrayList<>();
//每一行的高度
private List<Integer> mLineHeight = new ArrayList<>();
//水平和垂直间距
private int hgap;
private int vgap;

public XFlowLayout(Context context) {
this(context, null);
}

public XFlowLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public XFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ZBJFlowLayout);
hgap = (int) ta.getDimension(R.styleable.ZBJFlowLayout_hgap, 0);
vgap = (int) ta.getDimension(R.styleable.ZBJFlowLayout_vgap, 0);
ta.recycle();
}

//测量整个布局多大
@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);
//宽度和高度
int width = 0;
int height = 0;
//行宽和行高
int lineWidth = 0;
int lineHeight = 0;
//子view个数
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//获得子view的宽高
int childWidth = child.getWidth();
int childHeight = child.getHeight();

if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) {//换行
//对比最大宽度
width = Math.max(width, lineWidth);
//换行加上垂直间隔
height += lineHeight + vgap;
//已经换行宽高重置
lineWidth = childWidth;
lineHeight = childHeight;
} else {//不换行
//不换行水平宽度加上水平间隔
lineWidth += childWidth + hgap;
//对比最大高度
lineHeight = Math.max(lineHeight, childHeight);
}
//最后一个控件
if (i == childCount - 1) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
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) {
mAllChildViews.clear();
mLineHeight.clear();
//获得当前布局的宽度
int width = getWidth();

int lineWidth = 0;
int lineHeight = 0;
List<View> lineViews = new ArrayList<View>();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
if (childWidth + lineWidth > width - getPaddingLeft() - getPaddingRight()) {//换行
//记录行高
mLineHeight.add(lineHeight);
//记录当前行的子view
mAllChildViews.add(lineViews);
//重置行宽高
lineWidth = 0;
lineHeight = childHeight + vgap;
//new一个新的集合
lineViews = new ArrayList<>();
}
lineWidth = lineWidth + childWidth + hgap;
lineHeight = Math.max(lineHeight, childHeight);
lineViews.add(child);
}
//处理最后一行
mLineHeight.add(lineHeight);
mAllChildViews.add(lineViews);
//记录view位置和行数
int left = getPaddingLeft();
int top = getPaddingTop();
int lineCount = mAllChildViews.size();
for (int i = 0; i < lineCount; i++) {
//当前行所有的VIEW
lineViews = mAllChildViews.get(i);
//当前行高
lineHeight = mLineHeight.get(i);
for (int j = 0; j < lineViews.size(); j++) {
View child = lineViews.get(j);
if (child.getVisibility() == View.GONE) {//不显示则跳出
continue;
}
int cLeft = left;
int cTop;
if (i == 0) {
cTop = top;
} else {
cTop = top + vgap;
}
int cRight = cLeft + child.getMeasuredWidth();
int cBottom = cTop + child.getMeasuredHeight();
child.layout(cLeft, cTop, cRight, cBottom);
left += child.getMeasuredWidth() + hgap;
}
left = getPaddingLeft();
if (i == lineCount - 1) {
top += lineHeight + vgap;
} else {
top += lineHeight;
}
}
}

// @Override
// public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
// return new MarginLayoutParams(getContext(),attrs);
// }
}

attrs文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="ZBJFlowLayout">
<attr name="hgap" format="dimension" />
<attr name="vgap" format="dimension" />
</declare-styleable>
</resources>

xml里面引用
<com.expect.view.XFlowLayout

android:layout_margin="10dp"
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#5246"
zfl:hgap="10dp"
zfl:vgap="10dp">

大概就是这些了  好久没写博客了  不知道还能坚持到多久
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android FlowLayout