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 分钟前
SufraceFlinger图像合成原理(2)-SurfaceFlinger与应用进程间的通信
android
用户2018792831673 分钟前
uses-library:系统应用报NoClassDefFoundError问题
android
叽哥4 分钟前
Kotlin学习第 4 课:Kotlin 函数:从基础定义到高阶应用
android·java·kotlin
mg6686 分钟前
安卓玩机工具----安卓“搞机工具箱”最新版 控制手机的玩机工具
android·智能手机
诺诺Okami6 分钟前
Android Framework- Activity启动2
android
米豆同学7 分钟前
SystemUI plugin 开发
android
lichong9512 小时前
【混合开发】vue+Android、iPhone、鸿蒙、win、macOS、Linux之video 的各种状态和生命周期调用说明
android·vue.js·macos
app出海创收老李2 小时前
海外独立创收日记(1)-我是如何从0到1在Google Play获得睡后被动收入的?
android·程序员
lang9998882 小时前
kodi在Android4.0.4安装播放歌曲显示歌词
android·kodi·歌词插件
yzx9910132 小时前
构建未来:深度学习、嵌入式与安卓开发的融合创新之路
android·人工智能·深度学习