Android ChipGroup收起折叠效果实现详解

作者:TimeFine 时间:2023-07-29 01:58:20 

一、先上效果图

借用某东App的效果,如下。

折叠时的效果:

Android ChipGroup收起折叠效果实现详解

展开时的效果:

Android ChipGroup收起折叠效果实现详解

二、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 &gt; -1) id else mClickChipId

总结: 这个重要的是实现思路,核心代码也贴出来了,理解了实现起来就不难。写这篇文章主要是是记录一下。

来源:https://juejin.cn/post/7148363145667411975

标签:Android,ChipGroup,收起,折叠
0
投稿

猜你喜欢

  • 解决mybatis分页插件PageHelper导致自定义拦截器失效

    2023-10-13 07:24:29
  • C#中string.Empty和null的区别详解

    2023-05-19 16:01:45
  • Centos中安装jdk案例讲解

    2023-04-30 00:37:50
  • C#实现智能AI五子棋游戏详解

    2021-12-10 06:17:38
  • C++联合体union用法实例详解

    2023-12-01 16:34:00
  • 利用Flutter制作经典贪吃蛇游戏

    2023-07-21 07:04:13
  • springboot中使用Feign整合nacos,gateway进行微服务之间的调用方法

    2021-07-12 07:00:28
  • C#手动操作DataGridView使用各种数据源填充表格实例

    2023-07-20 08:30:31
  • springboot jpa 延迟加载问题的2种解决

    2021-10-14 03:05:20
  • 微信开发--企业转账到用户

    2023-01-06 00:52:41
  • android 仿微信demo——微信消息界面实现(移动端)

    2021-08-01 11:37:26
  • C# Random类的正确应用方法

    2021-06-25 14:56:17
  • 通过Class类获取对象(实例讲解)

    2023-05-19 14:12:58
  • Java动态线程池插件dynamic-tp集成zookeeper

    2023-11-25 03:41:38
  • C#中字符串的加密的源码

    2023-09-14 22:35:34
  • Java简易学生成绩系统写法实例

    2021-08-18 08:06:03
  • Java Jedis NOAUTH Authentication required问题解决方法

    2023-08-19 14:09:47
  • 基于Springboot+Junit+Mockito做单元测试的示例

    2023-01-03 21:15:51
  • Java获取当前时间年月日的方法

    2023-02-19 01:26:54
  • j2ee之AJAX二级联动效果

    2021-09-13 10:06:58
  • asp之家 软件编程 m.aspxhome.com