当前位置: 首页 > news >正文

Android自定义侧滑Item

源码地址:https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem

使用方式一:XML布局中直接使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><com.test.festec.cehuaitem.widget.SideslipContainerandroid:id="@+id/sideslip_container01"android:layout_width="match_parent"android:layout_height="70dp"app:option_width="65dp"><com.test.festec.cehuaitem.widget.SideslipContentandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:background="@color/d5"android:paddingTop="20dp"android:textAlignment="center"android:textSize="20sp"android:text="content"android:layout_width="match_parent"android:layout_height="match_parent" /></com.test.festec.cehuaitem.widget.SideslipContent><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/blue"android:tag="add"android:text="增加" /><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/orange"android:tag="edit"android:text="编辑" /><com.test.festec.cehuaitem.widget.SideslipOptionandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/red"android:tag="delete"android:text="删除" /></com.test.festec.cehuaitem.widget.SideslipContainer></LinearLayout>

Activity中监听

class MainActivity : Activity() {private lateinit var binding: ActivityMainBindingprivate var options = mutableListOf("增加", "编辑", "删除")private var optionBg = mutableListOf(R.color.blue, R.color.orange, R.color.red)@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)binding.sideslipContainer01.addOnClickListener(object : SideslipContainer.SideslipContainerOnClick {override fun optionOnClick(optionTag: Any) {Toast.makeText(this@MainActivity,"optionTag:$optionTag", Toast.LENGTH_SHORT).show()binding.sideslipContainer01.sideslipRecover()}override fun contentOnClick() {Toast.makeText(this@MainActivity,"content", Toast.LENGTH_SHORT).show()binding.sideslipContainer01.sideslipRecover()}})}}

使用方式二:代码方式使用

先定义一个容器

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><LinearLayoutandroid:id="@+id/container"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" /></LinearLayout>

Activity中动态添加

class MainActivity : Activity() {private lateinit var binding: ActivityMainBindingprivate var options = mutableListOf("增加", "编辑", "删除")private var optionBg = mutableListOf(R.color.blue, R.color.orange, R.color.red)@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ActivityMainBinding.inflate(layoutInflater)setContentView(binding.root)// 创建侧滑容器,配置基础参数val sideslip = SideslipContainer(this, DensityUtil.dp2px(this, 65f))val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,DensityUtil.dp2px(this, 70f))sideslip.layoutParams = layoutParams// 创建侧滑内容val content = SideslipContent(this).apply {background = resources.getDrawable(R.color.black,null)}// 加入侧滑容器中sideslip.addView(content)// 创建选项卡,并加入侧滑容器中options.forEachIndexed { index, str ->val option = SideslipOption(this,str)option.text = stroption.background = resources.getDrawable(optionBg[index], null)sideslip.addView(option)}// 点击监听sideslip.addOnClickListener(object : SideslipContainer.SideslipContainerListener {override fun optionOnClick(optionTag: Any) {Log.e("TAG","optionTag:$optionTag")}override fun contentOnClick() {Log.e("TAG","content")}})binding.container.addView(sideslip)}}

使用方式三:结合RecyclerView使用

重写LayoutManager

// 重写LayoutManager,动态让RecyclerView 禁止/恢复 Y轴滚动
open class CustomLinerLayoutManager(context: Context) : LinearLayoutManager(context) {private var isScrollEnabled = truefun getEnabled(): Boolean {return isScrollEnabled}fun setScrollEnabled(flag: Boolean) {isScrollEnabled = flag}override fun canScrollVertically(): Boolean {return isScrollEnabled && super.canScrollVertically();}}

重写RecyclerView

class MyRecyclerView : RecyclerView {constructor(context: Context) : super(context)constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)init {addOnScrollListener(object : RecyclerView.OnScrollListener() {/**** public static final int SCROLL_STATE_IDLE = 0;  :  RecyclerView 当前未滚动。** public static final int SCROLL_STATE_DRAGGING = 1;  :  RecyclerView 当前正在被外部输入(例如用户触摸输入)拖动。** public static final int SCROLL_STATE_SETTLING = 2;  :  RecyclerView 当前正在动画到最终位置,而不是在外部控制。*/override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {childrenRecover()}}})}// view初始化private var viewInit = false// 上一会触摸的子Viewvar originalChild: SideslipContainer? = null// 当前触摸的子Viewvar currentChild: SideslipContainer? = nullprivate var customLayoutManager: CustomLinerLayoutManager? = nullprivate var childMoveCallback = object : ChildOnTouchCallback {override fun currentChildMove() {childrenRecover()}override fun originalChild(originalSideslip: SideslipContainer?) {originalChild = originalSideslip}override fun currentChild(currentContainer: SideslipContainer?) {currentChild = currentContainer}override fun listStopYScroll() {// Log.e("TAG", "List停止滚动")if (customLayoutManager!!.getEnabled()) {customLayoutManager?.setScrollEnabled(false)}}override fun listRecoverYScroll() {// Log.e("TAG", "List恢复滚动")if (!(customLayoutManager!!.getEnabled())) {customLayoutManager?.setScrollEnabled(true)}}}// 子View恢复private fun childrenRecover() {children.forEach {(it as SideslipContainer).sideslipRecover()}}override fun onViewAdded(child: View?) {// Log.e("TAG","onViewAdded")val sideslipContainer = (child as SideslipContainer)sideslipContainer.addOnChildMoveCallback(childMoveCallback)}// 当复用item,彻底超出屏幕,不可见时执行override fun onViewRemoved(child: View?) {// Log.e("TAG","onViewRemoved")(child as SideslipContainer).sideslipStateRest()}override fun onWindowFocusChanged(hasWindowFocus: Boolean) {// Log.e("TAG","onWindowFocusChanged")super.onWindowFocusChanged(hasWindowFocus)if (!viewInit) {customLayoutManager = (layoutManager as CustomLinerLayoutManager)}viewInit = true}interface ChildOnTouchCallback {// 有子View侧滑了fun currentChildMove()// 上一个触摸的子Viewfun originalChild(originalSideslip: SideslipContainer?)// 当前触摸的子Viewfun currentChild(currentContainer: SideslipContainer?)// 列表停止Y轴滚动fun listStopYScroll()// 列表恢复Y轴滚动fun listRecoverYScroll()}}

