使用FlexboxLayout创建灵活的布局
原标题:Build flexible layouts with FlexboxLayout
链接:https://android-developers.googleblog.com/2017/02/build-flexible-layouts-with.html
作者:Takeshi Hagikura (开发者程序工程师)
翻译:arjinmc
去年,Google I / O发布了ConstraintLayout,它使你能够在维护平面视图层次结构的同时构建复杂的布局。它也在Android Studio的可视化布局编辑器中完全支持。
同时,我们开源的FlexboxLayout将CSS Flexible Layout模块的相同功能移植到Android。这里有一些 FlexboxLayout特别有效的情况。
FlexboxLayout可以解释为高级LinearLayout,因为这两个布局都会顺序对齐其子视图。FlexboxLayout与LinearLayout之间的显著差异是FlexboxLayout有包装的特性。
那就是说,如果你加入了属性flexWrap="wrap",如果在当前行的左边没有足够的空间给下一个view时,FlexboxLayout会自动加一行,如下图所示。
各种屏幕尺寸的布局
考虑到这个特点,让我们来看一下你想要依次放置视图,但如果可用空间发生变化(由于设备因素,方向更改或多窗口模式下的窗口调整大小),则可以将它们移动到新行。
Nexus 5X竖屏
Nexus 5X横屏
Pixel C启用多窗口模式,左侧分隔线。
Pixel C启用多窗口模式,分频线在中间。
Pixel C启用多窗口模式,右侧分隔线。
你需要定义多个DP-bucket布局(如layout-600dp,layout-720dp,layout-1020dp),以处理诸如LinearLayout或者传统布局的各种屏幕尺寸RelativeLayout。但是上面的对话框是用一个单独的FlexboxLayout。
该示例中使用的技术是flexWrap="wrap"如上所述设置,
<com .google.android.flexbox.flexboxlayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexwrap="wrap">
那么您可以获得以下布局,其中子视图与新行对齐,而不是溢出其父对象。
我想强调的另一种技术是将layout_flexGrow属性设置为 单个子view。这有助于在剩余空间时改善最终布局的外观。该 layout_flexGrow属性的作用类似于其中LinearLayout的layout_weight属性。这意味着 FlexboxLayout根据layout_flexGrow在同一行中为每个孩子设置的值分配剩余空间。
在下面的示例中,它假定每个孩子的layout_flexGrow 属性设置为1,所以可用空间将均匀分布到它们中。
<android .support.design.widget.TextInputLayout
android:layout_width="100dp"
android:layout_height="wrap_content"
app:layout_flexgrow="1">
您可以在GitHub存储库中查看完整的布局xml文件。
RecyclerView集成
另一个优点FlexboxLayout是可以与RecyclerView集成。随着最新版本的Alpha版本的FlexboxLayoutManager扩展RecyclerView.LayoutManager,现在你可以以更多的内存高效的方式在可滚动容器中使用Flexbox功能。
请注意,你仍然可以实现滚动Flexbox的容器FlexboxLayout包裹着 ScrollView。但是,如果布局中包含的项目数量较大,则可能会遇到jankiness甚至OutOfMemoryError,因为FlexboxLayout用户滚动时不会将视图回收到屏幕上的视图。
(如果你想详细了解RecyclerView的详细信息,你可以检查出从Android的UI工具包的团队,如视频1,2)
一个真实世界的例子,其中RecyclerView集成是非常有用的是对于像谷歌照片应用程序或新闻应用程序的应用程序,都期望大量物品而需要处理各种物品宽度。
在FlexboxLayout的存储库中可以找到一个例子程序。你可以在存储库中看到,每个图像显示RecyclerView的宽度不同。但是通过将flexWrap设置设置为wrap,
FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
layoutManager.setFlexWrap(FlexWrap.WRAP);
并给每一个孩子设置flexGrow(如你所看到的,你可以通过配置的属性FlexboxLayoutManager和FlexboxLayoutManager.LayoutParams设置孩子的属性,而不是从XML配置)属性。
void bindTo(Drawable drawable) {
mImageView.setImageDrawable(drawable);
ViewGroup.LayoutParams lp = mImageView.getLayoutParams();
if (lp instanceof FlexboxLayoutManager.LayoutParams) {
FlexboxLayoutManager.LayoutParams flexboxLp =
(FlexboxLayoutManager.LayoutParams) mImageView.getLayoutParams();
flexboxLp.setFlexGrow(1.0f);
}
}
无论屏幕方向如何,你都可以很好地看到每个图像在布局中很合适。
如果你想查看完整的FlexboxLayout示例,可以查看:
下一步是什么?
查看其他属性的完整文档,以构建针对你的需求量身定制的灵活布局。如果你发现任何问题或功能请求,我们很乐意听到你的反馈,请在GitHub信息库中提出问题。