100行Android代码自定义一个流式布局-FlowLayout
2015-02-17 16:18
453 查看
首先来看一下 手淘HD - 商品详情 - 选择商品属性 页面的UI
商品有很多尺码,而且展现每个尺码所需要的View的大小也不同(主要是宽度),所以在从服务器端拉到数据之前,展现所有尺码所需要的行数和每一行的个数都无法确定,因此不能直接使用GridView或ListView。
如果使用LinearLayout呢?
一个LinearLayout只能显示一行,如果要展示多行,则每一行都要new一个LinearLayout出来,而且还必须要计算出每一个LinearLayout能容纳多少个尺码对应的View,实现起来也会比较复杂。
其实要实现这个功能,只需要借鉴一下CSS3的flex-box就可以了。
要实现一个Android版本的flexbox,原理非常简单,为了与Android的命名规范保持一致,我们称之为
首先新建一个
在
在
下面只列出了最核心的代码片段,完整代码已经放到Github上-AndroidFlowLayout,欢迎fork。
代码与
完整版代码已经放到Github-FlowLayout,打出来的aar包已经上传到了bintray,使用方式非常简单,只需要在项目(project)对应的
具体做法可参考 publishing gradle android library to jcenter
打包脚本可参考 flowlayout/build.gradle
有问题请留言。よろしくお願いします
商品有很多尺码,而且展现每个尺码所需要的View的大小也不同(主要是宽度),所以在从服务器端拉到数据之前,展现所有尺码所需要的行数和每一行的个数都无法确定,因此不能直接使用GridView或ListView。
如果使用LinearLayout呢?
一个LinearLayout只能显示一行,如果要展示多行,则每一行都要new一个LinearLayout出来,而且还必须要计算出每一个LinearLayout能容纳多少个尺码对应的View,实现起来也会比较复杂。
其实要实现这个功能,只需要借鉴一下CSS3的flex-box就可以了。
要实现一个Android版本的flexbox,原理非常简单,为了与Android的命名规范保持一致,我们称之为
FlowLayout。
首先新建一个
FlowLayout类,继承自
ViewGroup
在
onMeasure中根据 child views 计算出
FlowLayout高度
在
onLayout中对child views 的进行布局(layout)
下面只列出了最核心的代码片段,完整代码已经放到Github上-AndroidFlowLayout,欢迎fork。
在onMeasure中计算FlowLayout的高度
<code class="language-java hljs " style="box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; padding: 0.5em; color: rgb(0, 0, 0); border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; display: block; background-color: transparent !important;"><span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 遍历所有的子View</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">for</span> (<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> i = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>, childCount = getChildCount(); i < childCount; ++i) { View childView = getChildAt(i); <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// measure子View,并获取它的宽度和高度</span> LayoutParams childLayoutParams = childView.getLayoutParams(); childView.measure( getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, childLayoutParams.width), getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom, childLayoutParams.height)); <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> childWidth = childView.getMeasuredWidth(); <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> childHeight = childView.getMeasuredHeight(); <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 计算当前行的高度(当前行所有子View中最高的那个)</span> lineHeight = Math.max(childHeight, lineHeight); <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 把当前child view放到上一个child view的右边,如果放不下,则换行</span> <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span> (childLeft + childWidth + paddingRight > myWidth) { childLeft = paddingLeft; childTop += mVerticalSpacing + lineHeight; lineHeight = childHeight; } <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">else</span> { childLeft += childWidth + mHorizontalSpacing; } } <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> wantedHeight = childTop + lineHeight + paddingBottom; <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 计算FlowLayout所需要高度</span> setMeasuredDimension(myWidth, resolveSize(wantedHeight, heightMeasureSpec));</code>
在onLayout中对child views进行布局
代码与onMeasure非常类似,只需要根据child view的宽度和高度放到指定位置即可。
<code class="language-java hljs " style="box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; padding: 0.5em; color: rgb(0, 0, 0); border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; display: block; background-color: transparent !important;"><span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">for</span> (<span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> i = <span class="hljs-number" style="box-sizing: border-box; color: rgb(0, 136, 0);">0</span>, childCount = getChildCount(); i < childCount; ++i) { View childView = getChildAt(i); <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span> (childView.getVisibility() == View.GONE) { <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">continue</span>; } <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> childWidth = childView.getMeasuredWidth(); <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">int</span> childHeight = childView.getMeasuredHeight(); lineHeight = Math.max(childHeight, lineHeight); <span class="hljs-keyword" style="box-sizing: border-box; font-weight: bold;">if</span> (childLeft + childWidth + paddingRight > myWidth) { childLeft = paddingLeft; childTop += mVerticalSpacing + lineHeight; lineHeight = childHeight; } <span class="hljs-comment" style="box-sizing: border-box; color: rgb(136, 136, 136);">// 关键代码</span> childView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); childLeft += childWidth + mHorizontalSpacing; }</code>
完整版代码已经放到Github-FlowLayout,打出来的aar包已经上传到了bintray,使用方式非常简单,只需要在项目(project)对应的
build.gradle中添加一条dependency即可。
<code class=" hljs nginx" style="box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; padding: 0.5em; color: rgb(0, 0, 0); border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; display: block; background-color: transparent !important;"><span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">compile</span> <span class="hljs-string" style="box-sizing: border-box; color: rgb(136, 0, 0);">'com.liangfeizc:flowlayout:1.0.0<span class="hljs-variable" style="box-sizing: border-box;">@aar</span>'</span></code>
把aar包上传到 jCenter
具体做法可参考 publishing gradle android library to jcenter 打包脚本可参考 flowlayout/build.gradle
有问题请留言。よろしくお願いします
相关文章推荐
- 100行Android代码自定义一个流式布局-FlowLayout
- <android>自己写一个流式布局吧(FlowLayout)
- Android自定义流式布局-FlowLayout
- android自定义view实现流式布局(FlowLayout)和热门标签
- Android 自定义一个简单而又实用的流式Tag标签布局
- Android自定义流式布局-FlowLayout
- Android 自定义ViewGroup 实现流式布局
- iOS开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- 使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- Android-教你自作一个简单而又实用的流式Tag标签布局
- 三行代码接入,社交软件打字时底下弹出的表情布局,自定义ViewPager+页面点标+各种功能的android小框架。
- iOS开发之UI基础--纯代码自定义UItableviewcell实现一个简单的微博界面布局
- android ExpandableListView的group是一个自定义的布局,折叠图标覆盖布局上的部分内容
- ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
- Android自定义ViewGroup实现流式布局
- Android-->FlowRadioGroup(流式布局RadioGroup, 自定义View的简单使用)
- iOS 使用纯代码自定义UITableViewCell实现一个简单的微博界面布局
- android 自定义布局继承一个系统的布局会报错
- Android 流式布局FlowLayout