public class FlowView extends ViewGroup {
// 用来记录描述有多少行View
private List<LineView> mLineViews = new ArrayList<LineView>();
// 用来记录当前已经添加到了哪一行
private LineView mCurrentLineView;
private int mHorizontalSpace = 20;//水平间隔
private int mVerticalSpace = 20;//垂直间隔
public FlowView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlowView(Context context) {
this(context, null);
}
/**
* 向外公布的方法
* @param horizontalSpace
* @param VerticalSpace
*/
public void setSpace(int horizontalSpace, int VerticalSpace){
this.mHorizontalSpace = horizontalSpace;
this.mVerticalSpace = VerticalSpace;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 给Child 布局---> 给Line布局
int paddingLeft = getPaddingLeft();
int paddingTop = getPaddingTop();
for (int i = 0; i < mLineViews.size(); i++) {
LineView lineView = mLineViews.get(i);
//给每个lineViewlayout即可
lineView.layout(paddingLeft, paddingTop);
//表示下一行的高度
paddingTop += mVerticalSpace + lineView.mHeight;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//清空
mLineViews.clear();
mCurrentLineView = null;
//获得布局的宽度
int layoutWidth = MeasureSpec.getSize(widthMeasureSpec);
//获取行最大的宽度
int maxWidth = layoutWidth - getPaddingLeft() - getPaddingRight();
// 测量孩子
int count = getChildCount();
for (int i = 0; i < count; i++) {
View view = getChildAt(i);
//如果孩子不可见,就不必测量
if (view.getVisibility() == View.GONE) {
continue;
}
//测量孩子
measureChild(view, widthMeasureSpec, heightMeasureSpec);
//子行添加view
if (mCurrentLineView == null) {
mCurrentLineView = new LineView(maxWidth, mHorizontalSpace);
//添加到行中
mLineViews.add(mCurrentLineView);
//航中一个孩子没有
mCurrentLineView.addView(view);
}else {
//行不空,说明有孩子
if (mCurrentLineView.canAdd(view)) {
// 可以添加
mCurrentLineView.addView(view);
}else {
//添加不下去,换行添加
mCurrentLineView = new LineView(maxWidth, mHorizontalSpace);
//添加到集合
mLineViews.add(mCurrentLineView);
// 将view添加到line
mCurrentLineView.addView(view);
}
}
}
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//设置自己的宽度与高度
int measuredWidth = layoutWidth;
float allHeight = 0;
for (int i = 0; i < mLineViews.size(); i++) {
float height = mLineViews.get(i).mHeight;
// 加行高
allHeight += height;
if (i != 0) {
// 加间距
allHeight += mVerticalSpace;
}
}
int measuredHeight = (int) (getPaddingBottom() + getPaddingTop() + allHeight + 0.5f);
//测量自身的高度
setMeasuredDimension(measuredWidth, measuredHeight);
}
class LineView {
public List<View> mViews = new ArrayList<View>();// 用来记录每一行有几个View
public int mUsedWidth;//已使用的宽度
public int mMaxWidth;//最大宽度
public int mHorizontalSpace; View和view之间的水平间距
public int mHeight;//高度
public int mMaginLeft;
public int mMaginBottom;
public int mMaginRight;
public int mMaginTop;
public LineView(int maxWidth, int space){
this.mMaxWidth = maxWidth;
this.mHorizontalSpace = space;
}
/**
* 给孩子布局
*
* @param paddingLeft
* @param paddingTop
*/
public void layout(int paddingLeft, int paddingTop) {
int currentLeft = paddingLeft;
//把剩余的空间评分
float extra = 0;
float widthAvg = 0;
int size = mViews.size();
// 判断已经使用的宽度是否小于最大的宽度
if (mMaxWidth > mUsedWidth) {
extra = mMaxWidth - mUsedWidth;
widthAvg = extra / size;
}
for (int i = 0; i < size; i++) {
View view = mViews.get(i);
int viewWidth = view.getMeasuredWidth();
int viewHeight = view.getMeasuredHeight();
// 判断是否有富余
if (widthAvg != 0) {
int newWidth = (int) (viewWidth + widthAvg + 0.5f);
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);
view.measure(widthMeasureSpec, heightMeasureSpec);
//重新赋值
viewWidth = view.getMeasuredWidth();
viewHeight = view.getMeasuredHeight();
}
// 布局
int left = currentLeft;
//int top = paddingTop;
//让子view垂直居中
int top = (int) (paddingTop + (mHeight - viewHeight)/2.0f + 0.5f);
int right = left + viewWidth;
int bottom = top + viewHeight;
view.layout(left, top, right, bottom);
//下一个view的left
currentLeft += viewWidth + mHorizontalSpace;
}
}
/**
* 添加view
* @param view
*/
public void addView(View view){
int size = mViews.size();
int viewWidth = view.getMeasuredWidth();
int viewHeight = view.getMeasuredHeight();
//mUsedWidth += viewWidth;
if (size == 0) {
// 说还没有添加View
if (viewWidth > mMaxWidth) {
mUsedWidth = mMaxWidth;
}else {
mUsedWidth = viewWidth;
}
//初始化高度
mHeight = viewHeight;
}else {
// 多个view的情况
mUsedWidth += viewWidth + mHorizontalSpace;
//如果当前的高度》最新加入view的高度,就是当前的高度,否则就是行加入的view的高度
mHeight = mHeight > viewHeight ? mHeight : viewHeight;
}
// 将View记录到集合中
mViews.add(view);
}
/**
* 能否添加
* @param view
* @return
*/
public boolean canAdd(View view){
//如果没有view,就可添加
if (mViews.size() == 0) {
return true;
}
int viewWidth = view.getMeasuredWidth();
if (mUsedWidth + mHorizontalSpace + viewWidth > mMaxWidth) {
// 加不进去
return false;
}else {
return true;
}
}
}
}
Android瀑布流实现二
最新推荐文章于 2021-09-18 16:05:44 发布