Window Shade
我手上的Samsung Galaxy S3的作業系統是Android 4.0.4。
當我收到facebook/google+/…等程式通知的時候,最上面那條bar會出現對應的圖示。
這時候可以透過將bar「滑下來」的動作拉出一個UI,裡面會有
快速設定
通知項目詳細列表
這個UX,Google把它稱為Window shade
神奇的地方在於當你在拉下或拉上面板的同時,
快速設定與通知項目是會先「掉下來」到底端,
到了項目的頂端出現之後才會黏在頂部。
(相信我你沒有特別注意這件事情,而且用久了會覺得理所當然)
GAIA也有notification panel
Firefox OS的UI – GAIA 裡面也有定義功能列以及通知面板這件事,
這個功能正在開發中。
有一天我們收到某個contributor提交的pull request:
Gaia pull request#1898
節錄重要的修改如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
onTouchMove : function ut_onTouchMove ( touch ) {
var screenHeight = this . overlay . getBoundingClientRect (). height ,
gripBarHeight = this . gripBar . getBoundingClientRect (). height ,
dy = - ( this . startY - touch . pageY ),
newHeight ;
if ( this . shown )
dy += screenHeight ;
dy = Math . min ( screenHeight , dy );
if ( dy > gripBarHeight ) {
var quickSettingsHeight = this . quickSettings . getBoundingClientRect (). height ;
if ( dy < quickSettingsHeight + gripBarHeight ) {
newHeight = screenHeight - quickSettingsHeight - gripBarHeight ;
} else {
newHeight = screenHeight - dy ;
}
this . quickSettings . style . MozTransition = '' ;
this . quickSettings . style . MozTransform = 'translateY(' + newHeight + 'px)' ;
}
var style = this . overlay . style ;
style . MozTransition = '' ;
style . MozTransform = 'translateY(' + dy + 'px)' ;
},
//....skiped...
show : function ut_show ( dy ) {
var alreadyShown = this . shown ,
trayStyle = this . overlay . style ,
quickSettingsStyle = this . quickSettings . style ;
trayStyle . MozTransition = '-moz-transform 0.2s linear' ;
trayStyle . MozTransform = 'translateY(100%)' ;
quickSettingsStyle . MozTransition = '-moz-transform 0.2s linear' ;
quickSettingsStyle . MozTransform = 'translateY(0px)' ;
this . shown = true ;
this . screen . classList . add ( 'utility-tray' );
if ( ! alreadyShown ) {
var evt = document . createEvent ( 'CustomEvent' );
evt . initCustomEvent ( 'utilitytrayshow' , true , true , null );
window . dispatchEvent ( evt );
}
}
原作者提到他做這件事是要讓quick-setting
更快的出現。
這段code也已經被merge了。
不過就在昨天同事發現了一個關於功能列的issue
於是我開始看發生了什麼事。然後上面那兩個function耗費了我一個下午….XD
@colinfrei其實做了一件非常有趣但是很難從code裡面看出端倪的事情。
甚至也很難用語言來描述,不過我想試著說明發生了什麼事,怎麼做到的。
簡單的說,他利用兩個「不同」區塊的CSS3的Transition「同步化」來實現剛剛所提的Window Shade的行為。
CSS: Transition
參閱MDN: transition
CSS: Transform
參閱MDN: transform
真相其實是:
utility-tray
是一個絕對定位的div
,平常位置定在螢幕上方-moz-calc(100% – UTILITY_TRAY_HEIGHT)
。
當你開始Touch的時候,根據你的移動距離計算translateY
,使它產生位移
你可以把-moz-transform: translateY(px)
當成是top: px
在CSS3的新招。
它提供了更快速的rendering — 當你想利用-moz-transition: -moz-transform
來做位移動畫的時候。
這件事情可以另外寫一篇文章來說(挖洞的意味)。
當你放開拉bar的時候而且如果已經超過「要讓通知面板掉下來的合法距離」:
設定一個MozTransition
給utility-tray-overlay
再設定一個MozTransition
給quick-setting
4.讓utility-tray
整個以某個定速掉下來到螢幕底端 + 讓quick-setting
以同樣的定速往上移動到utility-tray
的開端
= 於是就造成了quick-setting
似乎黏在通知列下方不動但整個面板是往下掉的假象!
the story continues
不過可惜的是似乎沒有考慮到當通知面板要滑上去的時候,
「有物件的部份也應該留在頂端直到被拉bar撞到一起彈上去」這件事
於是我也仿造這個作法另外送了一個pull request
GAIA pull request#2181
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
case 'transitionend' :
if ( ! this . shown ) {
this . screen . classList . remove ( 'utility-tray' );
var overlayStyle = this . overlay ;
var firstShownStyle = this . firstShowStyle ;
firstShownStyle . MozTransition = '' ;
if ( this . phase2hide ) {
firstShownStyle . MozTransition = '-moz-transform 0.2s linear' ;
firstShownStyle . MozTransform =
'translateY(' + this . firstShownPosition + 'px)' ;
overlayStyle . MozTransition = '-moz-transform 0.2s linear' ;
overlayStyle . MozTransform = 'translateY(0)' ;
// Check the transition event is triggered at firstShown.
// If so, turn off the flag which represent for
// 'The overlay has already reached the bottom of quick-setting'
if ( evt . target == this . firstShown )
this . phase2hide = false ;
} else {
// Reset position of this.firstShown
this . firstShown . style . MozTransition = '' ;
this . firstShown . style . MozTransform = 'translateY(0)' ;
}
}
break ;
利用transitionend
event callback,透過連續兩次的Transition
來:
讓utility-tray
先定速往上移動/讓quick-setting
定速往下移動到底端。
等到utility-tray
的transition結束時,會收到transitionend
的事件。
這時候再讓utility-tray
進行第二次transition…而目的地就是螢幕頂端。
同時quick-setting
就不再動作了,讓它跟著utility-tray
一起被往上卷走。
transitionend
參閱MDN: transitionend
the end?
其實UX還沒有定義這個行為,所以pull request本身沒有被接受。
不過…I did learn something from these codes:)