RecyclerView适配器

class MyListAdapter(var context: Context,var data: MutableList<Info>
) : RecyclerView.Adapter<MyListAdapter.MyViewHolder>() {private var options = mutableListOf("增加", "编辑", "删除")private var optionBg =mutableListOf(R.color.blue, R.color.orange, R.color.red)@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {val itemView = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false)val sideslip = sideslipContainer(itemView)return MyViewHolder(sideslip)}@SuppressLint("UseCompatLoadingForDrawables", "ResourceAsColor")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)override fun onBindViewHolder(holder: MyViewHolder, position: Int) {val sideslip = holder.itemView as SideslipContainer// 根据不同权限,添加不同的选项卡val optionsView = mutableListOf<SideslipOption>()if (data[position].level == 0) {optionsView.clear()} else if (data[position].level == 1) {val option = SideslipOption(context, options[1])option.text = options[1]option.background = context.resources.getDrawable(optionBg[1], null)optionsView.add(option)} else {options.forEachIndexed { index, str ->val option = SideslipOption(context, str)option.text = stroption.background = context.resources.getDrawable(optionBg[index], null)optionsView.add(option)}}sideslip.addMultipleOption(optionsView)// 点击回调sideslip.addOnClickListener(object : SideslipContainer.SideslipContainerOnClick {override fun optionOnClick(optionTag: Any) {Toast.makeText(context,"${holder.adapterPosition} -- optionTag:$optionTag",Toast.LENGTH_SHORT).show()sideslip.sideslipRecover()}override fun contentOnClick() {Toast.makeText(context,"${holder.adapterPosition} - content",Toast.LENGTH_SHORT).show()sideslip.sideslipRecover()}})holder.idTv.text = data[position].id.toString()holder.titleTv.text = data[position].titleholder.describeTv.text = data[position].describe}override fun getItemCount(): Int {return data.size}@SuppressLint("UseCompatLoadingForDrawables")@RequiresApi(Build.VERSION_CODES.LOLLIPOP)private fun sideslipContainer(itemView: View): SideslipContainer {// 创建侧滑容器,配置基础参数val sideslip = SideslipContainer(context)sideslip.setOptionWidth(DensityUtil.dp2px(context, 65f))val layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,DensityUtil.dp2px(context, 70f))sideslip.layoutParams = layoutParams// 创建侧滑内容val content = SideslipContent(context)content.addView(itemView)// 加入侧滑容器中sideslip.addView(content)// 创建选项卡,并加入侧滑容器中// options.forEachIndexed { index, str ->//    val option = SideslipOption(context, str)//    option.text = str//    option.background = context.resources.getDrawable(optionBg[index], null)//    sideslip.addView(option)// }return sideslip}class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {var idTv: TextViewvar titleTv: TextViewvar describeTv: TextViewinit {idTv = itemView.findViewById(R.id.id_tv)titleTv = itemView.findViewById(R.id.title_tv)describeTv = itemView.findViewById(R.id.describe_tv)}}
}

