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.SideslipContainer
        android:id="@+id/sideslip_container01"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        app:option_width="65dp">

        <com.test.festec.cehuaitem.widget.SideslipContent
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android: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.SideslipOption
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/blue"
            android:tag="add"
            android:text="增加" />

        <com.test.festec.cehuaitem.widget.SideslipOption
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/orange"
            android:tag="edit"
            android:text="编辑" />

        <com.test.festec.cehuaitem.widget.SideslipOption
            android: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: ActivityMainBinding

    private 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">


    <LinearLayout
        android: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: ActivityMainBinding

    private 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 = str
            option.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 = true

    fun 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

    // 上一会触摸的子View
    var originalChild: SideslipContainer? = null

    // 当前触摸的子View
    var currentChild: SideslipContainer? = null

    private var customLayoutManager: CustomLinerLayoutManager? = null

    private 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()

        // 上一个触摸的子View
        fun originalChild(originalSideslip: SideslipContainer?)

        // 当前触摸的子View
        fun 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 = str
                option.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].title
        holder.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: TextView
        var titleTv: TextView
        var describeTv: TextView

        init {
            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: ListLayoutBinding

    private 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 = linearLayoutManager
        binding.root.adapter = adapter
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/67530.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java版工程项目管理系统源码+系统管理+系统设置+项目管理+合同管理+二次开发em

​ 鸿鹄工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离构建工程项目管理系统 1. 项目背景 一、随着公司的快速发展&#xff0c;企业人员和经营规模不断壮大。为了提高工程管理效率、减轻劳动强度、提高信息处理速度和准确性&#xff0c;公司对内部…

在家查阅下载AACR(美国癌症研究学会)数据库文献

AACR&#xff08;美国癌症研究学会&#xff09;简介&#xff1a; 美国癌症研究学会American Association for Cancer Research创建于1907年&#xff0c;是世界上成立最早、规模最大的致力于全面、创新和高水准癌症研究的科学组织。其出版物包括7种正式出版的期刊&#xff1a; …

【Eureka技术指南】「SpringCloud」从源码层面让你认识Eureka工作流程和运作机制(下)

原理回顾 Eureka Server 提供服务注册服务&#xff0c;各个节点启动后&#xff0c;会在Eureka Server中进行注册&#xff0c;这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息&#xff0c;服务节点的信息可以在界面中直观的看到。Eureka Client 是一个Java 客…

gpu-manager安装及测试

提示&#xff1a;GPU-manager安装为主部分内容做了升级开箱即用&#xff0c;有用请点收藏❤抱拳 文章目录 前言一、约束条件二、使用步骤1.下载镜像1.1 查看当前虚拟机的驱动类型&#xff1a; 2.部署gpu-manager3.部署gpu-admission4.修改kube-scheduler.yaml![在这里插入图片描…

siMLPe:Human Motion Prediction

Back to MLP: A Simple Baseline for Human Motion Prediction解析 摘要1. 简介2. Related Work2.1 基于RNN的人体运动预测2.2 基于GCN的人体运动预测2.3 基于 Attention 的人类运动预测2.4 总结 3. siMLPe3.1 离散余弦变换&#xff08;Discrete Cosine Transform (DCT)&#x…

国产芯力特SIT1024QHG四通道本地互联网络(LIN)收发器,可替代TJA1024HG

SIT1024Q 是一款四通道本地互联网络&#xff08;LIN&#xff09;物理层收发器&#xff0c;符合 LIN 2.0、LIN 2.1、LIN 2.2、 LIN 2.2A 、 ISO 17987-4:2016 (12V) 和 SAE J2602 标准。主要适用于使用 1kbps 至 20kbps 传输速 率的车载网络。 SIT1024Q 通过 TXDx 引…

【LeetCode】打家劫舍||

打家劫舍|| 题目描述算法分析编程代码 链接: 打家劫舍|| 在做这个题之前&#xff0c;建议大家做一下这个链接: 按摩师 我的博客里也有这个题的讲解&#xff0c;名字是按摩师 题目描述 算法分析 编程代码 class Solution { public:int maxrob(vector<int>nums,int left,…

【C++】C语言基础部分知识点总结 (指针,函数,内存,关键字,预处理等)(秋招篇)

文章目录 前言讲一下32位系统常用数据类型的字节大小&#xff08;stm32f103为例&#xff09;讲一些C/C中常见的库什么是易变变量&#xff1f;代码的转化和构建通常会经历哪几个步骤&#xff1a;&#xff08;预处理&#xff0c;编译&#xff0c;汇编&#xff0c;链接&#xff09…

Elastic Stack 8.9:更快的跨集群搜索和指标聚合

作者&#xff1a;Tyler Perkins, Gilad Gal, Teresa Soler, Shani Sagiv, Bernhard Suhm, George Kobar Elastic Stack 8.9 在多个方面实现了显着的性能改进&#xff1a;Kibana 中更快的跨集群搜索、Elasticsearch 更快的聚合&#xff0c;以及更快、更相关的向量搜索&#xff0…

Android Studio实现刮刮卡效果

代码和刮刮乐图片参考网络 实现效果 MainActivity import android.app.Activity; import android.os.Bundle;public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentVi…

【Java可执行程序命令】学习路线攻略,史诗级别全汇总 ~

Java可执行程序命令学习路线攻略 &#x1f4d7;文章指路Java可执行命令1、编译工具 javac2、程序启动工具 java3、API文档生成 javadoc4、反编译工具 javap5、打包部署工具 jar6、调试工具 jdb7、C头文件创建 javah8、JWS应用程序启动 javaws9、安装包创建 javapackager10、JAR…

Vue3状态管理库Pinia——自定义持久化插件

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

PostgreSQL和MySQL多维度对比

文章目录 0.前言1. 基础对比2.PostgreSQL和MySQL语法对比3. 特性4. 参考文档 0.前言 在当今的软件开发和数据管理领域&#xff0c;数据库是至关重要的基础设施之一。选择正确的数据库管理系统&#xff08;DBMS&#xff09;对于应用程序的性能、可扩展性和数据完整性至关重要。…

SpringBoot集成Logback日志

SpringBoot集成Logback日志 文章目录 SpringBoot集成Logback日志一、什么是日志二、Logback简单介绍三、SpringBoot项目中使用Logback四、概念介绍一、日志记录器Logger1.1、日志记录器对象生成1.2、记录器的层级结构1.3、过滤器1.4、logger设置日志级别1.5、java代码演示1.6、…

【论文阅读】Deep Instance Segmentation With Automotive Radar Detection Points

基于汽车雷达检测点的深度实例分割 一个区别&#xff1a; automotive radar 汽车雷达 &#xff1a; 分辨率低&#xff0c;点云稀疏&#xff0c;语义上模糊&#xff0c;不适合直接使用用于密集LiDAR点开发的方法 &#xff1b; 返回的物体图像不如LIDAR精确&#xff0c;可以…

API 测试 | 了解 API 接口概念|电商平台 API 接口测试指南

什么是 API&#xff1f; API 是一个缩写&#xff0c;它代表了一个 pplication P AGC 软件覆盖整个房间。API 是用于构建软件应用程序的一组例程&#xff0c;协议和工具。API 指定一个软件程序应如何与其他软件程序进行交互。 例行程序&#xff1a;执行特定任务的程序。例程也称…

Matlab滤波、频谱分析

Matlab滤波、频谱分析 滤波&#xff1a; 某目标信号是由5、15、30Hz正弦波混合而成的混合信号&#xff0c;现需要设计一个滤波器滤掉5、30Hz两种频率。 分析&#xff1a;显然我们应该设计一个带通滤波器&#xff0c;通带频率落在15Hz附近。 % 滤波 % 某目标信号是由5、15、3…

LVS工作环境配置

一、LVS-DR工作模式配置 模拟环境如下&#xff1a; 1台客户机 1台LVS负载调度器 2台web服务器 1、环境部署 &#xff08;1&#xff09;LVS负载调度器 yum install -y ipvsadm # 在LVS负载调度器上进行环境安装 ifconfig ens33:200 192.168.134.200/24 # 配置LVS的VIP…

Mir 2.14 正式发布,Ubuntu 使用的 Linux 显示服务器

导读Canonical 公司最近发布了 Mir 2.14&#xff0c;这是该项目的最新版本。 Mir 2.14 在 Wayland 方面通过 ext-session-lock-v1 协议增加了对屏幕锁定器 (screen lockers) 的支持&#xff0c;并最终支持 Wayland 拖放。此外还整合了渲染平台的实现&#xff0c;放弃了之前在 R…

嵌入式领域:人才供需失衡,发展潜力巨大

嵌入式技术正快速发展&#xff0c;ARM处理器、嵌入式操作系统、LINUX等技术助力嵌入式领域崛起。然而&#xff0c;行业新颖且门槛高&#xff0c;缺乏专业指导。因此&#xff0c;嵌入式人才稀缺&#xff0c;身价水涨船高。 未来几年&#xff0c;嵌入式系统将在信息化、智能化、…