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坐标轴来实现)
相关推荐
枯骨成佛33 分钟前
Android中Crash Debug技巧
android
kim56596 小时前
android studio 更改gradle版本方法(备忘)
android·ide·gradle·android studio
咸芝麻鱼6 小时前
Android Studio | 最新版本配置要求高,JDK运行环境不适配,导致无法启动App
android·ide·android studio
无所谓จุ๊บ6 小时前
Android Studio使用c++编写
android·c++
csucoderlee6 小时前
Android Studio的新界面New UI,怎么切换回老界面
android·ui·android studio
kim56596 小时前
各版本android studio下载地址
android·ide·android studio
饮啦冰美式6 小时前
Android Studio 将项目打包成apk文件
android·ide·android studio
夜色。7 小时前
Unity6 + Android Studio 开发环境搭建【备忘】
android·unity·android studio
ROCKY_8178 小时前
AndroidStudio-滚动视图ScrollView
android
趴菜小玩家9 小时前
使用 Gradle 插件优化 Flutter Android 插件开发中的 Flutter 依赖缺失问题
android·flutter·gradle