背景是這樣的:有一個需求要對下方的關注按鈕實現如下動畫,動畫的最后要根據滑動位置對關注按鈕進行縮放,縮放結束時整體大小為控件原始大小的90%,最終效果圖如下所示(模擬器是 4.2 的系統,最上面的沉浸式有點問題,忽略之):
如圖,關注按鈕向上滑動到某臨界位置時,按鈕需要縮小;同樣,向下滑動到相同的臨界位置時,需要放大。
在布局文件中,關注按鈕整體布局為RelativeLayout,愛心ImageView和文字TextView居中。
由於動畫需要根據滑動位置動態計算,因此不能用縮放動畫實現。當滑動到臨界位置時,我做如下處理:
float scale = 1- 0.1f * (scrollY - 100) / 10; //scale范圍:1.0~0.9
mLayoutFollow.setPivotX(1.0f);
mLayoutFollow.setPivotY(1.0f);
mLayoutFollow.setScaleX(scale);
mLayoutFollow.setScaleY(scale);
上述代碼中,縮放比例scale 的值是根據滑動距離scrollY 動態計算出來的,其取值范圍為1.0~0.9;設置setPivotX(1.0f)和setPivotY(1.0f)的目的,是想讓關注按鈕(RelativeLayout)的縮放軸點為右下角,但是悲劇的是,這樣的設置並沒有生效,縮放的中心始終為左上角。這與 xml 中設置PivotX和PivotY屬性是相矛盾的(在 xml中,都設置為0.0f,則縮放中心為控件左上角;都設置為0.5f,則縮放中心為控件中心;都設置為1.0f,則縮放中心為控件右下角,詳見博文圖解 Android 動畫中 android:pivotX 和 android:pivotY 屬性的含義)。
測試后發現,只要 setPivotX(float x) 或 setPivotY(float y) 中有一個值為 0,最后的結果都是縮放中心為左上角;而當不設置這兩個值時(即去掉setPivotX/Y這兩行代碼),縮放中心為控件中心。(奇怪,為什么呢?。。)
想到 xml 中還可以將PivotX屬性設置為整數,於是這樣設置:
mLayoutFollow.setPivotX(100);
mLayoutFollow.setPivotY(0.0f);
發現,縮放中心變為控件最上方,但偏右一些,說明setPivotX(100)生效了。
據此啟發,於是,得到最終設置縮放中心為控件右下角的方法如下:
float scale = 1- 0.1f * (scrollY - 100) / 10;//scale范圍:1.0~0.9
mLayoutFollow.setPivotX(X); //X為控件寬度的px值,以實際情況為准
mLayoutFollow.setPivotY(Y); //Y為控件寬度的px值,以實際情況為准
mLayoutFollow.setScaleX(scale);
mLayoutFollow.setScaleY(scale);
設置控件縮放中心為其他位置的方法亦類似。
查看 View 的setPivotX源碼如下:
/**
* Sets the x location of the point around which the view is
* {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
* By default, the pivot point is centered on the object.
* Setting this property disables this behavior and causes the view to use only the
* explicitly set pivotX and pivotY values.
*
* @param pivotX The x location of the pivot point.
* @see #getRotation()
* @see #getScaleX()
* @see #getScaleY()
* @see #getPivotY()
*
* @attr ref android.R.styleable#View_transformPivotX
*/
public void setPivotX(float pivotX) {
if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
invalidateViewProperty(true, false);
mRenderNode.setPivotX(pivotX);
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
}
}
翻譯前面的注釋:默認情況下(不設置時),軸點位於控件中心處;設置該屬性后,控件只會明確地使用所設置的軸點位置。而參數pivotX的含義是軸點的 x 位置(這里應該就是絕對位置了)。
不知道這樣的理解是不是正確的。。。╮(╯▽╰)╭ 尷尬~~~拋磚引玉,還望知道的小伙伴告知~