kotlin 添加購(gòu)物車動(dòng)畫


購(gòu)物車放大動(dòng)畫


動(dòng)畫執(zhí)行完回調(diào)

interface RefreshDataListener {

fun onDataRefresh(tag: Int, key: String, value: String)

}


動(dòng)畫代碼

fun addCart(startView: ImageView, endView: View, xmlLayout: RelativeLayout, listener:RefreshDataListener) {

//? 一、創(chuàng)造出執(zhí)行動(dòng)畫的主題---imageview

? ? //? 代碼new一個(gè)imageview,圖片資源是上面的imageview的圖片

? ? //? (這個(gè)圖片就是執(zhí)行動(dòng)畫的圖片,從開始位置出發(fā),經(jīng)過(guò)一個(gè)拋物線(貝塞爾曲線),移動(dòng)到購(gòu)物車?yán)?

? ? val goods = AppCompatImageView(xmlLayout.context)

goods.setImageDrawable(startView.drawable)

val params = RelativeLayout.LayoutParams(80, 80)

xmlLayout.addView(goods, params)

//? 二、計(jì)算動(dòng)畫開始/結(jié)束點(diǎn)的坐標(biāo)的準(zhǔn)備工作

? ? //? 得到父布局的起始點(diǎn)坐標(biāo)(用于輔助計(jì)算動(dòng)畫開始/結(jié)束時(shí)的點(diǎn)的坐標(biāo))

? ? val parentLocation = IntArray(2)

xmlLayout.getLocationInWindow(parentLocation)

//? 得到商品圖片的坐標(biāo)(用于計(jì)算動(dòng)畫開始的坐標(biāo))

? ? val startLoc = IntArray(2)

startView.getLocationInWindow(startLoc)

//? 得到購(gòu)物車圖片的坐標(biāo)(用于計(jì)算動(dòng)畫結(jié)束后的坐標(biāo))

? ? val endLoc = IntArray(2)

endView.getLocationInWindow(endLoc)

//? 三、正式開始計(jì)算動(dòng)畫開始/結(jié)束的坐標(biāo)

? ? //? 開始掉落的商品的起始點(diǎn):商品起始點(diǎn)-父布局起始點(diǎn)+該商品圖片的一半

? ? val startX = (startLoc[0] - parentLocation[0]).toFloat()//+ startView.getWidth() / 2;

? ? val startY = (startLoc[1] - parentLocation[1]).toFloat()//+ startView.getHeight() / 2;

? ? //商品掉落后的終點(diǎn)坐標(biāo):購(gòu)物車起始點(diǎn)-父布局起始點(diǎn)+購(gòu)物車圖片的1/5

? ? val toX = (endLoc[0] - parentLocation[0] + endView.width /5).toFloat()

val toY = (endLoc[1] - parentLocation[1]).toFloat()

//? 四、計(jì)算中間動(dòng)畫的插值坐標(biāo)(貝塞爾曲線)(其實(shí)就是用貝塞爾曲線來(lái)完成起終點(diǎn)的過(guò)程)

? ? //? 開始繪制貝塞爾曲線

? ? val path = Path()

//? 移動(dòng)到起始點(diǎn)(貝塞爾曲線的起點(diǎn))

? ? path.moveTo(startX, startY)

//? 使用二次薩貝爾曲線:注意第一個(gè)起始坐標(biāo)越大,貝塞爾曲線的橫向距離就會(huì)越大,一般按照下面的式子取即可

? ? path.quadTo((startX + toX) /2, startY, toX, toY)

//mPathMeasure用來(lái)計(jì)算貝塞爾曲線的曲線長(zhǎng)度和貝塞爾曲線中間插值的坐標(biāo),

? ? //? 如果是true,path會(huì)形成一個(gè)閉環(huán)

? ? val mPathMeasure = PathMeasure(path, false)

val mCurrentPosition = FloatArray(2)

//? 屬性動(dòng)畫實(shí)現(xiàn)(從0到貝塞爾曲線的長(zhǎng)度之間進(jìn)行插值計(jì)算,獲取中間過(guò)程的距離值)

? ? val valueAnimator = ValueAnimator.ofFloat(0f, mPathMeasure.length)

valueAnimator.duration =1000

? ? //? 勻速線性插值器

? ? valueAnimator.interpolator = LinearInterpolator()

valueAnimator.addUpdateListener{ animation-> // 當(dāng)插值計(jì)算進(jìn)行時(shí),獲取中間的每個(gè)值,

? ? ? ? // 這里這個(gè)值是中間過(guò)程中的曲線長(zhǎng)度(下面根據(jù)這個(gè)值來(lái)得出中間點(diǎn)的坐標(biāo)值)

? ? ? ? val value = animation.animatedValue as Float

// boolean getPosTan(float distance, float[] pos, float[] tan) :

? ? ? ? // 傳入一個(gè)距離distance(0<=distance<=getLength()),然后會(huì)計(jì)算當(dāng)前距

? ? ? ? // 離的坐標(biāo)點(diǎn)和切線,pos會(huì)自動(dòng)填充上坐標(biāo),這個(gè)方法很重要。

? ? ? ? //mCurrentPosition此時(shí)就是中間距離點(diǎn)的坐標(biāo)值

? ? ? ? mPathMeasure.getPosTan(value, mCurrentPosition, null)

// 移動(dòng)的商品圖片(動(dòng)畫圖片)的坐標(biāo)設(shè)置為該中間點(diǎn)的坐標(biāo)

? ? ? ? goods.translationX = mCurrentPosition[0]

goods.translationY = mCurrentPosition[1]

}

? ? // 五、 開始執(zhí)行動(dòng)畫

? ? valueAnimator.start()

// 六、動(dòng)畫結(jié)束后的處理

? ? valueAnimator.addListener(object : Animator.AnimatorListener {

override fun onAnimationStart(animation: Animator) {}

//當(dāng)動(dòng)畫結(jié)束后:

? ? ? ? override fun onAnimationEnd(animation: Animator) {

// 寫個(gè)接口回調(diào)動(dòng)畫結(jié)束了

? ? ? ? ? ? listener.onDataRefresh(1,"","")

// 執(zhí)行 購(gòu)物車放大再還原動(dòng)畫

? ? ? ? ? ? endView.startAnimation(AnimationUtils.loadAnimation(xmlLayout.context, R.anim.big_small))

// 把移動(dòng)的圖片imageview從父布局里移除

? ? ? ? ? ? xmlLayout.removeView(goods)

}

override fun onAnimationCancel(animation: Animator) {}

override fun onAnimationRepeat(animation: Animator) {}

})

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容