`

流布局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>  

 

分享到:
评论

相关推荐

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

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

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

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

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

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

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

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

    小程序源码 瀑布流布局 (代码+截图)

    小程序源码 瀑布流布局 (代码+截图)小程序源码 瀑布流布局 (代码+截图)小程序源码 瀑布流布局 (代码+截图)小程序源码 瀑布流布局 (代码+截图)小程序源码 瀑布流布局 (代码+截图)小程序源码 瀑布流布局 (代码+截图)小...

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

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

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

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

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

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

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

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

    Android完美适配瀑布流布局代码

    瀑布流布局,又称Masonry Layout,是一种常见的网页和移动应用界面设计模式,尤其在图片展示、电商产品列表等场景中广泛应用。在Android平台上实现瀑布流布局,可以为用户提供美观且富有动态感的浏览体验。本篇文章...

    Android 自定义瀑布流式布局

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

    瀑布流布局功能源码.zip

    瀑布流布局,又称Masonry布局或Pinterest布局,是一种在网页设计和移动应用中常见的图片展示方式,尤其在图片分享类应用中广泛使用。这种布局方式的特点是将元素以多列的形式排列,每列中的元素间距相等,但各列之间...

    瀑布流布局

    瀑布流布局,也被称为Masonry布局,是一种常用于图片展示或网页设计的布局方式,它模仿了瀑布下落的效果,使得页面上的元素可以自适应地排列,每列的高度不固定,根据内容填充。这种布局模式在电子商务网站、社交...

    瀑布流布局的多种实现方式及其比较研究.pdf

    瀑布流布局的多种实现方式及其比较研究 瀑布流布局是指一种网站页面布局方式,通过将内容以瀑布状的形式呈现,提供了良好的用户体验。该布局方式突破了传统网页的布局方式,不仅设计独特,更能带来良好的用户体验,...

    jQuery点击添加图片瀑布流布局效果

    【jQuery点击添加图片瀑布流布局效果】是一种常见的前端网页设计技术,主要应用于展示大量图片时,提供美观且高效的浏览体验。瀑布流布局,也被称为Pinterest式布局,因其图像逐个下落并形成类似瀑布的效果而得名。...

    瀑布流图片布局以及打开点击图片动画特效

    瀑布流图片布局是一种常见的网页设计模式,常用于展示图片丰富的网站,如摄影网站、社交媒体或者电商产品展示等。它的特点是图片以多列的形式排列,每一列的高度不固定,随着图片内容的变化而自然下落,形成一种类似...

    swift-用swift写的简单的瀑布流布局用于UICollectionView支持拖拽布局

    这篇项目以"swift-用swift写的简单的瀑布流布局用于UICollectionView支持拖拽布局"为标题,意味着它提供了一个实现瀑布流布局的解决方案,并且集成了拖拽功能。在iOS应用开发中,用户交互体验至关重要,拖拽布局能...

    jQuery实现的瀑布流布局的图片特效代码

    瀑布流布局,也被称为Masonry布局,是一种常用于图片展示的网页设计模式,它使得页面中的元素能够像瀑布一样从上到下自然流动,每行的元素宽度不固定,但保持了良好的视觉平衡。在本案例中,我们将讨论如何利用...

    Masonry图片筛选功能瀑布流布局画廊.zip

    在IT领域,瀑布流布局(Masonry Layout)是一种常见的网页设计模式,特别是在图片展示和画廊应用中。这种布局方式可以有效地展示大量的图片,让用户在有限的屏幕空间内看到尽可能多的内容,同时保持视觉上的平衡和...

    jQuery响应式图片瀑布流布局代码.zip

    【jQuery响应式图片瀑布流布局代码】是一种网页设计技术,旨在提供一种动态、美观且适应不同设备屏幕尺寸的图片展示方式。在这个项目中,开发者利用了JavaScript库jQuery的高效特性和响应式设计原理来实现这一功能。...

Global site tag (gtag.js) - Google Analytics