机缘
因公司需要开发密集架相关项目,涉及相关项目需求设计,市场上并未有相关动画效果流出,基于设计开发相关需求
多列密集架情况:
- 密集架固定列在最左侧
- 密集架固定列在最右侧
- 密集架固定列在最中间
收获
最终完成初步效果
实例展示:
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坐标轴来实现)