這交互炸了 陀螺儀圖片「VR 看房」效果
原標題:這交互炸了 陀螺儀圖片「VR 看房」效果
本文作者
作者:jiangye
鏈接:
https://www.jianshu.com/p/1d3abe34c895
本文由作者授權發布。
1
概述
最近要抽取年前做的 VR 看房的相關功能至單獨的倉庫,藉此機會對其中利用陀螺儀滑動圖片的處理方式,以及平滑過渡至 VR 看房場景的過程做一個說明,也能讓接手 VR 相關模塊的同事更快了解其實現方式。
平滑過渡至 VR看房 場景
首先解析利用陀螺儀滑動圖片的處理方式。
在這裡主要說一說自己的思路,具體代碼會在最後給出 Demo 以供參考。
2
思路
為試驗該效果,自定義了一個繼承自ImageView的GyroscopeImageView,再寫一個實現SensorEventListener介面的GyroscopeManager。
在其onSensorChanged回調中利用陀螺儀感測器角度的變化來換算出圖片需要滑動的距離,並調用GyroscopeImageView的invalidate()方法,在GyroscopeImageView的onDraw方法中利用canvas.translate來改變圖片的位置。
效果如下:
圖片隨陀螺儀感測器滑動效果
在開發過程中注意到的問題:
1. 圖片的尺寸要合理,寬高略大於控制項能有較好的視覺效果。
2. 監聽陀螺儀感測器事件耗電,要在合適的時候註冊和註銷對感測器的監聽。
3. 當應用內有多個GyroscopeImageView時,要對它們進行合理的管理。
作為一個寫在獨立倉庫中的功能,要讓業務方能夠方便地接入使用。
但關於上面提到的前兩個問題,還需業務方的配合來解決:
1. 業務方在使用GyroscopeImageView控制項時,需要告知我們控制項的寬高,這樣我們能合理地對圖像尺寸做處理。
//例如用 Picasso載入圖像 可將控制項的寬高傳入自定義的 TransFormation 來處理圖像大小
Picasso. get()
.load(picUrl)
.transform( newGyroscopeTransFormation(width, height))
. into(gyroscopeImageView);
2. 業務方需要在相關Activity的onResume和onPause中對陀螺儀感測器進行註冊和註銷監聽。
@OverrideprotectedvoidonResume(){
super.onResume();
//利用我們的 GyroscopeManager 來註冊感測器監聽
GyroscopeManager.getInstance().register( this);
}
@OverrideprotectedvoidonPause(){
super.onPause();
//利用我們的 GyroscopeManager 來註銷監聽
GyroscopeManager.getInstance().unregister( this);
}
這樣看起來業務方接入還是比較簡單的。
重點分析一下第三個問題:
如何對應用內的GyroscopeImageView進行合理的管理。
3. 當有多個GyroscopeImageView存在時,GyroscopeManager應只對當前Activity中正在展示的GyroscopeImageView進行刷新。
想到View在添加至Window時會調用 View.onAttachedToWindow(),之後才進行繪製,當View與Window分離時會調用onAttachedToWindow()
由此得出的初步想法:在GyroscopeManager中維護一個GyroscopeImageView的集合。在GyroscopeImageView的onAttachedToWindow方法中將自身加入該集合,onDetachedFromWindow時將自身從集合中移除。而GyroscopeManager在感測器的回調中,去通知集合內的 view 進行刷新。
調試中發現該想法考慮不周,如果在一個包含GyroscopeImageView的頁面 Activity1 之上開啟一個 Activity2,此時 Activity1 內的GyroscopeImageView還在PhoneWindow內沒有調用onDetachedFromWindow(),因此該View還在 GyroscopeManager所維護的集合中。
若 Activity2 中也有GyroscopeImageView,則會註冊感測器監聽,且刷新集合內所有GyroscopeImageView。這樣一來被覆蓋在下層的 Activity1 內的GyroscopeImageView也會被通知刷新,這是沒有必要的,因為此時它並不可見。所以還需維護一個需要感測器處理的 Activity, 只通知該 Activity 內的GyroscopeImageView進行刷新。
最後針對GyroscopeImageView維護了一個Map:
Map<GyroscopeImageView, Boolean>
其 value 為Boolean標識該GyroscopeImageView是否需要被GyroscopeManager通知刷新。通過 Activity 的狀態變化來設置Map中各個GyroscopeImageView對應的 value,進行合理控制。
3
平滑過渡至 VR 場景頁
接下來說說從房源詳情頁平滑過渡至 VR 場景頁的動畫。
同樣先談一談實現該效果的思路,最後會給出 Demo 以供參考。
此處從房源詳情頁 Activity 跳轉至 VR 場景的 Activity,不同 Activity 內的 View 之間做動畫可以使用 Activity 轉場動畫。
但是我們GyroscopeImageView內的圖片是可滑動的,使用 Activity 轉場動畫會發現控制項內的圖片會瞬間居中回正,然後再擴展到全屏,該居中的過程較為突兀,有明顯的閃動感。
更加平滑的效果是使GyroscopeImageView內的圖片直接從當前的狀態擴展至全屏,最終放棄Activity轉場動畫,並提出如下解決方案:
1. 首先記錄第一個 Activity 中GyroscopeImageView控制項的位置和其內部圖片的偏移量。
2. 在第二個 Activity 中放置一個相同位置的ImageView, 並展示相同偏移量的圖片,用來覆蓋住上個頁面的GyroscopeImageView控制項。然後將該ImageView擴展至全屏做動畫。
3. 把第二個 Activity 的背景設為透明。
平滑的過度動畫
Demo地址:
https://github.com/JY39/GyroscopeImageDemo
TAG:鴻洋 |