移動端界面設計如此火熱的今天,各種大廠的設計規範和設計語言已經很是的成熟,咱們想作一些在這套成熟的設計規範以外的嘗試和創新,因此有別於傳統的banner交互形式成爲了咱們的發力點。前端
因爲app版面空間有限,除了功能導向、閱讀習慣和設計美觀外,自如想在既定的框下,作一下不一樣的設計嘗試,哪怕這種嘗試只能提高用戶1%的觀感。可能租了幾年自如的房子,用了幾年自如客app,你可能也不會注意到一些小的細節。但若是哪天,做爲用戶的你忽然發現了這個隱藏的「彩蛋」,看到了自如在這些小細節上的用心,我相信那天你將會對自如這個品牌有更深層次的認識和理解。java
裸眼3D技術通常都是應用在裸眼3D大屏、全息投影等等比較常見的場景中,在APP的banner上應用,的確也是一次全新的嘗試。咱們經過藉助移動設備上的傳感器、以及自身的屏顯清晰度、畫面呈現,將2D影像轉化爲景深效果,以呈現出不用"3D"眼鏡就可看到的3D效果。markdown
如下以Android爲例,介紹一下該效果的實現方式。app
自如客app的banner其實一直在創新當中,有專門注意過的同窗可能知道,在裸眼3D效果以前,自如客app其實就已經實現了分層,當時爲了實現更加天然和精緻的切換效果:在每一個banner滑入滑出的時候,底部其實會在原地進行漸顯漸隱,內容會跟隨手勢滑入滑出。這次爲了實現3D效果,咱們在之前分層的基礎上加了一層中景,將原有的前景拆分爲前景和中景。oop
上圖的sl_bg爲背景,pv_middle爲中景,sl爲前景佈局
因爲切換的交互,實際上banner使用了兩個viewpager進行了聯動。背景在最底層的viewpager裏面,中景和前景在另一個viewpager裏。this
打開自如客app後,用戶操做設備能夠明顯感覺到畫面的錯位移動,形成視覺上的景深效果。這種錯位移動其實就是藉助設備自己的傳感器來實現的,具體實現方式是咱們讓中景始終保持不動,同時從設備傳感器獲取當前設備對應的傾斜角,根據傾斜角計算出背景和前景的移動距離,而後執行背景和前景移動的動做。以下圖所示:spa
爲了使用的方便,咱們封裝了一個SensorLayout,專門用於根據設備的傾斜角執行內容的位移; SensorLayout內部的主要實現:設計
mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
// 重力傳感器
mAcceleSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
// 地磁場傳感器
mMagneticSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mSensorManager.registerListener(this, mAcceleSensor, SensorManager.SENSOR_DELAY_GAME);
mSensorManager.registerListener(this, mMagneticSensor, SensorManager.SENSOR_DELAY_GAME);
複製代碼
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mAcceleValues = event.values;
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
mMageneticValues = event.values;
}
float[] values = new float[3];
float[] R = new float[9];
SensorManager.getRotationMatrix(R, null, mAcceleValues, mMageneticValues);
SensorManager.getOrientation(R, values);
// x軸的偏轉角度
values[1] = (float) Math.toDegrees(values[1]);
// y軸的偏轉角度
values[2] = (float) Math.toDegrees(values[2]);
複製代碼
經過重力傳感器和地磁場傳感器,獲取設備的偏轉角度code
if (mDegreeY <= 0 && mDegreeY > mDegreeYMin) {
hasChangeX = true;
scrollX = (int) (mDegreeY / Math.abs(mDegreeYMin) * mXMoveDistance*mDirection);
} else if (mDegreeY > 0 && mDegreeY < mDegreeYMax) {
hasChangeX = true;
scrollX = (int) (mDegreeY / Math.abs(mDegreeYMax) * mXMoveDistance*mDirection);
}
if (mDegreeX <= 0 && mDegreeX > mDegreeXMin) {
hasChangeY = true;
scrollY = (int) (mDegreeX / Math.abs(mDegreeXMin) * mYMoveDistance*mDirection);
} else if (mDegreeX > 0 && mDegreeX < mDegreeXMax) {
hasChangeY = true;
scrollY = (int) (mDegreeX / Math.abs(mDegreeXMax) * mYMoveDistance*mDirection);
}
smoothScrollTo(hasChangeX ? scrollX : mScroller.getFinalX(), hasChangeY ? scrollY : mScroller.getFinalY());
複製代碼
mDegreeX即爲第二部中獲取的偏轉角度,mDegreeXMin和mDegreeXMax爲X軸可發生偏轉位移的角度最大值和最小值,mYMoveDistance即爲Y軸上的最大偏移距離(圍繞X軸發生旋轉,視圖會沿Y軸上發生位移);Y軸上的偏轉同理;就算好X軸和Y軸的偏移距離後,使用scroller進行滑動;
讀到這裏,相信你們已經基本瞭解了這套banner的實現方案。Android端在佈局上進行了分層,中景位置不變,藉助重力傳感器和地磁場傳感器獲取偏轉角度,根據角度使背景和前景進行錯位移動。iOS端的實現原理也基本一致,再也不贅述。
本文做者:自如大前端研發中心-黃進
自如大前端研發中心招募新同窗!
FE/IOS/Android工程師看過來
公司福利有:
- 全額五險一金,並額外購買商業保險
- 免費健身房+年度體檢
- 公司附近租房9折優惠
- 每一年2次晉升機會
辦公地點:北京酒仙橋普天實業科技園 歡迎對技術有執着熱愛的你加入咱們!簡歷請投遞 zhangxl122@ziroom.com!