首页 > 系统 > Android > 正文

Android开发之瀑布流控件的实现与使用方法示例

2019-10-22 18:25:15
字体:
来源:转载
供稿:网友

本文实例讲述了Android开发之瀑布流控件的实现与使用方法。分享给大家供大家参考,具体如下:

public class FlowLayout extends ViewGroup {  /**行里子view之间的行距离*/  public int mHorizontolSpace = Util.getDimen(R.dimen.top_padding);  /**行里子view之间的垂直距离*/  public int mVerticalSpace = Util.getDimen(R.dimen.top_padding);  /**创建行的集合*/  private List<Line> mLines = new ArrayList<Line>();  /**当前行*/  private Line mCurrentLine;  /**当前行使用的宽度*/  private int mCurrentUseWidth = 0;  /**父容器的宽高*/  private int parentWidthSize;  private int parentHeightSize;  public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);  }  public FlowLayout(Context context, AttributeSet attrs) {    super(context, attrs);  }  public FlowLayout(Context context) {    super(context);  }  @Override  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    //0.先清空行集合里的数据    clear();    //1.得到父viewGroup的模式与大小    int parentWidthMode = MeasureSpec.getMode(widthMeasureSpec);//    parentWidthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();    int parentHeightMode = MeasureSpec.getMode(heightMeasureSpec);    parentHeightSize = MeasureSpec.getSize(heightMeasureSpec) - getPaddingBottom() - getPaddingTop();    /* 每个子view都是包裹内容     * layout.addView(mTextView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT     * 得到每个孩子的测量规则     */    //2.得到每个孩子的模式    int childWidthMode = parentWidthMode == MeasureSpec.EXACTLY ? MeasureSpec.EXACTLY : parentWidthMode;    int childHeightMode = parentHeightMode == MeasureSpec.EXACTLY ? MeasureSpec.EXACTLY : parentHeightMode;    //3.根据模式得到子控件的大小    int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthMode, parentWidthSize);    int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightMode, parentHeightSize);    //得到子view的个数    int count = getChildCount();    //创建新的行    mCurrentLine = new Line();    for (int i = 0; i < count; i++) {      View childView = getChildAt(i);      //4.测量每个孩子      childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);      //5.得到测量后的孩子的宽高      int childMeasureWidth = MeasureSpec.getSize(childWidthMeasureSpec);      //int childMeasureHeight = MeasureSpec.getSize(childHeightMeasureSpec);      //6.得到此行使用的宽度      mCurrentUseWidth += childMeasureWidth;      //7.判断此行的宽度是否大于父控件的宽度,如果大于则换行      if (mCurrentUseWidth > parentWidthSize) {        //8.如果当前的子view的宽度大于父容器的宽度,强行把这个view添加的集合里        if (mCurrentLine.getChildCount()<1) {          mLines.add(mCurrentLine);         }        //9.换行        newLine();      }else {        //8.把当前子view添加到行里        mCurrentLine.addChild(childView);        //9.添加间隔        mCurrentUseWidth += mHorizontolSpace;        if (mCurrentUseWidth > parentWidthSize) {          //10.换行          newLine();        }      }    }    //11.如果集合里没有添加当前行,则把当前添加到集合    if (!mLines.contains(mCurrentLine)) {      mLines.add(mCurrentLine);    }    //12.设置富容器的总宽高    int parentWidth = parentWidthSize + getPaddingLeft() + getPaddingRight();    int parentHeight = (mLines.size()-1) * mVerticalSpace + getPaddingBottom() + getPaddingTop();    for(Line line : mLines){      //得到所以line的高度      parentHeight += line.getHeight();    }    //13.resolveSize表示哪个高度合适,就用哪个    setMeasuredDimension(parentWidth, resolveSize(parentHeightSize, parentHeight));    /*setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),        getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));*/  }  /**   * 换行   */  private void newLine() {    //a.先把当前的行添加到集合    mLines.add(mCurrentLine);    //b.创建新的一行    mCurrentLine = new Line();    //c.新行里的使用的行必须设置为0    mCurrentUseWidth = 0;  }  public void clear() {    mLines.clear();    mCurrentLine = null;    mCurrentUseWidth = 0;  }  @Override  protected void onLayout(boolean changed, int l, int t, int r, int b) {    //15.得到每个line孩子的左上角的坐标    int left = l + getPaddingLeft();    int top = t + getPaddingTop();    //现在容器里只有line是子孩子    for (int i = 0; i < mLines.size(); i++) {      Line line = mLines.get(i);      //16.把分配位置给line去处理      line.layout(left, top);      //17.设置第一行后的其它行的top数值      top += line.getHeight() + mVerticalSpace;    }  }  /**   * 行类,用来封装一行的view   */  private class Line{    /**当前行的宽度*/    private int mWidth = 0;    /**当前行的高度*/    private int mHeight = 0;    /**每个孩子得到的剩余空间*/    int mChildPdding = 0;    private List<View> children = new ArrayList<View>();    public void addChild(View childView) {      children.add(childView);      //取得之view里最高的高度      if (childView.getMeasuredHeight() > mHeight) {        mHeight = childView.getMeasuredHeight();      }      //18.得到行宽度      mWidth += childView.getMeasuredWidth();    }    /**     * 定位每个line在富容器里的额位置     * @param left     * @param top     */    public void layout(int left, int top) {      //18.得到行宽度      mWidth += mHorizontolSpace * (children.size() -1);      //19.得到剩余的宽度大小      //int padding = getMeasuredWidth() - mWidth;      int padding = parentWidthSize - mWidth;      if (padding > 0) {        mChildPdding = padding / children.size();      }      // getWidth()view显示的时候大小,如果view没显示,这个值就为0,步包括隐藏的部分, getMeasuredWidth()控件实际大小,包括隐藏的部分      //一般来说 getMeasuredWidth() > getWidth();      for (int i = 0; i < children.size(); i++) {        View child = children.get(i);        //第一种:有间隔的flow        int bottom = child.getMeasuredHeight() + top;        //20.把剩余的空间分配给每个view        int right = child.getMeasuredWidth() + left + mChildPdding;        //第二种:无间隔的flow//       int bottom = getMeasuredHeight() + top;//       int right = getMeasuredWidth() + left;        //第一个child的位置        child.layout(left, top, right, bottom);        //第二个及后面child的right        right += child.getMeasuredWidth() + mHorizontolSpace + mChildPdding;      }    }    /**     * 得到子view的大小     * @return     */    public int getChildCount() {      if (children != null) {        return children.size();      }      return 0;    }    public int getHeight() {      return mHeight;    }  }}

