React Native — Pressable props

葉明哲 (Brian Yeh)
5 min readDec 5, 2020

--

Pressable 特性示意圖 ref: https://reactnative.dev/docs/assets/d_pressable_anatomy.svg

幫 Pressable 的所有 Props 實作一個範例程式

React Native 0.63 出了一個新元件 — Pressable,這篇文章將會實測每個 props 的用法,另外會分享一些實作中的感想。

範例程式在這: https://snack.expo.io/@tp26610/pressableprops

就讓我們開始吧!

children

View 一樣,children 可以有多個 Component。而 Touchable 系列 Component 只能有一個 children component,如果想有多個 children component 就必須包一層 View

delayLongPress

onPressIn 延遲的幾毫秒後,觸發 onLongPress,預設是 500 毫秒。

disabled

disabled 如果為 true,此按鈕就無法被點選,onPressInonPressonPressOut 也不會被呼叫。外觀不會有任何改變,如果希望外觀能改變的話就必須自己多實作一個 disabled 狀態的 style。

hitSlop

向外延伸的有效點擊範圍,可以是 number 或是 Rect 物件。

PS: 要用實體機測試才會有效果,用 snack 的 web 跑無效。

onLongPress

預設是長案 500 ms 時,callback function 會被呼叫

onPress、onPressIn、onPressOut

輸入參數要是一個 function,function 會有一個 pressEvent 的參數,實測之後發現跟官網說的 PressEvent 不一樣。

在 Snack 的 Web 環境測試結果如下:

因為 JSON.stringify(pressEvent) 會出現 cyclic 錯誤,所以只取 pressEvent物件的第一層純值的參數

在 Snack 的 Web 環境測試結果如下:

{   
"bubbles": false,
"cancelable": false,
"defaultPrevented": false,
"eventPhase": 3,
"isTrusted": true,
"timeStamp": 2393361.9949999847
}

發現 timestamp 的 S 是大寫啊,不是官方文件說的 timestamp

在 iPhone 8 實體機測試結果是如下:

onPressIn >> pressEvent={
"timeStamp": 1607102475094
}
onPress >> pressEvent={}
onPressOut >> pressEvent={}

只有 onPressIn 會有 timeStamp

另外在 iPhone 實體機有實測到以下現象:

  1. 當使用者點擊按鈕時,依序被呼叫的 props 是 onPressInonPressonPressOut
  2. 當使用者按著不放,然後在按鈕元件內放開,依序被呼叫的 props 是 onPressInonPressOutonPress
  3. 當使用者按著不放,手指保持壓著螢幕移出按鈕元件範圍,移出按鈕範圍時,就會觸發 onPressOutonPress 則不會被呼叫。

單純看 props 的名字還以為一定會是 onPressonPressInonPressOut 的順序呢!

pressRetentionOffset

向外延伸的有效 onPressOut 範圍,輸入參數和 hitSlop prop 一樣,沒設定 pressRetentionOffset時,手指壓著 Pressable 元件不放,當手指移出 Pressable 元件時就會觸發 onPressOut。加上此 prop 就會讓 onPressOut 觸發的範圍向外延伸。

PS: 要用實體機測試的效果才會準,用 snack 的 web 跑 onPressOut 的有效範圍會變很大。

android_disableSound

Android 開啟觸控音效後,點擊按鈕都會有觸控音效,當此 prop 為 true 時,即使手機有開啟觸控音效,點擊後也不會有聲音。

PS: 此 prop 只有在 Android 的裝置上才會有效果

android_ripple

Android 的按鈕預設點擊會有漣漪動畫,至少需設定 RippleConfig 中的 color 和實作 onPress props ,點擊後才會有漣漪動畫。設定 borderless 會讓漣漪動畫效果超出元件,動畫圓的半徑會是元件中心點到對角的長度。

PS: 此 prop 只有在 Android 的裝置上才會有效果

結語

目前我體會到 Pressable 最方便的地方在於它也是一個 View,style 能直接設定有關 View 的參數,能直接容納多個 children component。而且有時按鈕會太小,很難點擊,而 Pressable 有 prop 直接支援向外延伸的點擊範圍,能輕易克服點擊範圍太小的問題。

但也不是沒有缺點, Pressable 預設是沒有點擊動畫,需要自己加上點擊的樣式,有時候自己寫一些簡單的程式還是 TouchableOpacity 比較好用,預設會有點擊透明的動畫。

--

--

葉明哲 (Brian Yeh)

沒事就愛寫點小程式,夢想能建立一個永續的軟體團隊