BottomSheetを使う機会があったので使い方あれこれまとめる。
公式ドキュメントは結構読みづらいんですよね。
日本語にすると文字消えたりするし毎回あれこれ調べるの面倒なので自分なりに整理。
細かい部分とかは別記事で
BottomSheetとBottomSheetModalの違い
1:レンダリング位置
・BottomSheetは親コンポーネント内にレンダリング
・BottomSheetModalは@gorhom/portalを使用して、アプリケーションの最上位にレンダリング
2:使用目的
・BottomSheetは通常、画面の一部として常に表示されるコンポーネントに使用される
・BottomSheetModalは、ボタンクリックなどのアクションによって表示/非表示を切り替えるモーダルとして使用される
3:表示制御
・BottomSheetはsnapToIndex()などを使用
・BottomSheetModalはpresent()メソッドを使用
アプリケーションのどこからでも簡単に呼び出すことが可能
4:スタック機能
BottomSheetModalは複数のモーダルをスタックさせる機能をサポート
5:アニメーション
BottomSheetModalは、スムーズな表示/非表示のアニメーションを提供
BottomSheetでもアニメーションは可能。reanimatedと相性がいい
6:柔軟性
アプリケーションのどこからでも呼び出せるのでBottom Sheet Modalのほうが柔軟性高め
普通のBottomSheetもComponent化してしまえば割と柔軟に使える
まとめ
・BottomSheetModalは動的に表示/非表示を切り替える必要がある場合や、アプリケーション全体で共有するボトムシートが必要な場合に適している。
・BottomSheetModalは動的に表示/非表示を切り替える必要がある場合や、アプリケーション全体で共有するボトムシートが必要な場合に適している。
BottomSheetのProps使い方
Configuration
index:最初のSnapPoint
設定したSnapPoint配列のIndex
snapPoints:スナップ可能なPoint配列
スナップポイントを指定する
例:
1 |
['20%','60%','100%'] |
overDragResistanceFactor:最大限まで引き上げた後の抵抗
- 定義:
BottomSheetが最大限まで開いた状態からさらに上方向にドラッグされる際の抵抗力を決定。 - 動作:
値が大きいほど、オーバードラッグ(最大位置を超えてドラッグすること)に対する抵抗が強くなる。 - デフォルト値:2.5
- 効果:
- 値を小さくすると、ユーザーがBottomSheetを最大位置を超えて引き上げやすくなる。
- 値を大きくすると、最大位置を超えてドラッグすることが難しくなる。
- ユーザーエクスペリエンス:
このプロパティを適切に設定することで、BottomSheetの動きをより自然で直感的にすることが可能。ユーザーに対して、Sheetがどこまでドラッグできるかを暗示的に伝えることができる。 - パフォーマンスへの影響:
このプロパティ自体はパフォーマンスにほとんど影響を与えません。アニメーションの滑らかさは主にReanimatedライブラリによって保証されている。
overDragResistanceFactor
を適切に設定することで、BottomSheetの挙動をアプリケーションの要件やデザインに合わせて微調整することができ、より洗練されたユーザーインターフェースを実現可能。
detached:画面の下部から分離
- 目的:
detached
プロパティは、BottomSheetModalを画面の下部から切り離して表示するために使用。 - 動作:
detached={true}
に設定すると、BottomSheetModalは画面の下部に接触せずに浮いた状態で表示detached={false}
(デフォルト)では、BottomSheetModalは画面の下部に接触した状態で表示
- 視覚的効果:
- 有効にすると、BottomSheetModalの周囲に空間が生まれ、より独立したモーダルのように見える。
- 画面の端から少し離れた位置に表示されるため、より目立つデザインになりる。
- 関連プロパティ:
bottomInset
: detachedモードで使用され、画面下部からの距離を指定。style
: detachedモードでの外観をカスタマイズするのに使用(例:角丸、影など)。
- ユースケース:
- より独立したモーダル感を出したい場合
- 画面の他の要素と視覚的に分離したい場合
- 特定のデザインガイドラインに従う必要がある場合
- 注意点:
detached={true}
を使用する場合、適切なbottomInset
値を設定して、BottomSheetModalが画面の下部に十分な余白を持つようにすることが重要。
detached
プロパティを使用することで、より柔軟でカスタマイズされたBottomSheetModalのデザインを実現可能。特に、GoogleマップのようなUIを実装する場合、このプロパティは非常に有用。
enableContentPanningGesture:コンテンツ領域でのパンニングジェスチャー
- 目的:
このプロパティは、BottomSheetのコンテンツ領域でのパンニングジェスチャー(指でドラッグする動作)を有効または無効にするために使用される。 - デフォルト値:
true
- 動作:
true
の場合:ユーザーはコンテンツ領域をドラッグしてBottomSheetを開閉可能。false
の場合:コンテンツ領域でのパンニングジェスチャーが無効になり、BottomSheetの開閉ができなくなりる。
- 注意点:
- このプロパティを
false
に設定すると、BottomSheetScrollViewなどのスクロール可能なコンポーネントの動作に影響を与える可能性がある 参考。 - スクロール可能なコンテンツを含むBottomSheetで
false
に設定すると、スクロールが正常に機能しない問題が報告されている。
- このプロパティを
- 代替案:
- スクロール可能なコンテンツを使用する場合は、
enableContentPanningGesture
をtrue
のままにし、代わりにenablePanDownToClose
プロパティを使用してBottomSheetの閉じる動作を制御することが可能
- スクロール可能なコンテンツを使用する場合は、
- バグ報告:
- このプロパティを
false
に設定した際のスクロールの問題については 参考。
- このプロパティを
enableContentPanningGesture
の使用には注意が必要で、特にスクロール可能なコンテンツを含むBottomSheetを実装する場合は、この設定がユーザーエクスペリエンスに与える影響を十分に考慮する必要あり。
enableHandlePanningGesture:ハンドル部分でのパンニングジェスチャー
- このプロパティは、BottomSheetのハンドル部分でのパンニングジェスチャー(ドラッグ操作)を有効または無効にするために使用。
- デフォルト値:
true
- 動作:
true
の場合:ユーザーはBottomSheetのハンドル部分をドラッグしてシートを開閉。false
の場合:ハンドル部分でのパンニングジェスチャーが無効になり、ハンドルをドラッグしてのシートの開閉ができなくなる。
- ユースケース:
- ハンドル部分でのジェスチャー操作を無効にしたい場合(例:カスタムのヘッダーコンポーネントを使用する場合)
- シートの開閉を特定のボタンやアクションのみに制限したい場合
- 関連プロパティ:
enableContentPanningGesture
: コンテンツ領域でのパンニングジェスチャーを制御します。enablePanDownToClose
: 下方向へのパンニングでシートを閉じる機能を制御します。
- 注意点:
- このプロパティを
false
に設定すると、ユーザーはハンドル部分をドラッグしてシートを操作できなくなるため、他の方法でシートを操作できるようにする必要がある(例:ボタンやプログラムによる制御)。
- このプロパティを
enableHandlePanningGesture
を適切に使用することで、BottomSheetの操作性をカスタマイズし、特定のユースケースやデザイン要件に合わせたインターフェースを実現できる。ただし、ユーザーエクスペリエンスへの影響を考慮し、慎重に設定する必要がある。
enableOverDrag:「オーバードラッグ」機能
- このプロパティは、BottomSheetの「オーバードラッグ」機能を有効または無効にするために使用される。オーバードラッグとは、ユーザーがシートを最大の高さ以上にドラッグできる機能のこと。
- デフォルト値:
true
- 動作:
true
の場合:ユーザーはBottomSheetを最大の高さ以上にドラッグでき、放すとバウンス効果で元の位置に戻ります。false
の場合:BottomSheetは最大の高さで止まり、それ以上ドラッグできなくなる。
- ユーザーエクスペリエンス:
- オーバードラッグを有効にすると、より自然で流動的な操作感を提供。
- 無効にすると、シートの動きがより制限され、正確な位置で停止。
- 関連プロパティ:
overDragResistanceFactor
: オーバードラッグの抵抗力を調整。
- 注意点:
- オーバードラッグを無効にすると、ユーザーの操作感が変わる可能性があるため、UIの一貫性を考慮して設定する必要がある。
enableOverDrag
を適切に使用することで、BottomSheetの動作をアプリケーションの要件やデザインに合わせてカスタマイズ可能。ユーザーの操作感と視覚的なフィードバックのバランスを考慮して設定することが重要。
enablePanDownToClose:BottomSheetを閉じることができるかどうか
- このプロパティは、ユーザーが下方向へのパンニングジェスチャー(下にスワイプする動作)でBottomSheetを閉じることができるかどうかを制御する。
- デフォルト値:
true
- 動作:
true
の場合:ユーザーは下方向へのスワイプでBottomSheetを閉じることができる。false
の場合:下方向へのスワイプでBottomSheetを閉じることができなくなる。
- 注意点:
backdropComponent
を使用している場合、enablePanDownToClose
が正常に機能しない問題 参考。- この問題を解決するには、
backdropComponent
の代わりに別の方法でバックドロップを実装するか、カスタムのクローズロジックを実装する必要あり。
- 関連プロパティ:
enableContentPanningGesture
: コンテンツ領域でのパンニングジェスチャーを制御。enableHandlePanningGesture
: ハンドル部分でのパンニングジェスチャーを制御。
- ユースケース:
- ユーザーがBottomSheetを誤って閉じてしまうのを防ぎたい場合に
false
に設定。 - 特定のボタンやアクションでのみBottomSheetを閉じたい場合に使用。
- ユーザーがBottomSheetを誤って閉じてしまうのを防ぎたい場合に
enablePanDownToClose
を適切に使用することで、BottomSheetの操作性をカスタマイズし、アプリケーションの要件に合わせたユーザーエクスペリエンスを提供。ただし、backdropComponent
との互換性の問題に注意が必要。
enableDynamicSizing:高さをコンテンツの実際のサイズに基づいて動的に調整
- 目的:
このプロパティは、BottomSheetの高さをコンテンツの実際のサイズに基づいて動的に調整することを可能にする。 - 動作:
true
の場合:BottomSheetの高さはコンテンツの高さに応じて自動的に調整されます。false
の場合(デフォルト):BottomSheetの高さは指定されたスナップポイントに基づいて固定されます。
- 注意点:
- 対処法:
- 関連する問題:
- キーボードが開いた際にBottomSheetが全画面サイズに拡大してしまう問題 参考。
- 代替案:
- 問題が解決しない場合、従来の
snapPoints
を使用する方法に戻ることを検討する必要があり 参考。
- 問題が解決しない場合、従来の
ライブラリの最新バージョンを使用し、GitHubのイシューを確認する必要あり。
animateOnMount:最初にマウントされた際のアニメーション動作を制御
- 目的:
このプロパティは、BottomSheetが最初にマウントされた際のアニメーション動作を制御。 - デフォルト値:
true
- 動作:
true
の場合:BottomSheetは最初に閉じた状態でマウントされ、レイアウトが計算された後に初期のスナップポイントインデックスまでアニメーションで開きます。false
の場合:BottomSheetは初期のスナップポイントインデックスの位置で即座に表示されます(アニメーションなし)。
- ユースケース:
- アプリの起動時やページ遷移時に、BottomSheetをスムーズに表示したい場合に使用。
- ユーザーの注意を引きつけたい場合や、UIの変化を自然に見せたい場合に有効。
- パフォーマンスへの影響:
true
に設定すると、初期表示時にアニメーションが実行されるため、わずかにパフォーマンスに影響を与える可能性あり。- パフォーマンスが重要な場合は、
false
に設定することで即座に表示させることが可能。
- 注意点:
- このプロパティは、BottomSheetの初回マウント時にのみ影響します。その後の表示/非表示の動作には影響しません。
overrideReduceMotion:アニメーションを強制的に有効にする
- 目的:
このプロパティは、デバイスの「モーション軽減」設定を無視して、BottomSheetのアニメーションを強制的に有効にするために使用される。 - デフォルト値:
false
- 動作:
false
の場合:デバイスの「モーション軽減」設定に従う。true
の場合:デバイスの「モーション軽減」設定を無視し、常にアニメーションを有効にする。
- ユースケース:
- アプリケーションのUXにとってアニメーションが重要な場合に使用。
- ユーザーのデバイス設定に関わらず、一貫したアニメーション体験を提供したい場合に有効。
- アクセシビリティへの影響:
- このプロパティを
true
に設定すると、モーション感受性の高いユーザーにとっては問題となる可能性あり。 - アクセシビリティを考慮する場合は、慎重に使用する必要がある。
- このプロパティを
- パフォーマンスへの影響:
- アニメーションを強制的に有効にすることで、デバイスのパフォーマンスに影響を与える可能性あり。
overrideReduceMotion
プロパティを使用する際は、ユーザーエクスペリエンスとアクセシビリティのバランスを慎重に検討することが重要。アプリケーションの要件や対象ユーザーに応じて、適切に設定を行うべき。
style:コンテナ全体のスタイル
BottomSheetのコンテナ全体に適用
シャドウ、マージン、パディングなど、BottomSheet全体のレイアウトやスタイリングに使用される。
- 型:
backgroundStyle
:ViewStyle
型を受け取る。style
:ViewStyle | AnimatedStyle
型を受け取ります。アニメーションスタイルも適用可能。
- 優先順位:
backgroundStyle
はbackgroundComponent
プロパティが設定されている場合、無視される可能性がある。style
は常に適用される。
backgroundStyle
で背景の見た目を調整し、style
でBottomSheet全体のレイアウトや視覚効果を制御するという使い分けが可能。
backgroundStyle:背景のスタイル
- BottomSheetの背景のスタイルを変更するために使用される。BottomSheetの背景コンポーネントにのみ適用
- 型:
ViewStyle
型(React NativeのStyleSheet.ViewStyle
)を受け取る。 - カスタマイズ可能な要素:
- 背景色
- ボーダーラジウス
- シャドウ
- その他のViewStyleプロパティ
- 注意点:
backgroundComponent
プロパティと併用する場合、backgroundStyle
は無視される可能性あり。
- 透明な背景の作成:
完全に透明な背景を作成するには、以下のように設定:jsxbackgroundStyle={{ backgroundColor: 'transparent' }}
- 組み合わせ:
handleStyle
やhandleIndicatorStyle
などの他のスタイルプロパティと組み合わせて使用することで、BottomSheetの全体的な外観をカスタマイズ可能。 - 動的なスタイリング:
状態に応じてbackgroundStyle
を動的に変更することも可能。
backgroundStyle
を適切に使用することで、アプリケーションのデザインに合わせてBottomSheetの外観をカスタマイズし、より統一感のあるUIを作成することが可能。
handleStyle:ハンドルのスタイル
- 目的:
BottomSheetの上部にあるハンドル(通常は小さな横線)のスタイルを変更するために使用。 - 型:
ViewStyle
型(React NativeのStyleSheet.ViewStyle
)を受け取る。 - カスタマイズ可能な要素:
- 背景色
- ボーダーラジウス
- 幅
- 高さ
- マージン
- その他のViewStyleプロパティ
- 注意点:
handleComponent
プロパティを使用してカスタムハンドルコンポーネントを提供する場合、handleStyle
は無視。
- 関連プロパティ:
handleIndicatorStyle
: ハンドル内のインジケーター(通常は小さな横線)のスタイルをカスタマイズ。
- 動的なスタイリング:
状態に応じてhandleStyle
を動的に変更することも可能。
handleStyle
を適切に使用することで、BottomSheetの外観をアプリケーションのデザインに合わせてカスタマイズし、より統一感のあるUIを作成することが可能。ハンドル部分は小さな要素ですが、ユーザーの注目を集めやすい部分であるため、適切にスタイリングすることでUXを向上させることが可能。
handleIndicatorStyle:ハンドルインディケーターのスタイル
handleHeight:ハンドルの高さ
containerHeight:コンテナの高さ
contentHeight:コンテンツの高さ
containerOffset:位置情報を保持
containerOffset
は、BottomSheetコンテナの位置情報を保持するために使用されます。具体的には、画面上でのBottomSheetの上端、左端、右端、下端の位置を表します。
topInset:コンテナの上部に追加する余白
- 目的:
BottomSheetコンテナの上部に追加する余白(インセット)を指定します。 - 型:
数値型(number)を受け取ります。 - デフォルト値:
0 - 使用例:jsx
<BottomSheet topInset={50} ... > {/* コンテンツ */} </BottomSheet>
- 主な用途:
- ナビゲーションバーやステータスバーの高さを考慮してBottomSheetの位置を調整する。
@react-navigation/stack
のuseHeaderHeight
フックやreact-native-safe-area-context
のuseSafeArea
フックから得られる値をここに設定することが多い。
- 効果:
- BottomSheetの上端が指定された値だけ下がります。
- パーセンテージベースのスナップポイントの計算に影響を与えます。
- 注意点:
- この値を設定すると、BottomSheetの実際の表示可能領域が減少します。
- デバイスの種類やアプリのレイアウトによって適切な値が変わる可能性があります。
topInset
を適切に使用することで、ナビゲーションバーやステータスバーとBottomSheetが重ならないようにし、より良いユーザーエクスペリエンスを提供することができます。特に、異なるデバイスや画面サイズに対応する際に重要なプロパティとなります。
bottomInset
- 目的:
BottomSheetコンテナの下部に追加する余白(インセット)を指定します。 - 型:
数値型(number)を受け取ります。 - デフォルト値:
0 - 使用例:jsx
<BottomSheet bottomInset={34} ... > {/* コンテンツ */} </BottomSheet>
- 主な用途:
- ホームインジケーターやナビゲーションバーの高さを考慮してBottomSheetの位置を調整する。
react-native-safe-area-context
のuseSafeArea
フックから得られるbottom
の値をここに設定することが多い。
- 効果:
- BottomSheetの下端が指定された値だけ上がります。
- これにより、BottomSheetがホームインジケーターやナビゲーションバーと重ならないようにできます。
- 注意点:
- この値を設定すると、BottomSheetの実際の表示可能領域が減少します。
- デバイスの種類やアプリのレイアウトによって適切な値が変わる可能性があります。
- topInsetとの違い:
topInset
がBottomSheetの上部の余白を制御するのに対し、bottomInset
は下部の余白を制御します。
bottomInset
を適切に使用することで、BottomSheetがデバイスの物理的な特徴(ホームインジケーターなど)と干渉しないようにし、より良いユーザーエクスペリエンスを提供することができます。特に、異なるデバイスや画面サイズに対応する際に重要なプロパティとなります。
maxDynamicContentSize
- 目的:
動的なコンテンツサイズの最大高さを制限し、BottomSheetの高さが指定されたサイズを超えないようにします。 - 型:
数値型(number)を受け取ります。 - デフォルト値:
コンテナの高さ(container height) - 動作:
enableDynamicSizing
がtrue
の場合に効果を発揮します。- コンテンツの高さが
maxDynamicContentSize
を超えた場合、BottomSheetの高さはこの値に制限されます。
- 主な用途:
- 動的なコンテンツを持つBottomSheetで、最大高さを制御したい場合に使用します。
- ユーザーエクスペリエンスを考慮して、BottomSheetが画面全体を覆わないようにする場合に有用です。
- 注意点:
- この値は
enableDynamicSizing
がtrue
の場合にのみ効果があります。 - コンテナの高さよりも大きな値を設定しても、実際のBottomSheetの高さはコンテナの高さを超えることはありません。
- この値は
- 関連プロパティ:
enableDynamicSizing
: 動的サイジングを有効にするプロパティsnapPoints
: 固定のスナップポイントを設定するプロパティ
maxDynamicContentSize
を適切に使用することで、動的なコンテンツを持つBottomSheetの最大高さを制御し、より良いユーザーエクスペリエンスを提供することができます。特に、コンテンツの量が予測できない場合や、BottomSheetが画面全体を覆わないようにしたい場合に有用です。
keyboardBehavior
- 目的:
キーボードが表示されたときのBottomSheetの挙動を定義します。 - 型:
文字列型で、以下の値のいずれかを取ります:- ‘interactive’(デフォルト)
- ‘extend’
- ‘fillParent’
- オプションの説明:
- ‘interactive’: BottomSheetはキーボードの上に表示され、ユーザーはシートとキーボードの両方を操作できます。
- ‘extend’: キーボードが表示されると、BottomSheetは自動的に最大高さまで拡張されます。
- ‘fillParent’: キーボードが表示されると、BottomSheetは利用可能な画面スペース全体を埋めます。
- 注意点:
- このプロパティは、BottomSheet内でテキスト入力を使用する場合に特に重要です。
- ‘interactive’モードでは、BottomSheetTextInputコンポーネントを使用することが推奨されています。
- 関連プロパティ:
keyboardBlurBehavior
: キーボードが非表示になったときのBottomSheetの動作を制御します。android_keyboardInputMode
: Androidデバイスでのキーボード入力モードを指定します。
- プラットフォーム特有の動作:
- iOSとAndroidでは挙動が若干異なる場合があるため、両プラットフォームでのテストが推奨されます。
keyboardBehavior
を適切に設定することで、キーボードが表示されたときのユーザーエクスペリエンスを向上させることができます。特に、フォームやチャットインターフェースなど、テキスト入力を含むBottomSheetを実装する際に重要なプロパティです。
keyboardBlurBehavior
- 目的:
キーボードが非表示になったときのBottomSheetの挙動を定義します。 - 型:
文字列型で、以下の値のいずれかを取ります:- ‘none’(デフォルト)
- ‘restore’
- オプションの説明:
- ‘none’: キーボードが非表示になっても、BottomSheetの位置は変更されません。
- ‘restore’: キーボードが非表示になると、BottomSheetは元の位置(キーボードが表示される前の位置)に戻ります。
- 注意点:
- このプロパティは、
keyboardBehavior
プロパティと組み合わせて使用されることが多いです。 - ‘restore’オプションは、ユーザーがキーボードを閉じた後にBottomSheetの位置を元に戻したい場合に特に有用です。
- このプロパティは、
- 関連する問題:
- 一部のバージョンで’restore’オプションが正しく機能しない問題が報告されています3。
- これらの問題は最新バージョンで修正されている可能性が高いですが、使用する前に最新の情報を確認することをお勧めします。
- ユーザーエクスペリエンスへの影響:
- 適切に設定することで、キーボードの表示/非表示に伴うBottomSheetの動作をよりスムーズにし、ユーザーエクスペリエンスを向上させることができます。
keyboardBlurBehavior
を適切に設定することで、キーボードが非表示になったときのBottomSheetの動作を制御し、アプリケーションの要件に合わせたユーザーエクスペリエンスを提供することができます。特に、フォームやチャットインターフェースなど、テキスト入力を含むBottomSheetを実装する際に重要なプロパティです。
android_keyboardInputMode:アニメーション動作をカスタマイズ
animationConfigs
- BottomSheetの開閉やスナップ時のアニメーション挙動を細かく制御します。
- 型:
Animated.WithSpringConfig
またはAnimated.WithTimingConfig
型のオブジェクトを受け取ります。 - 主な設定可能なパラメータ:
duration
: アニメーションの持続時間(ミリ秒)easing
: イージング関数(例: Easing.inOut(Easing.ease))damping
: スプリングアニメーションの減衰係数mass
: スプリングアニメーションの質量stiffness
: スプリングアニメーションの剛性overshootClamping
: オーバーシュートを制限するかどうかrestDisplacementThreshold
: 静止状態とみなす変位のしきい値restSpeedThreshold
: 静止状態とみなす速度のしきい値
- デフォルト値:
ライブラリ内部で定義されたデフォルト設定が使用されます。 - 動的な変更:
アニメーション設定を動的に変更することも可能です。 - パフォーマンスへの影響:
適切に設定することで、スムーズなアニメーションを実現できますが、過度に複雑な設定はパフォーマンスに影響を与える可能性があります。 - プラットフォーム特有の考慮事項:
iOSとAndroidで最適な設定が異なる場合があるため、両プラットフォームでのテストが推奨されます。 - 注意点:
reduceMotion
オプションを使用して、デバイスの設定に応じてアニメーションを調整できます2。
animationConfigs
を適切に設定することで、BottomSheetの動きをよりスムーズにし、アプリケーションの要件に合わせたユーザーエクスペリエンスを提供することができます。ただし、過度に複雑な設定は避け、ユーザビリティとパフォーマンスのバランスを考慮することが重要です。
waitFor
-
waitFor
は、指定されたアニメーションやジェスチャーが完了するのを待ってから次の処理を実行するために使用されます。これにより、アニメーションの整合性を保ち、ユーザーエクスペリエンスを向上させることができます。
- 使用方法:
waitFor
は、通常、GestureHandler
と組み合わせて使用されます。例えば、パンジェスチャーが発生している間は他のジェスチャーを無効にすることができます。
- 注意点:
waitFor
は、他のアニメーションやジェスチャーとの相互作用を管理するために非常に便利ですが、適切に使用しないとユーザーインターフェースが遅延したり、反応が鈍く感じられることがあります。- 複雑なアニメーションやジェスチャーの組み合わせでは、十分なテストを行い、期待通りに動作することを確認する必要があります。
- 関連プロパティ:
withTiming
やwithSpring
などのアニメーション関数と組み合わせて使うことで、より滑らかなアニメーション体験を提供できます。
結論
waitFor
は、React Native Reanimatedでのアニメーションやジェスチャー管理において重要な役割を果たします。これを活用することで、複雑なインタラクションでも整合性のある動作を実現し、ユーザー体験を向上させることができます。
simultaneousHandlers
- 目的:
simultaneousHandlers
は、特定のジェスチャーハンドラーが他のハンドラーと同時にアクティブになることを可能にし、複雑なジェスチャー操作をサポートします。
- 型:
React.Ref
またはReact.Ref[]
(配列)を受け取ります。
- デフォルト動作:
- デフォルトでは、1つのジェスチャーハンドラーのみがアクティブ状態になれるため、他のハンドラーはキャンセルされます。
simultaneousHandlers
を使用することで、この動作を変更できます。
- デフォルトでは、1つのジェスチャーハンドラーのみがアクティブ状態になれるため、他のハンドラーはキャンセルされます。
- ユースケース:
- 画像のズームや回転、パン操作など、複数のジェスチャーを同時に認識する必要がある場合に特に有用です。
- 例えば、写真プレビューコンポーネントで、ピンチでズームしながら回転やパンを行う場合に使用されます。
- 注意点:
simultaneousHandlers
を設定することで、複数のハンドラーが同時にアクティブになれるようになりますが、これによって意図しない動作が発生する可能性もあるため、十分なテストが必要です。- 一部のシナリオでは、
simultaneousHandlers
が期待通りに機能しないことがあります。特に、他のハンドラーとの競合や状態管理に注意が必要です。
- 関連プロパティ:
waitFor
: 他のハンドラーの完了を待つために使用されるプロパティで、simultaneousHandlers
と組み合わせて使用されることがあります。
simultaneousHandlers
を適切に使用することで、ユーザーインターフェースでの複雑なジェスチャー操作をよりスムーズに実装できるようになります。特に、インタラクティブなコンポーネントやアプリケーションで重要な役割を果たします。
activeOffsetX
- 目的:
activeOffsetX
は、横方向のスワイプが認識されるために必要な最小のオフセット(移動量)を指定します。これにより、ユーザーが意図しないスワイプ操作を防ぎ、より直感的な操作感を提供します。 - 型:
数値型(number)を受け取ります。これが示すのは、スワイプが有効になるための最小移動量です。 - 設定方法:
- 配列として設定することも可能で、例えば
[-10, 10]
と設定すると、左方向に10ピクセル以上移動した場合、または右方向に10ピクセル以上移動した場合にスワイプが有効になります。
- 配列として設定することも可能で、例えば
- 主な用途:
- スワイプダウンでBottomSheetを閉じる機能を持たせつつ、左右へのスワイプ操作を許可する場合に便利です。
- 他のジェスチャーとの競合を避けるためにも使用されます。
- 注意点:
activeOffsetX
を適切に設定しないと、意図しない動作やユーザーエクスペリエンスの低下につながる可能性があります。- 特に複数のジェスチャーハンドラーが存在する場合は、他のハンドラーとの相互作用を考慮する必要があります。
- 関連プロパティ:
failOffsetX
: スワイプが失敗するためのオフセット値を指定します。activeOffsetY
: 縦方向のオフセットを制御します。
activeOffsetX
を適切に設定することで、BottomSheetの操作性やユーザーインターフェースの直感性を向上させることができます。特に、複雑なインタラクションやジェスチャー操作が必要なアプリケーションで重要な役割を果たします。
activeOffsetY
failOffsetX
failOffsetY
gestureEventsHandlersHook
- 目的:
gestureEventsHandlersHook
は、BottomSheetのパンジェスチャーに対するイベントハンドリングをカスタマイズするための手段を提供します。これにより、特定の動作(例:ハプティックフィードバック)やアニメーションのトリガーなどを実装できます。
- 型:
GestureEventsHandlersHookType
を受け取ります。デフォルトではuseGestureEventsHandlersDefault
が使用されます。
- ユースケース:
- ユーザーがBottomSheetをドラッグしたときにハプティックフィードバックを提供したり、特定の条件下でアニメーションをトリガーしたりする場合に役立ちます。
- 注意点:
- 現在、この機能は実験的であり、フックのシグネチャはメジャーバージョンアップなしに変更される可能性があります。そのため、使用する際には最新のドキュメントを確認し、将来的な変更に備える必要があります。
- 関連プロパティ:
- 他のジェスチャー関連プロパティ(例:
simultaneousHandlers
,waitFor
など)と組み合わせて使用することで、複雑なジェスチャー操作を実現できます。
- 他のジェスチャー関連プロパティ(例:
結論
gestureEventsHandlersHook
は、@gorhom/bottom-sheetライブラリでのパンジェスチャー処理をカスタマイズするための強力なツールです。これを活用することで、ユーザーエクスペリエンスを向上させるための柔軟なインタラクション設計が可能になります。ただし、実験的な機能であるため、将来的な変更に注意が必要です。
animatedIndex
animatedPosition
onChange
onAnimate
handleComponent:カスタムハンドル
backdropComponent:ボトムシートの背面に表示されるUI
MapViewとかも設定できるけどBottomSheetのジェスチャーと競合可能性あり
backgroundComponent:ボトムシートの背景部分(シート自体の外観)
ボトムシートの背景色、デザイン、角丸のスタイルなどを自由に変更可能
例: デフォルトの背景:
- 白い角丸矩形。
backgroundColor
やスタイルを直接変更する場合には制限がある。
カスタマイズできる内容:
- 背景色
- ボーダーやシャドウ
- グラデーション
- 背景画像の適用
footerComponent:BottomSheetのカスタムフッター
children
1 2 3 |
<BottomSheet> {/* childrenとして渡される部分 */} </BottomSheet> |
v4の注意事項
最近はV5になっているけどV4のころから使っているのでV4についてまとめておく
廃止されたProp
- initialSnapIndex:V3から廃止
- onClose:onChangeで代替
- enableContentPanningGesture:自動的に最適化され、個別に有効化する必要なし
- enableHandlePanningGesture:自動的に最適化され、個別に有効化する必要なし
V5でしか使えない
- onAnimate:Bottom Sheetのアニメーションの進行中にコールバックを受け取るためのプロパティ
用途: スクロールやアニメーションの状態を取得して、UIを動的に変更する場合 - containerStyle:Bottom Sheet全体の外部コンテナにスタイルを適用できるプロパティ
- scrollBehavior:Bottom Sheetがスクロール可能な場合の挙動を指定するプロパティ
- enableOverDrag:Bottom Sheetのスナップポイントを超えてドラッグできるかどうかを制御
- animationEasing:アニメーションの動きを制御
- animationDuration:アニメーションの長さをミリ秒単位で指定アニメーションの長さをミリ秒単位で指定
- ベース:Reanimated v3
サンプル色々
縦スクロールと横スクロールの併用
中間スナップポイントでも縦スクロールと横スクロールを正しく動作させる例
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
import React from 'react'; import { View, Text, StyleSheet, ScrollView } from 'react-native'; import BottomSheet, { BottomSheetScrollView } from '@gorhom/bottom-sheet'; const App = () => { const snapPoints = ['25%', '60%', '90%']; return ( <BottomSheet index={1} snapPoints={snapPoints}> {/* 縦スクロールビュー */} <BottomSheetScrollView contentContainerStyle={styles.scrollViewContent}> <Text style={styles.text}>Vertical Content</Text> {/* 横スクロールビュー */} <ScrollView horizontal style={styles.horizontalScrollView} contentContainerStyle={styles.horizontalContent} > {Array(10) .fill(0) .map((_, index) => ( <View key={index} style={styles.button}> <Text style={styles.buttonText}>Button {index + 1}</Text> </View> ))} </ScrollView> </BottomSheetScrollView> </BottomSheet> ); }; const styles = StyleSheet.create({ scrollViewContent: { padding: 20, }, text: { fontSize: 16, marginBottom: 20, }, horizontalScrollView: { marginVertical: 10, }, horizontalContent: { flexDirection: 'row', alignItems: 'center', }, button: { backgroundColor: '#007AFF', padding: 10, marginHorizontal: 5, borderRadius: 5, }, buttonText: { color: 'white', fontSize: 14, }, }); export default App; |
トラブルシューティング
中間ポイントでスクロールできない
未検証だが調査したものをメモとして
- nestedScrollEnabled={true}
- スクロールがぎこちない場合: keyboardShouldPersistTaps=”handled”
- BottomSheetScrollView を使用し、スクロール可能なコンテンツをラップ
- react-native-gesture-handler の waitFor や simultaneousHandlers を設定してスクロールの競合を防止
- keyboardShouldPersistTaps や scrollEnabled を調整
- HorizontalScrollView や FlatListに horizontal={true} を明示的に設定
コメント