Android ChipGroup收起折叠效果实现详解
作者:TimeFine
一、先上效果图
借用某东App的效果,如下。
折叠时的效果:
展开时的效果:
二、ChipGroup和Chip
chipGroup和chip之前写过博客,可移步Android Material 常用组件,看关于chip和chipGroup的部分,建议一定要看,因为里面还挺多坑的。这里简单贴下chip和chipGroup的代码:
ChipGroup:
<com.google.android.material.chip.ChipGroup android:id="@+id/chip_group" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/size_15dp" app:chipSpacingHorizontal="@dimen/size_9dp" app:chipSpacingVertical="@dimen/size_8dp" app:singleSelection="true" />
Chip: 需要定义三种Chip的布局:箭头朝上的、箭头朝下的、普通展示文字的,如果能复用定义一种也行,这里简单贴一种:
<?xml version="1.0" encoding="utf-8"?> <com.google.android.material.chip.Chip xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/chip" style="@style/Widget.MaterialComponents.Chip.Filter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/login_model" android:textSize="@dimen/font_12sp" android:theme="@style/Theme.MaterialComponents" app:checkedIconVisible="false" app:chipBackgroundColor="@color/printer_unused_reason" app:chipMinHeight="@dimen/size_24dp" app:chipMinTouchTargetSize="0dp" />
三、在ChipGroup中动态添加Chip
这个比较简单,inflate后add即可,如下:
//添加Chip for (index in 0 until size) { val chip = layoutInflater.inflate( R.layout.common_chip_end, mViewBind.chipGroup, false) as Chip chip.text = mWordList[index] //动态添加ID chip.id = index mViewBind.chipGroup.addView(chip) }
四、找到每个Chip位于的行数
这个需求一般会要求显示固定的行数(比如效果图中某东App的二行),然后显示有向下箭头的Chip,点击后可以展开,那么如何找到固定行数最后一行的最后一个Chip呢? 不用担心ChipGruop
(的父类)有给我们提供Api:
/** Gets the row index of the child, primarily for accessibility. */ public int getRowIndex(@NonNull View child) { Object index = child.getTag(R.id.row_index_key); if (!(index instanceof Integer)) { return -1; } return (int) index; }
于是当我们将添加到ChipGroup的Chip调用该Api后就知道每个Chip位于哪一行了。
五、实现思路
我们已经找到每个Chip位于第几行,自然我们就知道固定行数的最后一行的最后一个Chip是谁,我们替换该Chip为向下箭头的Chip就可以完成折叠的效果。
展开的效果就很简单了,加上向上箭头的Chip即可。
六、需要注意的问题
1、Chip的复用问题
很遗憾,chip不能复用,每次展开和折叠都会先清除ChipGroup中的Chip然后再添加,如果边清除边添加同一个Chip就会报错,所以清除所有Chip后还是要用inflate重新创建新的Chip。
//清除 mViewBind.chipGroup.removeAllViews() //重新inflate val chip = layoutInflater.inflate( R.layout.common_chip_end, mViewBind.chipGroup, false) as Chip //添加 mViewBind.chipGroup.addView(endChip)
2、Chip的ID设置
如果在for循环中添加chip,可以直接用Chip的数据源的索引(要展示的文本集合的索引),这样我们获取Chip的内容就很简单。如果是一些特殊的Chip,我们可以单独inflate单独添加,单独设置ID,比如向上向下箭头的Chip。
//设置箭头的ID arrowUpChip.id = ARROW_UP_CHIP_ID arrowDownChip.id = ARROW_DOWN_CHIP_ID //处理Chip的点击事件 mViewBind.chipGroup.setOnCheckedChangeListener { group, checkedId -> //记录点击的ID mClickChipId = if (checkedId > -1) checkedId else mClickChipId when (mClickChipId) { ARROW_DOWN_CHIP_ID -> { //箭头向下的Chip的点击 enlargeChipList(true) } ARROW_UP_CHIP_ID -> { //箭头向上的Chip的点击 enlargeChipList(false) } else -> { //其他 val text = mWordList[mClickChipId] } } }
3、点击同一个Chip返回的ID为-1的问题
ChipGroup有个坑就是重复点击同一个Chip,第一次返回的Chip的ID正常,后面返回的Chip的ID都是-1,所以需要记录首次点击的Chip的ID,如果你发现返回的ID为-1,那么就是用户点击了上次的Chip,这一点要注意。
//记录点击的ID mClickChipId = if (checkedId > -1) id else mClickChipId
总结: 这个重要的是实现思路,核心代码也贴出来了,理解了实现起来就不难。写这篇文章主要是是记录一下。
以上就是Android ChipGroup收起折叠效果实现详解的详细内容,更多关于Android ChipGroup收起折叠的资料请关注脚本之家其它相关文章!