Activity中绑定数据

class ListActivity : Activity() {private lateinit var binding: ListLayoutBindingprivate val data: MutableList<Info> = mutableListOf(Info(0, "title", "content", 2),Info(1, "title", "content", 1),Info(2, "title", "content", 2),Info(3, "title", "content", 2),Info(4, "title", "content", 2),Info(5, "title", "content", 1),Info(6, "title", "content", 1),Info(7, "title", "content", 2),Info(8, "title", "content", 2),Info(9, "title", "content", 1),Info(10, "title", "content", 1),Info(11, "title", "content", 2),Info(12, "title", "content", 2),Info(13, "title", "content", 1),Info(14, "title", "content", 1),Info(15, "title", "content", 2),Info(16, "title", "content", 2),Info(17, "title", "content", 2),Info(18, "title", "content", 2),Info(19, "title", "content", 1),Info(20, "title", "content", 2),Info(21, "title", "content", 1),Info(22, "title", "content", 2),Info(23, "title", "content", 2),Info(24, "title", "content", 2),Info(25, "title", "content", 1),Info(26, "title", "content", 2),Info(27, "title", "content", 1),Info(28, "title", "content", 2),Info(29, "title", "content", 2),Info(30, "title", "content", 2),Info(31, "title", "content", 1),Info(32, "title", "content", 1),Info(33, "title", "content", 2),Info(34, "title", "content", 2),Info(35, "title", "content", 1),)override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)binding = ListLayoutBinding.inflate(layoutInflater)setContentView(binding.root)val adapter = MyListAdapter(this, data)val linearLayoutManager = CustomLinerLayoutManager(this)binding.root.layoutManager = linearLayoutManagerbinding.root.adapter = adapter}}

相关文章:

Android自定义侧滑Item

源码地址&#xff1a;https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem 使用方式一&#xff1a;XML布局中直接使用 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com…...

c++11 标准模板(STL)(std::basic_stringbuf)(三)

定义于头文件 <sstream> template< class CharT, class Traits std::char_traits<CharT>, class Allocator std::allocator<CharT> > class basic_stringbuf : public std::basic_streambuf<CharT, Traits> std::basic_stringbuf…...

Nodejs 第九章(模块化)

Nodejs 模块化规范遵循两套一 套CommonJS规范另一套esm规范 CommonJS 规范 引入模块&#xff08;require&#xff09;支持四种格式 支持引入内置模块例如 http os fs child_process 等nodejs内置模块支持引入第三方模块express md5 koa 等支持引入自己编写的模块 ./ …/ 等支…...

shell之正则表达式及三剑客grep命令

一、正则表达式概述 什么是正则表达式&#xff1f; 正则表达式是一种描述字符串匹配规则的重要工具 1、正则表达式定义: 正则表达式&#xff0c;又称正规表达式、常规表达式 使用字符串描述、匹配一系列符合某个规则的字符串 正则表达式 普通字符&#xff1a; 大小写字母…...

LeetCode 热题 100 JavaScript--33. 搜索旋转排序数组

整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nums[1], …,…...

并发编程 - 线程池中的常见面试题

目录 1. 线程池相比于线程有什么优点 2. 线程池的参数有哪些 3. 线程工厂有什么用 4. 说一下线程的优先级 5. 说一下线程池的执行流程 6. 线程池的拒绝策略有哪些 7. 如何实现自定义拒绝策略 8. 如何判断线程池中的任务是否执行完成 1. 线程池相比于线程有什么优点 有…...

将多个单独的 Excel 文件合并成一个,并添加标题行

要将多个单独的 Excel 文件合并成一个&#xff0c;并添加标题行&#xff0c;可以使用 Python 的 pandas 库。以下是一个示例代码&#xff0c;假设要合并的 Excel 文件都在同一个文件夹中&#xff1a; import os import pandas as pd # 指定文件夹路径 folder_path path/to/fo…...

VPN pptp和l2tp协议破解

代码下载地址&#xff1a; https://download.csdn.net/download/m0_37567738/88215516?spm1001.2014.3001.5501...

4.3、Flink任务怎样读取Kafka中的数据

