【一步教学,一步到位,移动手机app开发

var cardRotateFunc: IFunc? = null
/**

  • 阴影大小变化函数
    /
    var cardShadowSizeFunc: IFunc? = null
    /
    *
  • 阴影距离变化函数
    /
    var cardShadowDistanceFunc: IFunc? = null
    /
    *
  • 配置各个函数
    */
    private fun configFunc() {
    cardRotateFunc = CardRotateFunc()
    with(cardRotateFunc!!) {
    inParamMin = 0F
    inParamMax = cardHeight * 2
    outParamMin = 0F
    outParamMax = 180F
    initValue = 45F
    }
    cardShadowSizeFunc = CardShadowSizeFunc()
    with(cardShadowSizeFunc!!) {
    inParamMin = 0F
    inParamMax = 180F
    outParamMax = 50F
    outParamMin = 0F
    initValue = 10F
    }
    cardShadowDistanceFunc = CardShadowDistanceFunc()
    with(cardShadowDistanceFunc!!) {
    inParamMin = 0F
    inParamMax = 180F
    outParamMax = 50F
    outParamMin = 0F
    initValue = 10F
    }
    }
    复制代码

2.5.3 阴影变化

为了更好地模拟3D效果,卡片阴影也存在微小的变化

/**

  • 根据旋转角度计算阴影大小、距离
    */
    private fun executeShadowFunc(rotate: Float) {
    cardShadowSizeFunc?.let {
    cardShadowSize = it.execute(rotate)
    }
    cardShadowDistanceFunc?.let {
    cardShadowDistance = it.execute(rotate)
    }
    }
    复制代码

2.5.4 数字图片绘制

数字的绘制就是图片的绘制,需要注意的是中间活动卡片在上翻或下翻转超过90度时,绘制的数字需要改变,涉及到图片的水平镜像翻转,调用matrix.postScale(-1F, 1F)实现。以下翻为例,代码如下:

if (curState == STATE_DOWN_ING) {
//往下翻
if (abs(cardRotateFunc!!.initValue - rotateX) >= 90F) {
//绘制前一个数字
if (curShowNum - 1 >= 0) {
tempBm = Bitmap.createBitmap(numBms[curShowNum - 1], 0, 0, curNumBm.width, curNumBm.height, matrix, false)
} else {
tempBm = Bitmap.createBitmap(numBms[0], 0, 0, curNumBm.width, curNumBm.height, matrix, false)
}
} else {
tempBm = Bitmap.createBitmap(numBms[curShowNum], 0, 0, curNumBm.width, curNumBm.height, matrix, false)
}
}
tempBm?.let {
drawBitmap(it, Rect(0, it.height / 2, it.width, it.height), rectF, mPaint)
}
复制代码

2.6 实现交互

2.6.1 上下翻转

逻辑主要在onTouchEvent方法中,通过中间卡片初始角度和当前的翻转角度判断是上翻还是下翻

/**

  • 手指按下的初始坐标
    */
    private var downX: Float = 0F
    private var downY: Float = 0F
    private var offsetY: Float = 0F
    override fun onTouchEvent(event: MotionEvent?): Boolean {
    when (event?.action) {
    MotionEvent.ACTION_DOWN -> {
    downX = event.x
    downY = event.y
    if (downY >= height / 2) {
    //绘制下方的mid card
    rotateX = 0F
    curState = STATE_UP_ING
    } else {
    rotateX = 180F
    curState = STATE_DOWN_ING
    }
    resetInitValue()
    postInvalidate()
    }
    MotionEvent.ACTION_MOVE -> {
    offsetY = event.y - downY
    executeFunc(offsetY)
    postInvalidate()
    }
    MotionEvent.ACTION_UP -> {
    //判断是上翻还是下翻
    if (rotateX >= 90F) {
    if (abs(cardRotateFunc!!.initValue - rotateX) >= 90F) {
    if (curShowNum + 1 <= 9) {
    startCardUpAnim(curShowNum + 1)
    } else {
    curShowNum = 9
    startCardDownAnim(9)
    }
    } else {
    startCardUpAnim(curShowNum)
    }
    } else {
    if (abs(cardRotateFunc!!.initValue - rotateX) >=
    90F) {
    if (curShowNum - 1 >= 0) {
    startCardDownAnim(curShowNum - 1)
    } else {
    curShowNum = 0
    startCardUpAnim(0)
    }
    } else {
    startCardDownAnim(curShowNum)
    }
    }
    downX = 0F
    downY = 0F
    }
    else -> {
    }
    }
    return true
    }
    复制代码

2.6.2 翻页动画、阴影动画

由于采用了坐标计算框架,动画的实现就变得非常简单了,控制好offset变量,即可控制中间卡片的翻转角度、阴影距离、阴影大小。以上翻动画为例:

/**

  • 卡片上翻动画
    */
    private fun startCardUpAnim(curNum: Int) {
    cardRotateAnim?.cancel()
    cardRotateAnim = ValueAnimator.ofFloat(rotateX, 180F)
    with(cardRotateAnim!!) {
    duration = 400L
    addUpdateListener {
    rotateX = it.animatedValue as Float
    executeShadowFunc(rotateX)
    postInvalidate()
    }
    addListener(object : AnimatorListenerAdapter() {
    override fun onAnimationEnd(animation: Animator?) {
    super.onAnimationEnd(animation)
    resetInitValue()
    curState = STATE_NORMAL
    curShowNum = curNum
    }
    })
    start()
    }
    }
    复制代码

2.6.3 显示数字的变化

当动画结束时,当前显示数字才是真正地发生了改变,对curShowNum进行赋值即可。也可以方便添加数字变化时的监听暴露给调用者。

2.7 加点细节

2.7.1 边界控制

当前数字为0时,无法再向下翻转,这时无需绘制上卡片;同样的,当前数字为9时,无需绘制下卡片

private fun judgeState(state: Int) {
when (state) {
STATE_NORMAL -> {
isNeedDrawMidCard = false
isNeedDrawUpCard = true
isNeedDrawDownCard = true
}
STATE_UP_ING -> {
isNeedDrawMidCard = true
if (curShowNum + 1 > 9) {
isNeedDrawDownCard = false
}
}
STATE_DOWN_ING -> {
isNeedDrawMidCard = true
if (curShowNum - 1 < 0) {
isNeedDrawUpCard = false
}
}
}
}
复制代码

2.7.2 翻页回弹

处于边界数字时,用户继续进行翻转操作,需要进行回弹至原位。

if (curShowNum + 1 <= 9) {
startCardUpAnim(curShowNum + 1)
} else {
curShowNum = 9
startCardDownAnim(9)
}

三、后记

}
}
复制代码

2.7.2 翻页回弹

[外链图片转存中…(img-xnewZwbz-1642753565232)]

处于边界数字时,用户继续进行翻转操作,需要进行回弹至原位。

if (curShowNum + 1 <= 9) {
startCardUpAnim(curShowNum + 1)
} else {
curShowNum = 9
startCardDownAnim(9)
}

三、后记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值