当前位置: 首页 > 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><…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题&#xff1a; 下面创建一个简单的Flask RESTful API示例。首先&#xff0c;我们需要创建环境&#xff0c;安装必要的依赖&#xff0c;然后…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...