Android ChipGroup收起折叠效果实现详解
作者:TimeFine 发布时间:2023-07-29 01:58:20
一、先上效果图
借用某东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
总结: 这个重要的是实现思路,核心代码也贴出来了,理解了实现起来就不难。写这篇文章主要是是记录一下。
来源:https://juejin.cn/post/7148363145667411975


猜你喜欢
- 本文实例为大家分享了java获取不同路径的方法,供大家参考,具体内容如下思路:自定义Button获取DialogManager、AudioM
- 经过一番的探索,终于搞清楚关键字async/await 在.net4.5之后可用的巧妙之处,在这里记录一下也与大家分享一下个人的心得体会as
- 这篇文章主要介绍了springboot @Configuration @bean注解作用解析,文中通过示例代码介绍的非常详细,对大家的学习或
- PullToRefresh是一套实现非常好的下拉刷新库,它支持:1.ListView2.ExpandableListView3.GridVi
- java执行xshell命令实例import java.io.BufferedReader;import java.io.IOExcepti
- 本文实例讲述了Spring实战之使用注解实现声明式事务操作。分享给大家供大家参考,具体如下:一 配置文件<?xml version=&
- Android内存优化是我们性能优化工作中比较重要的一环,这里其实主要包括两方面的工作:1、优化RAM,即降低运行时内存。这里的目的是防止程
- 前言RabbitMQ 是使用 Erlang 语言开发的消息中间件, 其遵循了高级消息队列协议(Advanced Message Queuin
- 本文实例讲述了Java Web项目部署在Tomcat运行出错与解决方法。分享给大家供大家参考,具体如下:1、在部署Java Web项目的过程
- 本文实例为大家分享了Android播放音乐案例的具体实现代码,供大家参考,具体内容如下效果:分析:和上一篇文章的结构是一样的,只不过我们需要
- 前文传送门:Netty启动流程服务端channel初始化注册多路复用回到上一小节的代码:final ChannelFuture initAn
- 新建工程,新建Module新建一个工程,之后按下图中的操作方式,创建一个Module创建 Android Library选中 Android
- 投篮小游戏规则,点击投篮目标点,就会有一个球沿着相关抛物线,然后,判断是否进入篮子里,其实就是一个矩形,直接是按照碰撞检测来的,碰到就算进去
- 一、版本说明spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。原因:spr
- 开发人员可以用以下两种方式声明UI:一是通过.xml文件(不带预览界面)或者.axml文件(带预览界面)来描述;二是用C#代码实现。&nbs
- 一、Struts2 * 原理:Struts2 * 的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,
- 前言开篇一个例子,我看看都有谁会?如果不会的,或者不知道原理的,还是老老实实看完这篇文章吧。@Slf4j(topic = "c.V
- 本文以一个简单的实例形式讲述了C#模板方法模式的实现方法,分享给大家供大家参考。具体实现方法如下:这里假设要做一道红烧肉,做法有很多,在不同
- Queue接口先看下Queue的继承关系和其中定义的方法:Queue继承自Collection,Collection继承自Iterable。
- 一、创建字符串创建字符串的方式有很多种,当是常见的一般就三种1. 直接赋值(常用)String str = "hello worl