0%

FlexboxLayout实现不规则图片墙

前提:服务器返回图片布局形式,图片大小。如下图的布局形式为[1,3,2,1]

Flexbox

1. 了解FlexboxLayout功能

https://github.com/google/flexbox-layout
https://www.oschina.net/news/73442/google-flexbox-layout

FlexboxLayout支持的属性:

属性 作用
flexDirection 主轴的方向 row:row-reverse:column:column-reverse
flexWrap 支持的换行方式 nowrap:wrap:wrap-reverse
justifyContent 在主轴上的对齐方式 flex-start:flex-end:center:space-between:space-around
alignItems 在副轴上的对齐方式 flex-start:flex-end:center:baseline:stretch
alignContent 多根轴线的对齐方式 flex-start:flex-end:center:space-between:space-around
showDividerHorizontal 水平分割线 none:beginning:middle:end
dividerDrawableHorizontal 资源 drawable
showDividerVertical 垂直分割线 none:beginning:middle:end
dividerDrawableVertical 资源 drawable
showDivider 分割线 none:beginning:middle:end
dividerDrawable 资源 drawable

FlexboxLayout的child view可设置的属性,略。

2. 解决方案

使用以下属性,同时设置好ImageView的宽高即可。
方法1:

app:flexDirection=“row”
app:flexWrap=“wrap”
app:justifyContent=“space_between”
app:showDividerHorizontal=“middle”
app:dividerDrawableHorizontal="@drawable/shape_flexbox_divider"

设置详解:

  1. 主轴方向为行
  2. 自动换行
  3. 在一行内的对齐方式是图片之间置空
  4. 显示水平分割线,在每行之间显示。

方法2:

app:flexDirection=“row”
app:flexWrap=“wrap”
app:showDivider=“middle”
app:dividerDrawable="@drawable/shape_flexbox_divider"

设置详解:

  1. 主轴方向为行
  2. 自动换行
  3. 同时显示水平和垂直的分割线,在图片之间显示,在行之间显示。

注意:由于使用的是dp单位,在计算时有除法可能出现误差,一定要计算精确,要不然会出现意外的换行(我用方法2就出现了意外换行,计算不精确)

3. 实现

FlexboxLayout的xml配置:

1
2
3
4
5
6
7
8
9
10
11

<com.google.android.flexbox.FlexboxLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexDirection="row"
app:flexWrap="wrap"
app:justifyContent="space_between"
app:showDividerHorizontal="middle"
app:dividerDrawableHorizontal="@drawable/shape_flexbox_divider"
/>

分割线资源文件配置:

1
2
3
4
5
6
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:width="4dp"
android:height="4dp"/>
<solid android:color="@android:color/white"/>

</shape>

伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
private ArrayList<Info> photos; //图片信息,包含宽高
private ArrayList<ImageView> viewCache; //缓存ImageView
private int[] layout = {1, 3, 2, 1}; //布局形式
private int dividerWidth; //分割线大小
private WIDTH; //FlexboxLayout的宽度

private void setPhotoContent() {
flexboxLayout.removeAllViews();
createPhotoView(photos.size());
int position = 0;
for (int i = 0; i < layout.length; i++) {
int w = (WIDTH -(layout[i] - 1) * dividerWidth) / layout[i];
int h = w * info.getHeight() / info.getWidth();
for (int j = 0; j < layout[i]; j++) {
setImageViewSize(viewCache(position), w, h);
//其他设置,如加载图片
setUri(viewCache.get(position), photos.get(position));
flexboxLayout.addView(view);
position++;
}
}
}

private void setImageViewSize(ImageView view, int w, int h) {

}

private void setUri(ImageView view, Info info) {

}

private void createPhotoView(int count) {
//创建所需数量ImageView, 图片数量太多的话,该方案不适用
while (count > viewCache.size()) {
viewCache.add(new ImageView());
}
}