使用方法:

public class TopFragment extends Fragment{  @Override  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {    ScrollView scrollView = new ScrollView(getActivity());    FlowLayout layout = new FlowLayout(getActivity());    layout.setBackgroundDrawable(Util.getDrawable(R.drawable.list_item_bg));    int padding = Util.getDimen(R.dimen.top_padding);    layout.setPadding(padding, padding, padding, padding);    GradientDrawable pressDrawable = DrawableUtil.createDrawable(0xffcecece);    for (int i = 0; i < mDatas.size(); i++) {      mTextView = new TextView(getActivity());      mTextView.setText(mDatas.get(i));      GradientDrawable randomDrawable = DrawableUtil.createRandomDrawable();      StateListDrawable stateListDrawable = DrawableUtil.createStateDrawable(pressDrawable, randomDrawable);      mTextView.setBackgroundDrawable(stateListDrawable);      mTextView.setTextColor(Color.WHITE);      int left = Util.px2dip(7);      int top = Util.px2dip(4);      int right = Util.px2dip(7);      int bottom = Util.px2dip(4);      mTextView.setPadding(left, top, right, bottom);      mTextView.setTag(mDatas.get(i));      mTextView.setOnClickListener(this);      layout.addView(mTextView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, - 2));    }    scrollView.addView(layout);    }    return scrollView;}

工具类:

public class DrawableUtil {  /**   * 创建随机背景的drawable   * @return   */  public static GradientDrawable createRandomDrawable(){    GradientDrawable drawable = new GradientDrawable();    drawable.setCornerRadius(Util.px2dip(5));    Random random = new Random();    int red = random.nextInt(200) + 20;    int green = random.nextInt(200) + 20;    int blue = random.nextInt(200) + 20;    int color = Color.rgb(red, green, blue);    drawable.setColor(color);    return drawable;  }    /**     * 创建带有背景的drawable     * @return     */    public static GradientDrawable createDrawable(int color){      GradientDrawable drawable = new GradientDrawable();      drawable.setCornerRadius(Util.px2dip(5));      drawable.setColor(color);      return drawable;  }  /**   * 状态选择器   * @param press   * @param normal   * @return   */  public static StateListDrawable createStateDrawable(Drawable press, Drawable normal){    StateListDrawable drawable = new StateListDrawable();    //按下    drawable.addState(new int[]{android.R.attr.state_pressed}, press);    //正常    drawable.addState(new int[]{}, normal);    return drawable;  }}

希望本文所述对大家Android程序设计有所帮助。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表