`

自动换行的ViewGroup:FlowLayout

阅读更多
  viewgroup简单说就是可以装view的view.今天遇到一个问题,就是需要一个可以自动根据一行中view的宽度自动换行的布局,网上找了下,没有相关的例子,但是找到了思路:自定义一个viewgroup,然后在onlayout文件里面自动检测view的右边缘的横坐标值,和你的view的parent view的况度判断是否换行显示view就可以了。因为代码比较简单,就不多说了:
public class MyViewGroup extends ViewGroup {
     private final static String TAG = "MyViewGroup";
     
     private final static int VIEW_MARGIN=2;
 
     public MyViewGroup(Context context) {
         super(context);
     }
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         Log.d(TAG, "widthMeasureSpec = "+widthMeasureSpec+" heightMeasureSpec"+heightMeasureSpec);
         
         for (int index = 0; index < getChildCount(); index++) {
             final View child = getChildAt(index);
             // measure
             child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
         }
 
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
     @Override
     protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
         Log.d(TAG, "changed = "+arg0+" left = "+arg1+" top = "+arg2+" right = "+arg3+" botom = "+arg4);
         final int count = getChildCount();
         int row=0;// which row lay you view relative to parent
         int lengthX=arg1;    // right position of child relative to parent
         int lengthY=arg2;    // bottom position of child relative to parent
         for(int i=0;i<count;i++){
             
             final View child = this.getChildAt(i);
             int width = child.getMeasuredWidth();
             int height = child.getMeasuredHeight();
             lengthX+=width+VIEW_MARGIN;
             lengthY=row*(height+VIEW_MARGIN)+VIEW_MARGIN+height+arg2;
             //if it can't drawing on a same line , skip to next line
             if(lengthX>arg3){
                 lengthX=width+VIEW_MARGIN+arg1;
                 row++;
                 lengthY=row*(height+VIEW_MARGIN)+VIEW_MARGIN+height+arg2;
                 
             }
             
             child.layout(lengthX-width, lengthY-height, lengthX, lengthY);
         }
 
     }
 
 }

  这里有个地方要注意,那就要明白ViewGroup的绘图流程:ViewGroup绘制包括两个步骤:1.measure 2.layout
  在两个步骤中分别调用回调函数:1.onMeasure()   2.onLayout()
  1.onMeasure() 在这个函数中,ViewGroup会接受childView的请求的大小,然后通过childView的 measure(newWidthMeasureSpec, heightMeasureSpec)函数存储到childView中,以便childView的getMeasuredWidth() andgetMeasuredHeight() 的值可以被后续工作得到。
  2.onLayout() 在这个函数中,ViewGroup会拿到childView的getMeasuredWidth() andgetMeasuredHeight(),用来布局所有的childView。
  3.View.MeasureSpec 与 LayoutParams 这两个类,是ViewGroup与childView协商大小用的。其中,View.MeasureSpec是ViewGroup用来部署 childView用的, LayoutParams是childView告诉ViewGroup 我需要多大的地方。
  4.在View 的onMeasure的最后要调用setMeasuredDimension()这个方法存储View的大小,这个方法决定了当前View的大小。
  


http://www.cnblogs.com/slider/archive/2011/11/24/2262161.html

还可以试试这个:
import android.content.Context;

import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

/**
 *
 * @author RAW
 */
public class FlowLayout extends ViewGroup {
    private final static int PAD_H = 2, PAD_V = 2; // Space between child views.
    private int mHeight;

    public FlowLayout(Context context) {
        super(context);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
        final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
        final int count = getChildCount();
        int xpos = getPaddingLeft();
        int ypos = getPaddingTop();
        int childHeightMeasureSpec;
        if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST)
            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
        else
            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        mHeight = 0;
        for(int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if(child.getVisibility() != GONE) {
                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
                final int childw = child.getMeasuredWidth();
                mHeight = Math.max(mHeight, child.getMeasuredHeight() + PAD_V);
                if(xpos + childw > width) {
                    xpos = getPaddingLeft();
                    ypos += mHeight;
                }
                xpos += childw + PAD_H;
            }
        }
        if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
            height = ypos + mHeight;
        } else if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
            if(ypos + mHeight < height) {
                height = ypos + mHeight;
            }
        }
        height += 5; // Fudge to avoid clipping bottom of last row.
        setMeasuredDimension(width, height);
    } // end onMeasure()

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int width = r - l;
        int xpos = getPaddingLeft();
        int ypos = getPaddingTop();
        for(int i = 0; i < getChildCount(); i++) {
            final View child = getChildAt(i);
            if(child.getVisibility() != GONE) {
                final int childw = child.getMeasuredWidth();
                final int childh = child.getMeasuredHeight();
                if(xpos + childw > width) {
                    xpos = getPaddingLeft();
                    ypos += mHeight;
                }
                child.layout(xpos, ypos, xpos + childw, ypos + childh);
                xpos += childw + PAD_H;
            }
        }
    } // end onLayout()
}


How to Implement Flipboard Animation on Android


还可以看看这个:
Android标签流控件的实现
http://www.open-open.com/lib/view/open1425526186540.html

自动换行的线性布局,当排满一排或者一列,自动排列在下一行或者下一列。和另外一个FlowLayout(见下面的相关项目)不同的是,该项目可以设置对齐方式与排列方向,非常灵活。
https://github.com/ApmeM/android-flowlayout


Android TagFlowLayout完全解析 一款针对Tag的布局
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0914/3448.html

https://github.com/2dxgujun/AndroidTagGroup

流式布局,支持多种布局优化
https://github.com/lankton/android-flowlayout
  • 大小: 18.5 KB
分享到:
评论
1 楼 yq135314 2012-07-26  
谢谢,第二种不错,可以和ScrollView一起用,进行滚屏,太感谢了。

相关推荐

    Android 标签,可以自动换行的ViewGroup

    为了实现真正的自动换行,开发者通常会使用`FlowLayout`或自定义的ViewGroup。`FlowLayout`是一个开源的第三方库,它允许子视图在水平方向上填充,当一行填满后,会自动开始新的一行。这样,即使在不同的设备或屏幕...

    多个view自动换行

    更常见的一种解决方案是使用`FlowLayout`,这是一个可以自动换行的布局,但Android SDK并未提供原生的`FlowLayout`。我们可以创建一个自定义的`ViewGroup`来实现这个功能。例如,提供的`MyViewGroup.java`可能就是一...

    解决自动换行,自适应高度。常见与标签样式的 ViewGroup

    当我们在设计用户界面时,有时需要创建一个标签样式(Tag-style)的ViewGroup,这种组件通常包含多个标签,它们需要自动换行以适应有限的屏幕宽度,并且整个组件能自适应高度,以显示所有标签而不被截断。"解决自动...

    添加标签,自动换行,并可以多选,单选

    在这个场景中,提到的"添加标签,自动换行,并可以多选,单选"是一个对FlowLayout的增强,使得开发者能够更灵活地构建UI,特别是处理大量可选择的项目时。 1. **FlowLayout**: FlowLayout是Java Swing或Android中的...

    Android自定义ViewGroup之FlowLayout(三)

    FlowLayout的核心特性是,它会自动将子View按照从左到右的顺序添加到当前行,如果当前行剩余空间不足以容纳下一个子View,那么就会自动换行。这种方式类似于HTML中的`&lt;div&gt;`布局或者CSS的`display: flex; flex-wrap:...

    Android自定义标签view——可自动换行

    本项目“Android自定义标签view——可自动换行”提供了一种解决方案,使得在界面上显示的标签可以按照屏幕大小自动换行,从而避免了内容溢出的问题。下面将详细介绍这个项目及其相关知识点。 1. 自定义View:在...

    一行代码搞定标签换行,自定义ViewGroup

    `FlowLayout`是一种自定义的`ViewGroup`,它允许子视图(标签)根据需要自动换行,从而在界面上呈现出美观且适应性强的布局效果。 `FlowLayout`的实现主要基于两个关键点:计算每个标签的尺寸以及在布局过程中决定...

    Android 自定义ViewGroup 实战篇 -> 实现FlowLayout源码程序

    FlowLayout是一种流式布局,它的主要特点是子视图会从左到右排列,当一行填满后,会自动换行。这种布局方式特别适合展示一系列大小不一的视图,如标签、按钮或者图片。 接着,我们探讨如何创建FlowLayout。首先,...

    flowlayout 流式布局

    流式布局(FlowLayout)是一种在Android开发中常用的布局方式,它允许子视图(views)按照从左到右、从上到下的顺序排列,并在容器的边界处自动换行。这种布局非常适合展示不固定数量或者大小的元素,比如在创建一个...

    android商品属性选择标签控件,可实现自动换行

    这里我们将详细探讨如何实现一个支持自动换行、默认选中首个标签,并且能够进行多选的标签控件。 首先,我们来看"标签选择"这个概念。标签(Tag)是一种常用的数据展示方式,通常用于表示某个对象或内容的特性。在...

    android 实现自动换行的流布局

    在Android开发中,流式布局(FlowLayout)是一种常见的布局方式,它允许子视图(View)按照特定顺序从左到右排列,当一行填满时自动换行。这种布局在设计如网格、目录或者卡片展示等场景时非常实用。在Android原生库...

    Android 自定义ViewGroup 实战篇 实现FlowLayout.rar

    FlowLayout的主要功能是在水平方向上排列子View,当一行无法容纳更多的子View时,会自动换行。这种布局方式常用于展示多列卡片、标签或者按钮等,使得布局更加灵活。 创建自定义FlowLayout的步骤如下: 1. **创建...

    Android自定义ViewGroup之实现FlowLayout流式布局

    FlowLayout是一种布局方式,它的特点在于当子视图在一行内无法完全显示时,会自动换行继续排列。这种布局适用于需要动态排列且可能溢出一行的情况,如关键词标签、搜索热词列表等。在Android SDK中并未内置...

    FlowLayout

    1. **自动换行**:当一行的总宽度达到Flowlayout的宽度时,剩余的子View会自动换行到下一行。 2. **对齐方式**:默认情况下,所有子View都左对齐。但可以通过自定义属性设置不同的对齐方式,如居中或右对齐。 3. **...

    android流动布局demo

    在Android开发中,流动布局(FlowLayout)是一种非官方但非常实用的布局管理器,它允许子视图在一行内水平排列,当一行填满时,会自动换行到下一行,类似于网页中的流式布局。这个"android流动布局demo"为我们提供了...

    Android流式标签可动态添加FlowLayout

    在这个场景下,`FlowLayout`的主要功能是管理其子视图(通常是`TextView`,用于显示标签),并根据子视图的大小和数量自动调整它们的位置,实现水平方向上的自动换行。 `FlowLayout`的实现原理主要涉及到以下几个...

    实现热门标签控件 FlowLayout

    `FlowLayout`就是一种实现这种效果的布局管理器,它可以使得子视图按照从左到右、从上到下的顺序排列,当一行排满时会自动换行。本篇文章将详细介绍如何利用`FlowLayout`来实现这样的效果。 首先,我们需要理解`...

Global site tag (gtag.js) - Google Analytics