大家好,欢迎来到IT知识分享网。
- 流式布局在android中主要应用在搜索记录和用户标签,下面是效果图
- 首先我们分析流式布局的原理。其实就是当一个子view加上之前的子view的宽度超过了父容器的宽度的时候就换行。
- 接下来我们手把手书写流式布局
- 首先我们要完成我们的onMeasure算法,onMeasure中完成两个功能。1是自己的宽度和高度的确定,2是测量所有的子view的宽度和高度。
- 首先我们需要测量所有的孩子的宽度和高度。这里我们使用的测量算子是我们自定义的。
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- child.measure(MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST));
- }
这里我们通过的测量算子都是包裹内容模式。下图是测量算子关系图。这里子view的测量模式是AT_MOST,最大值测量模式。也就是子view的大小不会超过父容器的大小。
- 接下来我们到了根据子view的高度来确定流式布局的高度了。
private int getMeasureHeight(){ layoutFlow(); return getChildAt(getChildCount()-1).getBottom();
} *这里我没有想到好的算法,而是先讲所有的孩子layout一下,之后拿到最后一个孩子的getBottom,即返回当前流式布局的高度
- layoutFlow()的代码下面会介绍,在onLayout方法中。
- 首先我们需要测量所有的孩子的宽度和高度。这里我们使用的测量算子是我们自定义的。
int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- child.measure(MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST));
- }
- 这里我们通过的测量算子都是包裹内容模式。下图是测量算子关系图。这里子view的测量模式是AT_MOST,最大值测量模式。也就是子view的大小不会超过父容器的大小。
- 测量完了之后就是我们的layout代码了
- 下面是layout代码
protected void onLayout(boolean changed, int l, int t, int r, int b) {
- layoutFlow();
- }
- layout代码中调用的也是layoutFlow()。流式布局的重点就在与如何的放置子view
- 下面我们对layoutFlow代码进行分析
private void layoutFlow() {
- int childCount=getChildCount();
- int left=getPaddingLeft();
- int top=getPaddingTop();
- for(int i=0;i<childCount;i++){
- View child = getChildAt(i);
- int measuredWidth = child.getMeasuredWidth();
- if(i==0){
- child.layout(left,top,left+child.getMeasuredWidth(),top+child.getMeasuredHeight());
- left=child.getMeasuredWidth();
- }else{
- View childAt = getChildAt(i – 1);
- if(childAt.getRight()+child.getMeasuredWidth()+getPaddingRight()>getMeasuredWidth()){
- top = childAt.getBottom();
- left=getPaddingLeft();
- }else{
- left=childAt.getRight();
- }
- Log.e(“dasda”,top+”–>”+getMeasuredWidth());
- child.layout(left,top,left+child.getMeasuredWidth(),top+child.getMeasuredHeight());
- }
- }
- }
- 首先拿到所有的孩子,之后计算每个孩子的left和top。
- 第一个孩子直接layout即可
- 接下来就是判断是否换行
if(childAt.getRight()+child.getMeasuredWidth()+getPaddingRight()>getMeasuredWidth()){
- top = childAt.getBottom();
- left=getPaddingLeft();
- }
- 如果前一个孩子的right+当前孩子的宽度+流式布局的paddingRight>流式布局的宽度 则换行。并将前一个孩子的bottom当做当前孩子的top,left重置。
- 否则的话,left就等于前一个孩子的right值
- 完成了这两步,流式布局写的差不多了,接下来我们给所有孩子设置监听
- 监听的方法也很简单,就是根据手指按下的(x,y)获得按下的孩子即可。下面是判断的核心代码。根据x,y 遍历所有的孩子,拿到符合当前位置的孩子。
private int pointToPosition(float x, float y) {
- int top=0;
- int left=0;
- int bottom=0;
- int right=0;
- int childCount = getChildCount();
- for(int i=0;i<childCount;i++){
- View childAt = getChildAt(i);
- top=childAt.getTop();
- left=childAt.getLeft();
- right=childAt.getRight();
- bottom=childAt.getBottom();
- if(y>=top&&y<=bottom&&x>=left&&x<=right){
- return i;
- }
- }
- return -1;
- }
- 我们在ACTION_UP的时候回调监听即可
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- x = (int) event.getX();
- y = (int) event.getY();
- i = pointToPosition(x, y);
- break;
- case MotionEvent.ACTION_MOVE:
- break;
- case MotionEvent.ACTION_UP:
- int position = pointToPosition(event.getX(), event.getY());
- if (i == position)
- if (onItemClickListener != null) {
- Log.e(“tag”, “ontouc”);
- onItemClickListener.onItemClick(position, getChildAt(position));
- }
- break;
- }
- return true;
- }
- 这里我们在松手的时候判断和按下的是否是同一个孩子,是同一个孩子就回调
总结:流式布局可以很好的锻炼我们的onLayout方法。
- 源码链接
http://pan.baidu.com/s/1miyGIco
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/173198.html