目录 1、添加pom依赖 2、API使用说明 3、这是一个完整的入门案例 4、Kafka消息应该如何解析 4.1、只获取Kafka消息的value部分 ​4.2、获取完整Kafka消息(key、value、Metadata) 4.3、自定义Kafka消息解析器 5、起始消费位点应该如何设置 ​5.1、earliest() 5.2、lat…...

C语言实例_和校验算法

一、算法介绍 和校验&#xff08;Checksum&#xff09;是一种简单的纠错算法&#xff0c;用于检测或验证数据传输或存储过程中的错误。它通过对数据进行计算并生成校验和&#xff0c;然后将校验和附加到数据中&#xff0c;在接收端再次计算校验和并进行比较&#xff0c;以确定…...

安全加密框架图——Oracle安全开发者

Oracle安全开发者 ACLs 设计 ACLs&#xff08;访问控制列表&#xff09;时&#xff0c;可以根据以下思路进行设计&#xff1a; 所有者文件权限&#xff1a;确定文件的所有者能够对文件执行哪些操作&#xff0c;如读取、写入、执行等。这可以根据文件的性质和拥有者的职责来决…...

Android databinding 被多次定义

一、报错&#xff1a; AndroidStudio运行代码时&#xff0c;编译器报 Type androidx.databinding.Bindable is defined multiple times...... 二、解决&#xff1a; 点击 Build -> Clean Project&#xff0c;关闭编译器再打开即可。 三、解决过程&#xff1a; 在使用Andro…...

云原生周刊:Kubernetes v1.28 新特性一览 | 2023.8.14

推荐一个 GitHub 仓库&#xff1a;Fast-Kubernetes。 Fast-Kubernetes 是一个涵盖了 Kubernetes 的实验室&#xff08;LABs&#xff09;的仓库。它提供了关于 Kubernetes 的各种主题和组件的详细内容&#xff0c;包括 Kubectl、Pod、Deployment、Service、ConfigMap、Volume、…...

机器学习之分类模型

机器学习之分类模型 概述分类模型逻辑回归最近邻分类朴素贝叶斯支持向量机决策树随机森林多层感知机基于集成学习的分类模型VotingBaggingStackingBlendingBoosting 概述 机器学习分类模型通过训练集进行学习&#xff0c;建立一个从输入空间 X X X到输出空间 Y Y Y&#xff08…...

学习Vue:创建第一个Vue实例

当您开始探索 Vue.js&#xff0c;第一步就是创建一个 Vue 实例。Vue 实例是 Vue.js 应用程序的核心构建块&#xff0c;它使您能够将数据与用户界面连接起来&#xff0c;实现动态交互。在本文中&#xff0c;我们将详细介绍如何创建您的第一个 Vue 实例。 步骤1&#xff1a;引入 …...

JavaFx基础学习【二】:Stage

一、介绍 窗口Stage为图中标绿部分&#xff1a; 实际为如下部分&#xff1a; 不同的操作系统表现的样式不同&#xff0c;以下都是以Windows操作系统为例&#xff0c;为了使大家更清楚Stage是那部分&#xff0c;直接看以下图&#xff0c;可能更清楚&#xff1a; 有点潦草&…...

C语言——动态内存函数(malloc、calloc、realloc、free)

了解动态内存函数 前言&#xff1a;一、malloc函数二、calloc函数三、realloc函数四、free函数 前言&#xff1a; 在C语言中&#xff0c;动态内存函数是块重要的知识点。以往&#xff0c;我们开辟空间都是固定得&#xff0c;数组编译结束后就不能继续给它开辟空间了&#xff0…...

Redis数据结构——Redis简单动态字符串SDS

定义 众所周知&#xff0c;Redis是由C语言写的。 对于字符串类型的数据存储&#xff0c;Redis并没有直接使用C语言中的字符串。 而是自己构建了一个结构体&#xff0c;叫做“简单动态字符串”&#xff0c;简称SDS&#xff0c;比C语言中的字符串更加灵活。 SDS的结构体是这样的…...

【计算机网络】TCP协议超详细讲解

文章目录 1. TCP简介2. TCP和UDP的区别3. TCP的报文格式4. 确认应答机制5. 超时重传6. 三次握手7. 为什么两次握手不行?8. 四次挥手9. 滑动窗口10. 流量控制11. 拥塞控制12. 延时应答13. 捎带应答14. 面向字节流15. TCP的连接异常处理 1. TCP简介 TCP协议广泛应用于可靠性要求…...

Salesforce特别元数据部署技巧

标准的picklist字段部署 <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <Package xmlns"http://soap.sforce.com/2006/04/metadata"><types><members>Opportunity.StageName</members><…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...