`

流布局Flowlayoiut

 
阅读更多

整个的原理同 : http://username2.iteye.com/admin/blogs/2229583

 

直接上代码:

 1 ViewGroup 的使用

/**
 * 个人理解,容器的布局执行过程 1 父容器调用measureChildren 2 子容器调用measure 计算当前容器的宽高和其子容器的宽高 3
 * 当前执行的这个子容器触发onMeasure ,设置当前子容器的宽高 4 当前容器调用onLayout , 来展示当前容器的显示
 */
public class CustomFlowlayoutContainer extends ViewGroup {

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

	// attrs 是xml中配置的参数会传到这里
	public CustomFlowlayoutContainer(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
		return new MarginLayoutParams(getContext(), attrs);
	}

	/**
	 * 
	 * 根据父类传入的 widthMeasureSpec和heightMeasureSpec计算本类和其子类的宽高
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		// 获得它的父容器为它设置的测量模式和大小
		int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);//容器的模式为fill_parent或者固定大小,所以这个值为容器宽度
		int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
		int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
		int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

		// 如果是warp_content情况下,记录宽和高
		int width = 0;
		int height = 0;
		/**
		 * 记录每一行的宽度,width不断取最大宽度
		 */
		int lineWidth = 0;
		/**
		 * 每一行的高度,累加至height
		 */
		int lineHeight = 0;

		int cCount = getChildCount();

		// 遍历每个子元素
		for (int i = 0; i < cCount; i++) {
			View child = getChildAt(i);
			// 测量每一个child的宽和高
			measureChild(child, widthMeasureSpec, heightMeasureSpec);
			// 得到child的lp
			MarginLayoutParams lp = (MarginLayoutParams) child
					.getLayoutParams();
			// 当前子控件实际占据的宽度
			int childWidth = child.getMeasuredWidth() + lp.leftMargin
					+ lp.rightMargin;
			// 当前子控件实际占据的高度
			int childHeight = child.getMeasuredHeight() + lp.topMargin
					+ lp.bottomMargin;
			/**
			 * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行
			 */
			if (lineWidth + childWidth > sizeWidth) {
				width = Math.max(lineWidth, childWidth);// 取最大的
				lineWidth = childWidth; // 重新开启新行,开始记录
				// 叠加当前高度,
				height += lineHeight;
				// 开启记录下一行的高度
				lineHeight = childHeight;
			} else
			// 否则累加值lineWidth,lineHeight取最大高度
			{
				lineWidth += childWidth;
				lineHeight = Math.max(lineHeight, childHeight);
			}
			// 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较
			if (i == cCount - 1) {
				width = Math.max(width, lineWidth);
				height += lineHeight;
			}

		}
		//一般流式布局宽为EXACTLY所以数值为sizeWidth,高为wrap_content 为计算的height
		setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth
				: width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight
				: height);

	}

	/** 
     * 存储所有的View,按行记录 
     */  
    private List<List<View>> mAllViews = new ArrayList<List<View>>();  
    /** 
     * 记录每一行的最大高度 
     */  
    private List<Integer> mLineHeight = new ArrayList<Integer>();  
    
	/**
	 * 对其所有childView进行定位
	 */
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		//每次布局前要清零
	    mAllViews.clear();  
        mLineHeight.clear();  
  
        int width = getWidth();  
        
        int lineWidth = 0;  
        int lineHeight = 0;  
        // 存储每一行所有的childView  
        List<View> lineViews = new ArrayList<View>(); 
 
		int cCount = getChildCount();
	    // 遍历所有的孩子  
        for (int i = 0; i < cCount; i++)  
        {  
            View child = getChildAt(i);  
            MarginLayoutParams lp = (MarginLayoutParams) child  
                    .getLayoutParams();  
            int childWidth = child.getMeasuredWidth();  
            int childHeight = child.getMeasuredHeight();  
  
            // 如果已经需要换行  
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width)  
            {  
                // 记录这一行所有的View以及最大高度  
                mLineHeight.add(lineHeight);  
                // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView  
                mAllViews.add(lineViews);  
                lineWidth = 0;// 重置行宽  
                lineViews = new ArrayList<View>();  
            }  
            /** 
             * 如果不需要换行,则累加 
             */  
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;  
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin  
                    + lp.bottomMargin);  
            lineViews.add(child);  
        }  
        // 记录最后一行  
        mLineHeight.add(lineHeight);  
        mAllViews.add(lineViews);  
  
        int left = 0;  
        int top = 0;  
        // 得到总行数  
        int lineNums = mAllViews.size();  
        for (int i = 0; i < lineNums; i++)  
        {  
            // 每一行的所有的views  
            lineViews = mAllViews.get(i);  
            // 当前行的最大高度  
            lineHeight = mLineHeight.get(i);  
  
            Log.e("位置", "第" + i + "行 :" + lineViews.size() + " , " + lineViews);  
            Log.e("位置", "第" + i + "行, :" + lineHeight);  
  
            // 遍历当前行所有的View  
            for (int j = 0; j < lineViews.size(); j++)  
            {  
                View child = lineViews.get(j);  
                if (child.getVisibility() == View.GONE)  
                {  
                    continue;  
                }  
                MarginLayoutParams lp = (MarginLayoutParams) child  
                        .getLayoutParams();  
  
                //计算childView的left,top,right,bottom  
                int lc = left + lp.leftMargin;  
                int tc = top + lp.topMargin;  
                int rc =lc + child.getMeasuredWidth();  
                int bc = tc + child.getMeasuredHeight();  
  
                Log.e("位置", child + " , l = " + lc + " , t = " + t + " , r ="  
                        + rc + " , b = " + bc);  
  
                child.layout(lc, tc, rc, bc);  
                  
                left += child.getMeasuredWidth() + lp.rightMargin  
                        + lp.leftMargin;  
            }  
            left = 0;  
            top += lineHeight;  
        }  
	}
}

 2 Activity代码

 

public class TestFlowlayoutActivity extends Activity implements OnClickListener {
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_flowlayout );
		//DisplayUtil displayUtil = new DisplayUtil(getWindowManager());
	}
	@Override
	public void onClick(View v) {

		switch (v.getId()) {
		case R.id.start:
		 
			break;
		default:
			break;
		}
	}
}

 3 xml 代码

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:background="#E1E6F6"  
    android:orientation="vertical" >  
  
    <com.example.fragmentdemo1.widget.CustomFlowlayoutContainer
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content" >  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="Welcome" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="IT工程师" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="努力啊" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp" 
           	android:background="@drawable/button_bg"
            android:text="学习挣钱" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp" 
           	android:background="@drawable/button_bg"
            android:text="攒钱娶媳妇了" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp" 
           	android:background="@drawable/button_bg"
            android:text="攒钱买房子了" />  
  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="攒钱买车子了,什么时候出去玩玩" />  
        <TextView  
           	android:layout_width="wrap_content"
           	android:layout_height="wrap_content"
           	android:layout_margin="4dp"
           	android:background="@drawable/button_bg"
            android:text="一辈子就这样没了,该出去休息一下了" />
        
    </com.example.fragmentdemo1.widget.CustomFlowlayoutContainer>  
      
    </LinearLayout> 

 4 背景代码button_bg.xml

  

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >  
  	<!-- 填充色 -->
    <solid android:color="#FFFFFF" >  
    </solid>  
  	<!-- 圆角 -->
    <corners android:radius="20dp"/>  
    <!-- 描边 -->
    <stroke android:color="#C9C9C9" android:width="2dp"/>  
      
    <padding  
        android:bottom="2dp"  
        android:left="10dp"  
        android:right="10dp"  
        android:top="2dp" />  
  
</shape>  

 

分享到:
评论

相关推荐

    微信小程序源码 瀑布流布局(学习版)

    微信小程序源码 瀑布流布局(学习版)微信小程序源码 瀑布流布局(学习版)微信小程序源码 瀑布流布局(学习版)微信小程序源码 瀑布流布局(学习版)微信小程序源码 瀑布流布局(学习版)微信小程序源码 瀑布流布局(学习版)...

    微信小程序 瀑布流布局 (源码)

    微信小程序 瀑布流布局 (源码)微信小程序 瀑布流布局 (源码)微信小程序 瀑布流布局 (源码)微信小程序 瀑布流布局 (源码)微信小程序 瀑布流布局 (源码)微信小程序 瀑布流布局 (源码)微信小程序 瀑布流布局 (源码)微信...

    微信小程序——瀑布流布局(截图+源码).zip

    微信小程序——瀑布流布局(截图+源码).zip 微信小程序——瀑布流布局(截图+源码).zip 微信小程序——瀑布流布局(截图+源码).zip 微信小程序——瀑布流布局(截图+源码).zip 微信小程序——瀑布流布局(截图+...

    纯css3实现横向瀑布流布局,横向瀑布流代码.zip

    瀑布流布局,又称Masonry布局,是一种常见的网页布局方式,尤其在展示图片或者商品时非常流行。这种布局的特点是每个元素(通常是图片)的宽度不固定,但它们的左侧边缘会对齐,形成一种自适应的错落效果,类似于...

    瀑布流布局 WaterfallLayout

    瀑布流布局,也被称为Masonry布局或Pinterest布局,是一种常用于网页和移动应用中的展示大量图像或内容的方式。它的特点是内容以多列的形式排列,每一列的高度不固定,随着页面滚动,新内容会自然地填充到列的底部,...

    微信小程序-实现瀑布流布局demo源代码

    本教程将通过一个具体的实例——“微信小程序-实现瀑布流布局demo”来探讨如何在微信小程序中实现瀑布流布局和无限下拉加载功能。 首先,我们要理解瀑布流布局。这是一种常见的网页设计布局方式,其特点是以多列...

    微信小程序图片瀑布流布局demo

    在这个“微信小程序图片瀑布流布局demo”中,我们将会探讨如何在微信小程序中实现图片的瀑布流展示,这是一种常见的网页和移动应用设计模式,尤其适用于图片分享和展示类应用。 瀑布流布局,又称为无限滚动或荷叶边...

    瀑布流布局,点击加载更多效果

    瀑布流布局,也被称为Masonry布局,是一种常用于图片展示或商品列表的网页设计模式,它的特点是元素在页面上自适应地垂直排列,形成一种类似瀑布倾泻的效果。这种布局方式能够有效地利用屏幕空间,使得视觉效果更加...

    白色纯净简洁的瀑布流布局html5模板_html5 bootstrap 响应式模板UI前端源码.rar

    瀑布流布局是一种常见的网页设计模式,它以一种不规则的方式排列元素,使页面看起来像瀑布一样自上而下流动。这种布局方式常用于图片展示、社交媒体应用和电子商务网站,因为它可以提供良好的视觉体验,使用户在浏览...

    手摸手,带你实现移动端H5瀑布流布局.doc

    移动端H5瀑布流布局技术 移动端H5瀑布流布局是一种流行的网页布局方式,视觉上呈现出一种像瀑布一样垂直落下的排版。每张图片并不是显示的正正方方的,而是有的长有的短,呈现出一种不规则的形状。但是它们的宽度...

    原生JS瀑布流布局,无限加载

    瀑布流布局,也被称为Masonry布局,是一种网页设计布局方式,常见于图片分享网站和电商产品展示页面。这种布局的特点是元素逐行排列,每行中的元素宽度不固定,但高度自适应,使得整体视觉效果像瀑布一样从上至下...

    源代码:网站制作瀑布流布局.rar

    瀑布流布局,又称Masonry布局,是一种常见的网页设计布局方式,尤其在图片展示类网站中广泛应用。这种布局方式模仿了瀑布或流水下落的效果,每一列的元素自上而下依次排列,每列的高度根据其内容自动调整,使得页面...

    Android 瀑布流布局库源码

    瀑布流布局在Android应用开发中是一种常见的展示方式,尤其在电商、社交等应用中用于商品或图片的展示。它的特点是视图元素不均匀分布,像瀑布一样从上至下流淌,每一行的列数可能不同,形成一种错落有致的效果。在...

    仿花瓣瀑布流布局主题petal_2.0

    瀑布流是今年流行的一种页面布局方式,淘宝哇喔,蘑菇街,点点等都采用了瀑布流布局。花瓣主题集成了日志一键分享功能,对于提升网站流量非常有用。另外petal对于浏览器的兼容也是不错的,支持目前所有主流浏览器,...

    jQuery瀑布流布局伸缩放大特效.zip

    jQuery瀑布流布局是一种常见的网页设计技术,用于展示内容时创建类似瀑布般的多列布局,使得内容在页面上自适应地填充空间,同时保持各元素之间的间距一致。这种布局方式尤其适用于图片展示、商品目录或者博客文章...

    Android版的瀑布流布局

    瀑布流布局,又称Masonry Layout,是一种常见的网页和移动应用设计模式,特别是在图片展示和电商应用中尤为常见。在Android平台上实现瀑布流布局,能够使内容以美观且适应不同屏幕尺寸的方式排列,用户可以在滚动时...

    Web流布局实例

    Web流布局,也被称为“液态布局”或“灵活布局”,是网页设计中的一种布局方式,它允许网页元素根据浏览器窗口大小的变化而自动调整自身尺寸,以保持良好的可读性和用户体验。这种布局模式在响应式网页设计中尤其...

    Android 自定义瀑布流式布局

    在Android开发中,瀑布流式布局(Waterfall Layout)是一种常见的UI设计模式,它主要用于展示内容丰富的列表,如图片、商品、文章等,通常应用于新闻客户端、电商应用等。这种布局方式模仿了真实世界中瀑布流水的...

    Android 瀑布流 布局实现

    瀑布流布局,又称为瀑布流式布局或者无限滚动布局,是一种常见的移动应用和网页设计布局方式,尤其在图片展示和电商应用中非常流行。它的特点在于,内容以多列的形式呈现,每一列中的元素高度不一,使得整体视觉效果...

    RecyclerView瀑布流布局项目参考

    瀑布流布局(Waterfall Layout),又称流式布局,通常用于展示图片或者商品,这种布局方式使得屏幕空间得到充分利用,视觉效果更加美观。本项目参考着重于在Android Studio环境下如何实现RecyclerView结合瀑布流布局...

Global site tag (gtag.js) - Google Analytics