我們的app經(jīng)常遇到這樣一種場景照雁,就是小圖到大圖的轉換避矢,這時候如果有個縮放動畫就會很自然。本節(jié)將介紹如何使用動畫進行縮放圖片,在點擊頭像看大圖這種場景可以使用审胸。本文的例子的示意圖如下所示:
創(chuàng)建View
布局主要包含兩個View亥宿,一個ImageButton用于加載縮略圖,一個ImageView用于顯示大圖砂沛。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
android:id="@+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".animation.EnlargeImageActivity">
<ImageButton
android:id="@+id/imageBtn"
android:layout_width="100dp"
android:layout_height="75dp"
android:scaleType="centerCrop"
android:src="@drawable/pic_11"/>
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/pic_11"
android:visibility="invisible"/>
</android.support.constraint.ConstraintLayout>
設置縮放動畫
ImageButtton觸發(fā)動畫烫扼,這里就不贅述了。
縮放動畫
大體上碍庵,你需要從正常尺寸的View的界限動畫到大尺寸的View的界限映企。下面的方法通過四步介紹了如何實現(xiàn)一個從縮略圖到大圖的放大動畫。
分配大圖給ImageView静浴,即放大后的View堰氓。下面的代碼是在主線程中加載圖片的,這個過程在現(xiàn)實app中一般是要進行網(wǎng)絡操作的苹享,需要放在非UI線程双絮。理想狀態(tài)下,這個圖片的尺寸是不應該超過屏幕尺寸的得问。
計算ImageView的起始和結束尺寸囤攀。
從起始尺寸同時動畫四個屬性:X、Y宫纬、SCALE_X和SCALE_Y焚挠。這四個參數(shù)一起加入到AnimationSet,以便可以同時動畫漓骚。
使用一個相似的動畫作用于大的ImageView蝌衔,當點擊后,圖片縮小回去蝌蹂,最后隱藏ImageView徐紧。
從小到大動畫
代碼如下:
//從小到大
private fun zoomImageFromThumb() {
mCurrentAnimator?.cancel()
imageView.setImageResource(R.drawable.pic_11)
//獲取尺寸
val startBoundsInt = Rect()
val finalBoundsInt = Rect()
val globalOffset = Point()
imageBtn.getGlobalVisibleRect(startBoundsInt)
imageView.getGlobalVisibleRect(finalBoundsInt, globalOffset)
//調整使top=left=0
startBoundsInt.offset(-globalOffset.x, -globalOffset.y)
finalBoundsInt.offset(-globalOffset.x, -globalOffset.y)
val startBounds = RectF(startBoundsInt)
val finalBounds = RectF(finalBoundsInt)
//計算寬高縮放比
val startScale: Float
if ((finalBounds.width() / finalBounds.height() > startBounds.width() / startBounds.height())) {
startScale = startBounds.height() / finalBounds.height()
val startWidth: Float = startScale * finalBounds.width()
val deltaWidth: Float = (startWidth - startBounds.width()) / 2
startBounds.left -= deltaWidth.toInt()
startBounds.right += deltaWidth.toInt()
} else {
// Extend start bounds vertically
startScale = startBounds.width() / finalBounds.width()
val startHeight: Float = startScale * finalBounds.height()
val deltaHeight: Float = (startHeight - startBounds.height()) / 2f
startBounds.top -= deltaHeight.toInt()
startBounds.bottom += deltaHeight.toInt()
}
imageBtn.visibility = View.INVISIBLE
imageView.visibility = View.VISIBLE
imageView.pivotX = 0f
imageView.pivotY = 0f
mCurrentAnimator = AnimatorSet().apply {
//x皮胡、y膝晾、scaleX于樟、scaleY四個維度一起動畫
play(ObjectAnimator.ofFloat(
imageView,
View.X,
startBounds.left,
finalBounds.left)
).apply {
with(ObjectAnimator.ofFloat(imageView, View.Y, startBounds.top, finalBounds.top))
with(ObjectAnimator.ofFloat(imageView, View.SCALE_X, startScale, 1f))
with(ObjectAnimator.ofFloat(imageView, View.SCALE_Y, startScale, 1f))
}
duration = mShortAnimationDuration.toLong()
interpolator = DecelerateInterpolator()
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
mCurrentAnimator = null
}
override fun onAnimationCancel(animation: Animator) {
mCurrentAnimator = null
}
})
start()
}
}
其中有一點說明艘希,寬高采用了同樣的縮放比硼身,但是由于初始尺寸的寬高比不一定完全等于結束時的寬高比,因此會對初始尺寸進行微調覆享,使比例與最終比例一致佳遂。針對我們這里的情況,示意圖如下: ![]
初始寬高比大于1撒顿,結束寬高比小于1丑罪,為了統(tǒng)一,對初始尺寸進行調整,如中間圖所示吩屹。
從大到小縮放
從大到小的縮放動畫與上面的動畫相反跪另,這里就不貼代碼了,感興趣的可以去后面找demo地址查看煤搜。
縮放比例不一致的效果
上面的例子與官方類似免绿,都是縮放比例一致。本著好奇心擦盾,試試縮放比例不一致的效果如何嘲驾。
效果如下:
反正我是沒怎么看出差距來,看出來的差距的歡迎留言我迹卢。
總結
關于代碼辽故,請移步Github地址。這次對整個項目做了個整理腐碱,更好查看各個demo了誊垢,樣式如下:
參考
關注我的技術公眾號,不定期會有優(yōu)質技術文章推送喻杈。微信掃一掃下方二維碼即可關注: