Andorid 流式布局 热门标签解决方案

jopen 9年前

// 流式布局 话不多说,比较简单,注释都写的很清楚      import java.util.ArrayList;  import java.util.List;    import android.content.Context;  import android.util.AttributeSet;  import android.view.View;  import android.view.ViewGroup;    /**   *    * @author Mr.Himan   * @version 1.0<br>   *          2015年11月4日 11:12:06 <br>   *          流式布局 设置MarginTop 和MarginLeft有效 MarginRight 暂未实现   */  public class FlowLayout extends ViewGroup {     /**    * 存储所有的子View    */   private List<List<View>> mAllChildViews = new ArrayList<List<View>>();     /**    * 存储每一行的高度    */   private List<Integer> mLineHeight = new ArrayList<Integer>();     public FlowLayout(Context context) {    this(context, null);   }     public FlowLayout(Context context, AttributeSet attrs) {    this(context, attrs, 0);   }     public FlowLayout(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);   }     @Override   protected void onLayout(boolean changed, int l, int t, int r, int b) {    mAllChildViews.clear();    mLineHeight.clear();    // 获取当前ViewGroup的宽度    int width = getWidth();      int lineWidth = 0;    int lineHeight = 0;    // 记录当前行的view    List<View> lineViews = new ArrayList<View>();    int childCount = getChildCount();    for (int i = 0; i < childCount; i++) {     View child = getChildAt(i);     MarginLayoutParams lp = (MarginLayoutParams) child       .getLayoutParams();     int childWidth = child.getMeasuredWidth();     int childHeight = child.getMeasuredHeight();       // 如果需要换行     if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width) {      // 记录LineHeight      mLineHeight.add(lineHeight);      // 记录当前行的Views      mAllChildViews.add(lineViews);      // 重置行的宽高      lineWidth = 0;      lineHeight = childHeight + lp.topMargin + lp.bottomMargin;      // 重置view的集合      lineViews = new ArrayList();     }     lineWidth += childWidth + lp.leftMargin + lp.rightMargin;     lineHeight = Math.max(lineHeight, childHeight + lp.topMargin       + lp.bottomMargin);     lineViews.add(child);    }    // 处理最后一行    mLineHeight.add(lineHeight);    mAllChildViews.add(lineViews);      MarginLayoutParams params = (MarginLayoutParams) this.getLayoutParams();      // 设置子View的位置    int left = 0;    // 添加marginTop    int top = 0 + params.topMargin;    // 获取行数    int lineCount = mAllChildViews.size();    for (int i = 0; i < lineCount; i++) {     // 当前行的views和高度     lineViews = mAllChildViews.get(i);     lineHeight = mLineHeight.get(i);     for (int j = 0; j < lineViews.size(); j++) {      // 为每一列设置marginLeft      if (j == 0) {       left = 0 + params.leftMargin;      }      View child = lineViews.get(j);      // 判断是否显示      if (child.getVisibility() == View.GONE) {       continue;      }      MarginLayoutParams lp = (MarginLayoutParams) child        .getLayoutParams();      int cLeft = left + lp.leftMargin;      int cTop = top + lp.topMargin;      int cRight = cLeft + child.getMeasuredWidth();      int cBottom = cTop + child.getMeasuredHeight();      // 进行子View进行布局      child.layout(cLeft, cTop, cRight, cBottom);      left += child.getMeasuredWidth() + lp.leftMargin        + lp.rightMargin;     }     left = 0;     top += lineHeight;    }   }     @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);      // 如果当前ViewGroup的宽高为wrap_content的情况    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);     // 测量子View的宽和高     measureChild(child, widthMeasureSpec, heightMeasureSpec);     // 得到LayoutParams       MarginLayoutParams params = (MarginLayoutParams) child       .getLayoutParams();     // 子View占据的宽度     int childWidth = child.getMeasuredWidth() + params.leftMargin       + params.rightMargin;     // 子View占据的高度     int childHeight = child.getMeasuredHeight() + params.bottomMargin       + params.topMargin;     // 换行时候     if (lineWidth + childWidth > sizeWidth) {      // 对比得到最大的宽度      width = Math.max(width, lineWidth);      // 重置lineWidth      lineWidth = childWidth;      // 记录行高      height += lineHeight;      lineHeight = childHeight;     } else {      // 不换行情况      // 叠加行宽      lineWidth += childWidth;      // 得到最大行高      lineHeight = Math.max(lineHeight, childHeight);     }     // 处理最后一个子View的情况     if (i == childCount - 1) {      width = Math.max(width, lineWidth);      height += lineHeight;     }    }    setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth      : width, modeHeight == MeasureSpec.EXACTLY ? sizeHeight      : height);     }     /**    * 与当前ViewGroup对应的LayoutParams    */   @Override   public LayoutParams generateLayoutParams(AttributeSet attrs) {    return new MarginLayoutParams(getContext(), attrs);   }  }




来自: http://blog.csdn.net/soul_code/article/details/50265255