Android屬性動畫之旋轉(zhuǎn)動畫

CSDN同步發(fā)布

旋轉(zhuǎn)動畫有三種

  1. 繞著豎直中心線旋轉(zhuǎn)
  2. 繞著水平中心線旋轉(zhuǎn)
  3. 繞著中心點(diǎn)平面選擇

繞著豎直中心線旋轉(zhuǎn)

 val rotationYAnimator = ObjectAnimator.ofFloat(ivRotationY, "rotationY", 0f, 360f)
 rotationYAnimator.duration = 3000
 rotationYAnimator.start()

角度增加是逆時(shí)針方向旋轉(zhuǎn)。注意,如果旋轉(zhuǎn)角度是90度的話,最終View會不可見。

Screenrecorder-2021-07-17-14-48-54-431.gif

當(dāng)要旋轉(zhuǎn)的View尺寸很小的時(shí)候,效果很好,但是當(dāng)View很大的時(shí)候,就出問題了。如下所示:

Screenrecorder-2021-07-17-14-56-22-628.gif

當(dāng)時(shí)很奇怪為啥會這樣呢?最后是在這篇文章實(shí)現(xiàn)翻轉(zhuǎn)卡片的動畫效果看到了一個(gè)叫cameraDistance的東西,然后感覺可能這個(gè)有用,試了試果然可以。

View的 getCameraDistance 方法。

public float getCameraDistance() {
    final float dpi = mResources.getDisplayMetrics().densityDpi;
    return -(mRenderNode.getCameraDistance() * dpi);
}

View的 setCameraDistance 方法,看注釋。

/**
 * 設(shè)置從相機(jī)到這個(gè)View沿Z軸(和View繪制所在的X/Y平面正交)的距離。相機(jī)的距離會影響3D變化,
*  例如繞著X和Y軸旋轉(zhuǎn)。
 * 如果View的rotationX或者rotationY屬性發(fā)生了變化并且View的較大(超過屏幕大小的一半),
 * 建議始終使用大于此視圖高度(繞X軸旋轉(zhuǎn))或?qū)挾龋╕軸旋轉(zhuǎn))的相機(jī)距離。
 
 * 當(dāng)View繞X或Y軸旋轉(zhuǎn)時(shí),相機(jī)與視圖平面的距離會對視圖的透視失真產(chǎn)生影響。
 * 例如,一個(gè)大的距離會導(dǎo)致一個(gè)大的視角,當(dāng)View旋轉(zhuǎn)的時(shí)候,不會太多的透視失真。
 * 一個(gè)短的距離在View旋轉(zhuǎn)的時(shí)候會導(dǎo)致更多的透視失真,
 * 如果旋轉(zhuǎn)后的視圖部分位于攝影機(jī)后面,也可能導(dǎo)致一些圖形瑕疵。(這也是為什么建議當(dāng)View旋轉(zhuǎn)的時(shí)候,
 * 至少使用和View一樣大的距離。)

 * 這個(gè)相機(jī)距離用“深度像素”來表示。默認(rèn)的距離依賴屏幕的密度。例如,在一個(gè)中等密度的屏幕上,默認(rèn)的距離是1280。
 * 在高密度的屏幕上,默認(rèn)距離是1920。
    
 * 如果要指定一個(gè)距離,以便在不同的密度中獲得視覺上一致的結(jié)果,可以使用下面的公式。
 * float scale = context.getResources().getDisplayMetrics().density;
 * view.setCameraDistance(distance * scale);
 *
 * @param distance 以“深度像素”為單位的距離,如果為負(fù)數(shù),則使用相反的值
 */
public void setCameraDistance(float distance) {
    final float dpi = mResources.getDisplayMetrics().densityDpi;

    invalidateViewProperty(true, false);
    mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
    invalidateViewProperty(false, false);

    invalidateParentIfNeededAndWasQuickRejected();
}

注意:注釋中的這段這個(gè)相機(jī)距離用“深度像素”來表示。默認(rèn)的距離依賴屏幕的密度。例如,在一個(gè)中等密度的屏幕上,默認(rèn)的距離是1280。在高密度的屏幕上,默認(rèn)距離是1920。我認(rèn)為這個(gè)單位是dp。1280dp,1920dp。我的測試機(jī)density是2.75,通過getCameraDistance方法,獲取到的值是3520.0,3520.0除以2.75就是1280。

注意:關(guān)于設(shè)置cameraDistance,建議始終使用大于此視圖高度(繞X軸旋轉(zhuǎn))或?qū)挾龋╕軸旋轉(zhuǎn))的相機(jī)距離。而且這個(gè)距離得比較大才行,我測試下來得10000以上才可以。如下所示:

//我的測試機(jī)density是2.75
val density = resources.displayMetrics.density
val cameraDistance = density * 10000
ivRotationY.cameraDistance = cameraDistance
Screenrecorder-2021-07-17-15-49-13-98.gif

繞著水平中心線旋轉(zhuǎn)

同樣需要設(shè)置cameraDistance

 val rotationXAnimator = ObjectAnimator.ofFloat(ivRotationY2, "rotationX", 0f, 360f)
 val density = resources.displayMetrics.density
 val cameraDistance = density * 10000
 ivRotationY2.cameraDistance = cameraDistance

 rotationXAnimator.duration = 3000

 rotationXAnimator.start()
Screenrecorder-2021-07-17-15-33-29-596.gif

繞著中心點(diǎn)平面選擇

平時(shí)這個(gè)用的比較多應(yīng)該,也比較簡單。也不涉及 cameraDistance 的東西。

Screenrecorder-2021-07-17-15-42-18-75.gif

參考鏈接

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

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

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