1. 程式人生 > >解決 Android 中 View 的 setPivotX 和 setPivotY 不生效的問題以及設定縮放中心的方法

解決 Android 中 View 的 setPivotX 和 setPivotY 不生效的問題以及設定縮放中心的方法

背景是這樣的:有一個需求要對下方的關注按鈕實現如下動畫,動畫的最後要根據滑動位置對關注按鈕進行縮放,縮放結束時整體大小為控制元件原始大小的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 位置(這裡應該就是絕對位置了)。

不知道這樣的理解是不是正確的。。。╮(╯▽╰)╭ 尷尬~~~拋磚引玉,還望知道的小夥伴告知~