手把手带你写FlowLayout(流式布局)

手把手带你写FlowLayout(流式布局)流式布局在 android 中主要应用在搜索记录和用户标签 下面是效果图首先我们分析流式布局的原理 其实就是当一个子 view 加上之前的子 view 的宽度超过了父容器的宽度的时候就换行

大家好,欢迎来到IT知识分享网。

  • 流式布局在android中主要应用在搜索记录和用户标签,下面是效果图

手把手带你写FlowLayout(流式布局)

  • 首先我们分析流式布局的原理。其实就是当一个子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的大小不会超过父容器的大小。

    • 手把手带你写FlowLayout(流式布局)
    • 接下来我们到了根据子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值
  • 完成了这两步,流式布局写的差不多了,接下来我们给所有孩子设置监听

    手把手带你写FlowLayout(流式布局)

    • 监听的方法也很简单,就是根据手指按下的(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

(0)
上一篇 2025-03-12 10:00
下一篇 2025-03-12 10:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信