Android-使用FlexboxLayout轻松实现流式布局
产品需求:
1.列表筛选显示标签,标签按文本长度展示,不固定长度,当长度最大为168时显示省略
2.2行以内全部展示,超过2行,只展示2行;点击展开,展示2行及以上,点击收起,展示2行。
按照以往实现方式,直接使用recylerview设置布局方式为Gridview,然后扒拉扒拉一顿写,发现完全不合要求。
实现技术难点:
长度不固定、高度不固定。
然后了解到google出了一个布局控件,引入flexlayout,完美解决。
FlexboxLayout:
FlexboxLayout
是去年 Google I/O
上开源的一个布局控件,FlexboxLayout可以理解为高级的linearLayout,它提供了FlexboxLayoutManager,可以轻松实现子布局换行显示。
使用
项目中添加依赖:
//流式布局 implementation 'com.google.android:flexbox:1.0.0'
简单实现
创建FlexboxLayoutManager,并为recylerview设置layoutManager。
//设置流式布局
flexboxLayoutManager = new FlexboxLayoutManager(mActivity);
flexboxLayoutManager.setFlexWrap(FlexWrap.WRAP); //设置是否换行
flexboxLayoutManager.setFlexDirection(FlexDirection.ROW); // 设置主轴排列方式
flexboxLayoutManager.setAlignItems(AlignItems.STRETCH);
flexboxLayoutManager.setJustifyContent(JustifyContent.FLEX_START);
rvCondition.setLayoutManager(flexboxLayoutManager);
recylerview子布局。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" xmlns:tools="http://schemas.android.com/tools" android:background="@color/_F4F8FF" android:layout_marginRight="10dp" android:layout_marginBottom="10dp" android:id="@+id/ll_layout" android:gravity="center_vertical"> <TextView android:id="@+id/tv_condition" style="@style/textviewCommonStyle" android:layout_width="wrap_content" android:layout_height="28dp" android:ellipsize="end" android:layout_weight="1" android:maxWidth="168dp" android:textSize="13sp" android:textColor="@color/_001A37" android:maxLines="1" tools:text="奥迪A3 2019款Limousine 35 TFSI 运动型 国 VI11111111111111111111111111111111111" android:paddingLeft="8dp" android:gravity="center_vertical" android:paddingTop="0dp" android:paddingBottom="0dp" android:paddingEnd="0dp" /> <ImageView android:id="@+id/iv_delete" android:layout_width="18dp" android:layout_height="24dp" android:paddingEnd="8dp" android:paddingTop="8dp" android:paddingBottom="8dp" android:paddingStart="2dp" android:src="@drawable/ic_delete2" android:layout_gravity="end|center_vertical"/> </LinearLayout>
流式布局是实现了,现在的问题是怎么获取高度来判断当前行数呢
这里我是通过recylerview的最后一个item展示来判断,通过行数来设置当前recylerview的高度。
private void setCurMode(int layoutPosition, View itemView) { if(layoutPosition != conditionList.size() -1) return; itemView.post(new Runnable() { @Override public void run() { //判断当前显示几行 Log.e("fg","绘制完毕"); lines = Math.ceil(rvCondition.getHeight() / DeviceUtils.dpToPixel(mActivity, 38)); Log.e("fg","当前行数--"+lines); if(lines <= 1){ tvClose.setVisibility(View.GONE); tvClearAll.setVisibility(View.GONE); }else if(lines == 2){ isClosed = true; tvClose.setVisibility(View.GONE); tvClearAll.setVisibility(View.VISIBLE); }else if(lines >= 3){ if(isClosed) { tvClose.setVisibility(View.VISIBLE); tvClose.setText("展开"); tvClearAll.setVisibility(View.GONE); }else{ tvClose.setVisibility(View.VISIBLE); tvClose.setText("收起"); tvClearAll.setVisibility(View.VISIBLE); } } setCurLabelHeight(!isClosed); } }); }
setCurLabelHeight()
private void setCurLabelHeight(boolean isOpen) { ViewGroup.LayoutParams layoutParams = rvCondition.getLayoutParams(); if(!isOpen && lines >= 2){ //收缩 设置为2行 layoutParams.height = DeviceUtils.dpToPixel(mActivity,38 * 2); }else{ //展开,设置为包裹 layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; } rvCondition.setLayoutParams(layoutParams); }
实现效果:
某人说这样显示不好,每次操作一个删除或者添加标签时,都会去重置recylerview的高度后,再设置一次recyclerview的布局,后续操作的话换一种思路实现。
通过按钮点击监听来判断当前是否可折叠,再折叠,同理,先判断是否可展开再展开。
1.当前是否可折叠。
//是否可以折叠 private boolean canFold() { return Math.ceil(layoutManager.getHeight() / dp2px(40)) > 2; }
2.当前是否可展开。
//是否可以展开 private boolean canOpen() { return layoutManager.findLastVisibleItemPosition() != list.size() -1; }
相关参考: