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

<android>自己写一个流式布局吧(FlowLayout)

2017-03-07 15:14 405 查看

(android)自己写一个流式布局吧(FlowLayout)

*首先我们要继承ViewGroup 开发自定义布局:

// 步骤一。继承 ViewGroup 开发自定义布局

public class FlowLayout extends ViewGroup {

private int layoutHeight;

private int layoutWidth;

public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

setBackgroundColor(Color.YELLOW);

}

public FlowLayout(Context context) {

this(context, null, 0);

}

public FlowLayout(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}


*测量是不可少的 查看有多少个元素

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//3.2. 测量前 清空行

mLines.clear();

//1.4 获取所有子元素

int childCount = getChildCount();

//1.5 遍历每个元素

Line curr = null;

for (int i = 0; i < childCount; i++) {

View child = getChildAt(i);

//1.6 获取子元素的测量宽高

child.measure(0, 0);// 测量包裹内容的宽高

int cWidth = child.getMeasuredWidth();

int cHeight = child.getMeasuredHeight();

System.out.println(“i->” + i + ” (” + cWidth + “,” + cHeight + “)”);

// 分行判断 步骤三。

}

步骤二 创建行对象 , 包含多个 View 的对象

// 步骤二。创建行对象 , 包含多个 View 的对象

class Line {

//2.1 创建存储 View 的集合

public List mViews = new ArrayList();

//2.2 添加元素

//2.3 获取行的高度 : 行里面最高的一个控件的高度 .( 只有元素最高值 设置下,所有元素才能存放 )

public int getLineHeight() {

int height = 0;

for (View view : mViews) {

//2.4 遍历取得最大高度 赋值给 height

view.measure(0, 0);

height = Math.max(height, view.getMeasuredHeight());

}

return height;

}

//2.5. 行内所有元素的宽度 ( 只有把元素的宽度进行累加 )

public int getAllViewWidth() {

int width = 0;

//2.6. 累加

for (View view : mViews) {

//2.7. 遍历

view.measure(0, 0);

width += view.getMeasuredWidth();

}

return width;

}

}

`

步骤三。将所有的子元素装进行里面,如果满一行就得换行继承装

private int vSpace = 6;

private int hSpace = 6;

// 步骤三。将所有的子元素装进行里面,如果满一行就得换行继承装

3.1. 创建构造流式布局的行的集合

private List mLines = new ArrayList<>();

//3.3. 创建第一行

if (mLines.size() == 0) {

curr = new Line();

//3.4. 第一行是属于行集合的

mLines.add(curr);

//3.5. 添加进行第一行的第一个元素进行

curr.mViews.add(child);

} else {

//3.6. 从第二个元素起,余下空间 >= 需要空间 , 可以存放

// 需要空间 = 间隔 + 元素宽度

// 余下空间 = 总宽度 - 所有元素的宽度和 -(n-1)*hSpace

int needSpace = hSpace + cWidth;

// MeasureSpec.getSize 将测量值转换成像素值

int layoutWidth = MeasureSpec.getSize(widthMeasureSpec);

int remainSpace = layoutWidth - curr.getAllViewWidth() - (curr.mViews.size() - 1) * hSpace;

if (remainSpace >= needSpace) {

curr.mViews.add(child);

}

//3.7. 余下空间 < 需要空间 , 换行 ( 创建一个新行 )

else {

//3.8 创建一个新行

curr = new Line();

//3.9, 行是属性于集合的

mLines.add(curr);

//3.10. 往当前行里面添加元素

curr.mViews.add(child);

}

}

步骤四 . 计算出流式布局需要的宽高

// 步骤四 . 计算出流式布局需要的宽高

//4.1 通过 onMeasure 提供的 widthMeasureSpec 测量值 ,再通过 MeasureSpec 的 getSize 获取像素 480

layoutWidth = MeasureSpec.getSize(widthMeasureSpec);

//4.2. 流式布局的高度 跟行数相关,行数越大,高度越大。流式布局高度 = 所有行的高度和 + ( n-1 ) *vSpace

layoutHeight = 0;

//4.2.1 所有行的高度和

for (int i = 0; i < mLines.size(); i++) {

Line line = mLines.get(i);

layoutHeight += line.getLineHeight();

}

//4.2.2. ( n-1 ) *vSpace

layoutHeight = layoutHeight + (mLines.size() - 1) * vSpace;

//4.3 设置布局的宽高 参数 1. 宽 , 参数 高

setMeasuredDimension(layoutWidth, layoutHeight);//

}

步骤五。摆放分好行的每个元素 layout(left,top,right,bottom)

// 步骤五。摆放分好行的每个元素 layout(left,top,right,bottom)

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

//5.1. 遍历每一行

for (int i = 0; i < mLines.size(); i++) {

Line line = mLines.get(i);

//5.4 获取当前行的 top

int lineTop = getCurrLineTop(i);

//5.2. 遍历行中的所有元素

for (int j = 0; j < line.mViews.size(); j++) {

View view = line.mViews.get(j);

//5.3 设置元素的 left,top,right bot
9e21
tom

int left = 0;

if (j == 0) {

// 本行中的第一个元素的坐标 0,0

left = 0;

} else// 非第一个元素

{

// 第二个元素起的 left 值为前一个元素的 right 加上水平间隔

left = line.mViews.get(j - 1).getRight() + hSpace;

}

int top = lineTop;

// 宽度 =right-left 高度 = bottom-top

//5.5 将不能使用的空间均分给每个控件,增加它们的宽度

//5.5.1 获取每个元素分配的空间

int eachSpace=getEachSpace(line);

//5.5.2. 分配给每个控件的 right

int right = left + view.getMeasuredWidth()+eachSpace;

int bottom = top + view.getMeasuredHeight();

view.layout(left, top, right, bottom);

//5.5.3. 处理内容居中显示

//MeasureSpec.EXACTLY 100dp

int newWidth=view.getMeasuredWidth()+eachSpace;

int newMeasureWidth=MeasureSpec.makeMeasureSpec(newWidth,MeasureSpec.EXACTLY);

view.measure(newMeasureWidth,MeasureSpec.UNSPECIFIED);//–>onDraw

}

}

}

private int getEachSpace(Line line) {

// 获取余下不可用空间

int remainUnusedSpace=layoutWidth-line.getAllViewWidth()-(line.mViews.size()-1)*hSpace;

// 除以元素个数 3/5 0.6

return (int) (remainUnusedSpace*1f/line.mViews.size());

}

private int getCurrLineTop(int curr) {//

int top = 0;

for (int i = 0; i < curr; i++) {

Line line = mLines.get(i);

// 累加

top += (line.getLineHeight() + vSpace);

}

return top;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