Android-使用FlexboxLayout轻松实现流式布局 - Tears_fg

时间:2024-02-16 21:25:09

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;
    }

 相关参考:

1.https://www.jianshu.com/p/12da0a7db962

2.https://www.jianshu.com/p/b3a9c4a99053