產品需求:
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; }
相關參考:
