android密集架移动动画效果开发

机缘

因公司需要开发密集架相关项目,涉及相关项目需求设计,市场上并未有相关动画效果流出,基于设计开发相关需求

多列密集架情况:

  1. 密集架固定列在最左侧
  2. 密集架固定列在最右侧
  3. 密集架固定列在最中间

收获

最终完成初步效果

实例展示:

android密集架移动效果


部分核心代码

  • 基于需求的复杂性 内部设计是否开启柜体动画,若不开启则直接与硬件通信
  • 密集架向左移动核心代码:
java 复制代码
fun moveToLeft(clickedIndex: Int){
        if (isAnimation){
            if (isAir){
                Log.e("TAG","正在通风不可移动")
                Toast.makeText(this,"正在通风不可移动",Toast.LENGTH_SHORT).show()
                return
            }
            if (clickedIndex==fixRow){
                Log.e("TAG","固定列不可移动")
                Toast.makeText(this,"固定列不可移动",Toast.LENGTH_SHORT).show()
                return
            }
            isStop = false
            mBinding.stopTv.text = "停止"
            val childCount = mBinding.llOut?.childCount ?: 0
            if (fixRow==0) { // 固定列在最左侧
                var beginIndex = -1
                for (i in 1 until childCount){
                    var rowBean = allBeans[i]
                    if (rowBean.currentX==rowBean.destX||rowBean.currentX==rowBean.middleX||rowBean.currentX!=rowBean.rawX){ //说明已经移动到位
                        beginIndex = i
                        break
                    }
                }
                if (beginIndex==-1){
                    Log.e("TAG","没有向右移动过不可向左移动")
                    return
                }
                var delay: Long = 0 // 初始延迟时间
                cancleAllAnimation()
                for (i in beginIndex..clickedIndex){
                    var view = mBinding.llOut?.getChildAt(i)
                    var rowBean = allBeans[i]
                    var viewx = view!!.x
                    if (viewx==rowBean.rawX){ //说明已经移回原位
                        continue
                    }
                    allAnimation[i] = ValueAnimator.ofInt(rowBean.currentX.toInt(), rowBean.rawX.toInt())
                    allAnimation[i]?.startDelay = delay
                    allAnimation[i]?.duration = moveTime
                    allAnimation[i]?.addUpdateListener { animation ->
                        val currentValue = animation.animatedValue as Int
                        // 更新视图的左边距,实现平移动画
                        view?.layout(currentValue.toInt(), view.top, (currentValue + view.width).toInt(), view.bottom)
                        // 更新当前 x 坐标
                        rowBean.currentX = view.left.toFloat()
                        Log.e("TAG", "固定列在最左侧 向左移动 实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 左边距 ${view.left}")
                    }
                    allAnimation[i]?.start()
                    delay+=delayAddTime
                }
            }else if (fixRow==childCount-1){ // 固定列在最右侧
                var delay: Long = 0 // 初始延迟时间
                cancleAllAnimation()
                for (i in 0..clickedIndex){
                    var view = mBinding.llOut?.getChildAt(i)
                    var rowBean = allBeans[i]
                    var viewx = view!!.left.toFloat()
                    rowBean.currentX = viewx
                    if (rowBean.currentX==rowBean.destX){ //说明已经移动到位
                        continue
                    }
                    allAnimation[i] = ValueAnimator.ofInt(rowBean.currentX.toInt(), rowBean.destX.toInt())
                    allAnimation[i]?.startDelay = delay
                    allAnimation[i]?.duration = moveTime
                    allAnimation[i]?.addUpdateListener { animation ->
                        val currentValue = animation.animatedValue as Int
                        // 更新视图的左边距,实现平移动画
                        view?.layout(currentValue, view.top, currentValue + view.width, view.bottom)
                        // 更新当前 x 坐标
                        rowBean.currentX = view.left.toFloat()
                        Log.e("TAG", "固定列在右侧 向左移动 实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 左边距 ${view.left}")
                    }
                    allAnimation[i]?.start()
                    delay+=delayAddTime
                }

            }else{ //固定列在中间
                if (clickedIndex<fixRow){ // 点击位置处于固定列左侧 初始只能向左移动 不可向右移动
                    var delay: Long = 0 // 初始延迟时间
                    var beginIndex = 0
                    for (i in fixRow downTo clickedIndex){
                        var rowBean = allBeans[i]
                        if (rowBean.rawX==rowBean.destX){
                            continue
                        }
                        if (rowBean.currentX==rowBean.destX||rowBean.currentX==rowBean.middleX||rowBean.currentX!=rowBean.rawX){
                            beginIndex=i
                            break
                        }
                    }
//                    for (i in beginIndex..clickedIndex){
//                        allAnimation[i]?.let {
//                            it.cancel()
//                        }
//                    }
                    for (i in beginIndex..clickedIndex){
                        var view = mBinding.llOut?.getChildAt(i)
                        var rowBean = allBeans[i]
                        var viewx = view!!.left.toFloat()
                        rowBean.currentX = viewx
                        if (rowBean.currentX==rowBean.destX){ //说明已经移动到位 向左移动 已经移动到目标位置 不可再次向左移动
                            continue
                        }
                        allAnimation[i] = ValueAnimator.ofInt(rowBean.currentX.toInt(), rowBean.destX.toInt())
                        allAnimation[i]?.startDelay = delay
                        allAnimation[i]?.duration = moveTime
                        allAnimation[i]?.addUpdateListener { animation ->
                            val currentValue = animation.animatedValue as Int
                            // 更新视图的左边距,实现平移动画
                            view?.layout(currentValue, view.top, currentValue + view.width, view.bottom)
                            // 更新当前 x 坐标
                            rowBean.currentX = view.left.toFloat()
                            Log.e("TAG", "固定列在右侧 向左移动 实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 左边距 ${view.left}")
                        }
                        allAnimation[i]?.start()
                        delay+=delayAddTime
                    }
                }else{
                    var delay: Long = 0 // 初始延迟时间
                    var beginIndex = clickedIndex
                    for (i in fixRow..clickedIndex){
                        var rowBean = allBeans[i]
                        if (rowBean.rawX==rowBean.destX){
                            continue
                        }
                        if (rowBean.currentX==rowBean.destX||rowBean.currentX==rowBean.middleX||rowBean.currentX!=rowBean.rawX){
                            beginIndex = i
                            break
                        }
                    }
//                    for (i in beginIndex..clickedIndex){
//                        allAnimation[i]?.let {
//                            it.cancel()
//                        }
//                    }
//                    cancleAllAnimation()
                    for (i in beginIndex .. clickedIndex){ // 固定列在中间 从当前点击位置 降序 固定列位置 判断其是否能左移
                        var view = mBinding.llOut?.getChildAt(i)
                        var rowBean = allBeans[i]
                        var viewx = view!!.x
                        if (viewx == rowBean.rawX) { //说明目前在原位置 不可向左移动
                            continue
                        }
                        allAnimation[i] = ValueAnimator.ofFloat(rowBean.currentX, rowBean.rawX) // 向左移动 移动回初始位置
                        allAnimation[i]?.startDelay = delay
                        allAnimation[i]?.duration = moveTime
                        allAnimation[i]?.addUpdateListener { animation -> val currentValue = animation.animatedValue as Float
                            // 更新视图的左边距,实现平移动画
                            view?.layout(currentValue.toInt(), view.top, (currentValue + view.width).toInt(), view.bottom)
                            // 更新当前 x 坐标
                            rowBean.currentX = view.left.toFloat()
                            Log.e("TAG", "实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 平移距离:${view.left}")
                        }
                        allAnimation[i]?.start()
                        delay+=delayAddTime
                    }
                }
            }
        }else{
            //直接向硬件发送指令 向左移动


        }

    }
  • 密集架向右移动核心代码
