React Nativeの折りたたみセクションとアコーディオン
React Nativeの折りたたみとアコーディオンのガイド
React Nativeの折りたたみとアコーディオン(ライブラリ不要)| We.Inc
React NativeでLayoutAnimationを使ってセクションを開閉し、Animatedで矢印を回転させ、accessibilityStateのexpandedを伝える方法。アコーディオンのライブプレビュー付き。
React Nativeでセクションを折りたたむには、開閉フラグを状態に持ち、それがtrueの間だけ本文をレンダリングします。フラグを変更する前にLayoutAnimation.configureNextを呼び出すと、周囲のビューが新しい位置へスライドします。見出しのPressableにaccessibilityRole="button"とaccessibilityState={{ expanded }}を指定すれば、スクリーンリーダーが開いているかどうかを読み上げます。
折りたたみをアニメーションさせる2つの方法
- LayoutAnimation.configureNext
- すべてのビューの次のレイアウト変更
- 高さが不明な本文、セクションの一覧
- useNativeDriverを使ったAnimated.timing
- transformやopacityなどレイアウト以外のプロパティ
- 矢印の回転やフェード
- heightを使ったAnimated
- JSスレッド上での高さ
- 細かな制御が必要な固定高さのパネル
下のアコーディオンは、このページにあるReact NativeコードのWeb版です。状態の形も、各見出しのexpandedフラグも同じです。複数のセクションを開いたままにできる方式と、1つだけ開ける方式を切り替えて、画面に合うほうをコピーしてください。
- 状態には開いているセクションのidを保持します。1つだけ開ける方式では単一のidです。
- 見出しを押すと、プリセットを指定してLayoutAnimation.configureNextを呼び出し、その後で状態を更新します。
- 次のレイアウト処理で本文がマウントまたはアンマウントされ、隣接する要素がアニメーションしながら所定の位置に移動します。
- 回転はtransformなので、Animatedの値でネイティブドライバーを使って矢印を回転させます。
- 見出しのaccessibilityStateのexpandedで、どのセクションが開いているかを支援技術に伝えます。
- Androidでは、UIManager.setLayoutAnimationEnabledExperimental(true)が存在する場合に呼び出すようドキュメントで求められています。呼び出しは存在チェックで保護しましょう。
- 押せる範囲は矢印アイコンだけでなく、見出しの行全体にしましょう。
- 本文をアンマウントするほうが高さをアニメーションさせるよりシンプルで、非表示の内容がアクセシビリティツリーに残りません。
- useNativeDriverで高さをアニメーションさせないでください。React Nativeのドキュメントによると、ネイティブドライバーがアニメーションできるのはtransformやopacityなどレイアウト以外のプロパティだけです。
- 閉じている間も中の内容の状態を保持する必要があるなら、アンマウントせずにdisplay: "none"で非表示にしましょう。
よくある質問
React Nativeで折りたたみビューをアニメーションさせるには?
本文の表示・非表示を切り替える状態変更の直前に、LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)を呼び出します。easeInEaseOutプリセットは300ミリ秒かけて動きます。
AndroidでLayoutAnimationが何もしないのはなぜですか?
LayoutAnimationのページによると、AndroidではUIManager.setLayoutAnimationEnabledExperimental(true)が必要で、その関数が存在する場合にだけ呼び出します。最初のアニメーション付きの変更より前、アプリの起動時に一度実行しましょう。
Animatedとネイティブドライバーで高さをアニメーションできますか?
できません。React Nativeのドキュメントでは、ネイティブドライバーはtransformやopacityなどレイアウト以外のプロパティに限られているため、heightのようなレイアウトの値は対象外です。高さはネイティブドライバーなしでアニメーションさせるか、代わりにLayoutAnimationを使いましょう。
スクリーンリーダーはどうやってセクションが開いていると知るのですか?
見出しにaccessibilityState={{ expanded: isOpen }}、またはaria-expandedプロパティを設定します。ドキュメントでは、expandedは展開可能な要素が現在展開されているか折りたたまれているかを示すものと説明されています。
アコーディオンか、独立したセクションか
- アコーディオンは1つのセクションだけを開いておく方式で、読み手が1つの答えを求める設定画面や短いFAQに向いています。独立したセクションは、2つのパネルを開いて比べると便利なフィルターや注文の詳細に向いています。
- どちらも同じコンポーネントを使い、変わるのは切り替え関数だけです。独立したセクションではidのSetを保存し、アコーディオンでは単一のidを保存して、開いているものをもう一度押したらnullにします。
動きを滑らかに保つ
- LayoutAnimationが設定するのは直後のレイアウトだけなので、毎回、押したときのハンドラー内でsetStateの直前に呼び出してください。マウント時に一度呼び出しても、その後のタップには効果がありません。
- 本文が非常に長いと、ローエンドのスマートフォンではカクつくことがあります。セクション内の重い一覧は遅延読み込みにするか、短いプレビューと全画面へのリンクを表示しましょう。
折りたたみのコード
LayoutAnimationと回転する矢印を使った折りたたみセクション
本文は開いている間だけマウントされます。回転はtransformなので、矢印はネイティブドライバーで回ります。
アコーディオン:一度に開くのは1つだけ
状態には単一のidを持ちます。開いているセクションをもう一度押すとnullになり、閉じます。
注文はいつ発送されますか?
正午までのご注文は当日に発送します。荷物がスキャンされ次第、追跡リンクをメールでお送りします。
商品を返品できますか?
未使用の商品は30日以内であれば返品できます。注文画面から返品手続きを始め、ラベルを印刷してください。
住所を変更するには?
「アカウント」を開き、「住所」を選びます。変更はまだ発送されていない注文に適用されます。
アコーディオンのプレビュー
動作を示すための、架空のストアのヘルプ質問の例です。
1つだけ開く
複数開く
開き方
無料で始める · クレジットカード不要
関連: ガイド|Webマーケティングと集客を学ぶ
製品
ご利用いただける方
機能
リソース
会社情報
サイトマップを見る