android 换行乱_Android自动换行布局
public class FlowLayout extends ViewGroup {
/**
* 所有子控件的容器
*/
private List> lineList = new ArrayList<>();
/**
* 每行的高度
*/
private List lineHeightList = new ArrayList<>();
/**
* 防止多次測量
*/
private boolean measureFlag = true;
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);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
/**
* 在被調(diào)用這個方法之前 它的父容器 已經(jīng)把它的測量模式改成了當前控件的測量模式
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//獲取到父容器 給我們的參考值
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//獲取到自己的測量模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//記錄當前控件里面的子控件的總高寬
int childMaxWidth = 0;
int childCountHeight = 0;
//防止多次測量
if (measureFlag) {
measureFlag = false;
} else {
//當前一行,控件中的子控件的總寬度
int lineCountWidth = 0;
//當前一行,最高子控件的高度
int lineMaxHeight = 0;
//記錄每個子控件的寬高
int childWidth, childHeight;
//創(chuàng)建一行空容器
List viewList = new ArrayList<>();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
//先測量子控件
measureChild(childView, widthMeasureSpec, heightMeasureSpec);
MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams();
//計算當前子控件的實際寬高
childWidth = childView.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;
childHeight = childView.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin;
//如果當前行的寬度,加上這個view的寬度,大于容器的寬度時,就換行
if (lineCountWidth + childWidth + getPaddingLeft() + getPaddingRight() > widthSize) {
//需要換行的情況
//每次進入到這里的時候 只是保存了上一行的信息,并沒有保存當前行的信息
//拿到所有行中,最大的寬,去決定EXACTLY時的最大寬度
childMaxWidth = Math.max(childMaxWidth, lineCountWidth);
childCountHeight += lineMaxHeight;
//把行高記錄到集合中
lineHeightList.add(lineMaxHeight);
//把這一行的數(shù)據(jù)放進總容器
lineList.add(viewList);
//把一行的容器,重新創(chuàng)建一個,雖然會頻繁創(chuàng)建,但如果調(diào)用clear,會導致lineList的棧也會被清掉
viewList = new ArrayList<>();
//把每行的高寬初始化
lineCountWidth = childWidth;
lineMaxHeight = childHeight;
viewList.add(childView);
} else {
//不需要換行的情況
lineCountWidth += childWidth;
//取當前行的所有子控件最大的高度
lineMaxHeight = Math.max(lineMaxHeight, childHeight);
viewList.add(childView);
}
//這樣做的原因是 之前的if else中 不會把最后一行的高度加進listLineHeight
// 最后一行要特殊對待 不管最后一個item是不是最后一行的第一個item
if (i == (childCount - 1)) {
//保存當前行信息
childMaxWidth = Math.max(childMaxWidth, lineCountWidth + getPaddingLeft() + getPaddingRight());
childCountHeight += lineMaxHeight;
lineHeightList.add(lineMaxHeight);
lineList.add(viewList);
}
}
}
//設置控件最終大小
int measureWidth = (widthMode == MeasureSpec.EXACTLY ? widthSize : childMaxWidth + getPaddingLeft() + getPaddingRight());
int measureHeight = (heightMode == MeasureSpec.EXACTLY ? heightSize : childCountHeight + getPaddingTop() + getPaddingBottom());
setMeasuredDimension(measureWidth, measureHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//擺放子控件的位置
int left, top, right, bottom;
//保存上一個控件的邊距
int countLeft = 0;
//保存上一行的高度的邊距
int countTop = 0;
//遍歷所有行
for (List views : lineList) {
//遍歷每一行的控件
for (View view : views) {
MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
left = countLeft + layoutParams.leftMargin;
top = countTop + layoutParams.topMargin;
right = left + view.getMeasuredWidth();
bottom = top + view.getMeasuredHeight();
view.layout(left + getPaddingLeft(), top + getPaddingTop(), right + getPaddingRight(), bottom + getPaddingBottom());
//記錄當前控件的實際寬度坐標,讓下一個控件知道X軸的起點在哪
countLeft += view.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin;
}
int i = lineList.indexOf(views);
//換行時從最左邊開始
countLeft = 0;
//換行時累加高度
countTop += lineHeightList.get(i);
}
//布局結束后清空記錄的list
lineList.clear();
lineHeightList.clear();
}
}
總結
以上是生活随笔為你收集整理的android 换行乱_Android自动换行布局的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql中try的意思_java中tr
- 下一篇: java 安卓下载文件_GitHub -