java 复制代码
    fun moveToRight(clickedIndex: Int){
        if (isAnimation){
            if (isAir){
                Log.e("TAG","正在通风不可移动")
                Toast.makeText(this,"正在通风不可移动",Toast.LENGTH_SHORT).show()
                return
            }
            if (clickedIndex==fixRow){
                Log.e("TAG","固定列不可移动")
                Toast.makeText(this,"固定列不可移动",Toast.LENGTH_SHORT).show()
                return
            }
            isStop = false
            mBinding.stopTv.text = "停止"
            val childCount = mBinding.llOut?.childCount ?: 0
            if (fixRow==0){ // 固定列在最左侧
                var delay: Long = 0 // 初始延迟时间
                cancleAllAnimation()
                for (i in childCount-1 downTo clickedIndex){
                    var view = mBinding.llOut?.getChildAt(i)
                    var rowBean = allBeans[i]
                    var viewx = view!!.x
                    if (viewx==rowBean.destX){ //说明已经移动到位
                        continue
                    }
                    allAnimation[i] = ValueAnimator.ofFloat(rowBean.currentX, rowBean.destX)
                    allAnimation[i]?.startDelay = delay
                    allAnimation[i]?.duration = moveTime
                    allAnimation[i]?.addUpdateListener { animation ->
                        val currentValue = animation.animatedValue as Float
                        // 更新视图的左边距,实现平移动画
                        view?.layout(currentValue.toInt(), view.top, (currentValue + view.width).toInt(), view.bottom)
                        // 更新当前 x 坐标
                        rowBean.currentX = view.left.toFloat()
                        Log.e("TAG", "实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 平移距离:${view.left}")
                    }
                    allAnimation[i]?.start()
                    delay+=delayAddTime
                }
            }else if (fixRow==childCount-1){ // 固定列在最右侧
                var delay: Long = 0 // 初始延迟时间
                var beginIndex = -1
                for (i in fixRow downTo clickedIndex){
                    var rowBean = allBeans[i]
                    if (rowBean.currentX==rowBean.destX||rowBean.currentX==rowBean.middleX||rowBean.currentX!=rowBean.rawX){
                        beginIndex = i
                        break
                    }
                }
                cancleAllAnimation()
                for (i in beginIndex downTo clickedIndex){
                    var view = mBinding.llOut?.getChildAt(i)
                    var rowBean = allBeans[i]
                    var viewx = view!!.x
                    if (viewx==rowBean.rawX){ //说明已经移回原位
                        continue
                    }
                    allAnimation[i] = ValueAnimator.ofInt(rowBean.currentX.toInt(), rowBean.rawX.toInt())
                    allAnimation[i]?.startDelay=delay
                    allAnimation[i]?.duration = moveTime
                    allAnimation[i]?.addUpdateListener { animation ->
                        val currentValue = animation.animatedValue as Int
                        // 更新视图的左边距,实现平移动画
                        view?.layout(currentValue, view.top, currentValue + view.width, view.bottom)
                        // 更新当前 x 坐标
                        rowBean.currentX = view.left.toFloat()
                        Log.e("TAG", "固定列在右侧 向左移动实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 左边距 ${view.left}")
                    }
                    allAnimation[i]?.start()
                    delay+=delayAddTime
                }
            }else{ //固定列在中间
                if (clickedIndex<fixRow){
                    var delay: Long = 0 // 初始延迟时间
                    var beginIndex = fixRow
                    for (i in fixRow downTo clickedIndex){
                        var rowBean = allBeans[i]
                        if (rowBean.rawX==rowBean.destX){
                            continue
                        }
                        if (rowBean.currentX==rowBean.destX||rowBean.currentX==rowBean.middleX||rowBean.currentX!=rowBean.rawX){
                            beginIndex=i
                            break
                        }
                    }
//                    cancleAllAnimation()
//                    for (i in beginIndex downTo clickedIndex){
//                        allAnimation[i]?.let {
//                            it.cancel()
//                        }
//                    }
                    for (i in beginIndex downTo clickedIndex){
                        var view = mBinding.llOut?.getChildAt(i)
                        var rowBean = allBeans[i]
                        var viewx = view!!.x
                        if (viewx==rowBean.rawX){ //说明已经移回原位
                            continue
                        }
                        allAnimation[i] = ValueAnimator.ofInt(rowBean.currentX.toInt(), rowBean.rawX.toInt())
                        allAnimation[i]?.startDelay=delay
                        allAnimation[i]?.duration = moveTime
                        allAnimation[i]?.addUpdateListener { animation ->
                            val currentValue = animation.animatedValue as Int
                            // 更新视图的左边距,实现平移动画
                            view?.layout(currentValue, view.top, currentValue + view.width, view.bottom)
                            // 更新当前 x 坐标
                            rowBean.currentX = view.left.toFloat()
                            Log.e("TAG", "固定列在右侧 向左移动实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 左边距 ${view.left}")
                        }
                        allAnimation[i]?.start()
                        delay+=delayAddTime
                    }
                }else{
                    var delay: Long = 0 // 初始延迟时间
//                    cancleAllAnimation()
//                    for (i in childCount-1 downTo clickedIndex){
//                        allAnimation[i]?.let {
//                            it.cancel()
//                        }
//                    }
                    for (i in childCount-1 downTo clickedIndex){
                        var view = mBinding.llOut?.getChildAt(i)
                        var rowBean = allBeans[i]
                        var viewx = view!!.x
                        if (viewx==rowBean.destX){ //说明已经移动到位
                            continue
                        }
                        allAnimation[i] = ValueAnimator.ofFloat(rowBean.currentX, rowBean.destX)
                        allAnimation[i]?.startDelay = delay
                        allAnimation[i]?.duration = moveTime
                        allAnimation[i]?.addUpdateListener { animation ->
                            val currentValue = animation.animatedValue as Float
                            // 更新视图的左边距,实现平移动画
                            view?.layout(currentValue.toInt(), view.top, (currentValue + view.width).toInt(), view.bottom)
                            // 更新当前 x 坐标
                            rowBean.currentX = view.left.toFloat()
                            Log.e("TAG", "实时更新获取当前 view 对象 x 坐标:${rowBean.currentX}    view 平移距离:${view.left}")
                        }
                        allAnimation[i]?.start()
                        delay+=delayAddTime
                    }
                }
            }
        }else{
            //向右移动直接向硬件发送 指令
        }
    }

Tips

  • 柜体移动复杂性涉及多个方面,目前仅android端开发完成,与硬件交互方面同步移动暂未处理(若要实现或许可以通过使用view坐标轴来实现)
相关推荐
丘狸尾2 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~4 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads7 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu9 小时前
Android4.4 在系统中添加自己的System Service
android
C4rpeDime11 小时前
自建MD5解密平台-续
android
鲤籽鲲12 小时前
C# Random 随机数 全面解析
android·java·c#
m0_5485147716 小时前
2024.12.10——攻防世界Web_php_include
android·前端·php
凤邪摩羯16 小时前
Android-性能优化-03-启动优化-启动耗时
android
凤邪摩羯16 小时前
Android-性能优化-02-内存优化-LeakCanary原理解析
android
喀什酱豆腐17 小时前
Handle
android