Flutter アプリにインタラクティブ性を追加する
ユーザー入力に反応するようにアプリを変更するにはどうすればよいでしょうか? このチュートリアルでは、アプリにインタラクティブ性を追加します。 非インタラクティブなウィジェットのみが含まれます。 具体的には、アイコンを変更してタップできるようにします 2 つのウィジェットを管理するカスタム ステートフル ウィジェットを作成することで、 ステートレスなウィジェット。
の建物のレイアウトのチュートリアル作成方法を示しました 次のスクリーンショットのレイアウト。
アプリを初めて起動すると、星が赤く点灯します。 この湖が以前にお気に入りだったことを示しています。 星の横の数字は 41 であることを示します 人々はこの湖をお気に入りにしています。このチュートリアルを完了すると、 星をタップすると、お気に入りのステータスが削除されます。 実線の星を輪郭に置き換えて、 カウントを減らします。もう一度タップすると湖がお気に入りになり、 実線の星を描いてカウントを増やします。
これを実現するには、単一のカスタム ウィジェットを作成します これにはスターとカウントの両方が含まれます。 それ自体がウィジェットです。星をタップすると状態が変わります 両方のウィジェットに対応しているため、同じウィジェットで両方を管理する必要があります。
すぐにコードに触れることができますステップ 2: StatefulWidget をサブクラス化する。 状態を管理するさまざまな方法を試したい場合は、 にスキップ状態の管理。
ステートフル ウィジェットとステートレス ウィジェット
ウィジェットはステートフルまたはステートレスのいずれかです。ウィジェットができるなら 変化 - ユーザーが操作すると、 たとえば、ステートフルです。
あステートレスウィジェットは決して変更されません。Icon
、IconButton
、 とText
それは
ステートレス ウィジェットの例。ステートレスなウィジェット
サブクラスStatelessWidget
。
あステートフルウィジェットは動的です: たとえば、
イベントに応じて外観を変えることができます
ユーザーの操作またはデータの受信によってトリガーされます。Checkbox
、Radio
、Slider
、InkWell
、Form
、 とTextField
はステートフル ウィジェットの例です。ステートフルなウィジェット
サブクラスStatefulWidget
。
ウィジェットの状態は次の場所に保存されます。State
物体、
ウィジェットの状態を外観から分離します。
状態は、次のように変化する可能性のある値で構成されます。
スライダーの現在値、またはチェックボックスがチェックされているかどうか。
ウィジェットの状態が変化すると、
状態オブジェクトが呼び出すsetState()
、
フレームワークにウィジェットを再描画するように指示します。
ステートフル ウィジェットの作成
このセクションでは、カスタム ステートフル ウィジェットを作成します。
2 つのステートレス ウィジェット (赤色の実線) を置き換えます。
星とその隣の数値 - 単一の
2 つの行を管理するカスタム ステートフル ウィジェット
子ウィジェット:IconButton
とText
。
カスタム ステートフル ウィジェットを実装するには、次の 2 つのクラスを作成する必要があります。
- のサブクラス
StatefulWidget
ウィジェットを定義します。 - のサブクラス
State
その状態が含まれています ウィジェットを作成し、ウィジェットの定義を行いますbuild()
方法。
このセクションでは、ステートフル ウィジェットを構築する方法を説明します。
呼ばれたFavoriteWidget
、湖アプリの場合。
セットアップ後の最初のステップは、状態を選択することです
のために管理されたFavoriteWidget
。
ステップ 0: 準備をする
すでにアプリを構築している場合は、建物レイアウトのチュートリアル (ステップ 6)、 次のセクションに進んでください。
- 確認してください設定あなたの環境。
- 新しい Flutter アプリを作成する。
- 交換してください
lib/main.dart
ファイルmain.dart
。 - 交換してください
pubspec.yaml
ファイルpubspec.yaml
。 - を作成します
images
プロジェクト内のディレクトリを追加し、lake.jpg
。
デバイスを接続して有効にしたら、 または、iOSシミュレータ(Flutter インストールの一部) またはAndroidエミュレータ(Android Studio の一部 インストールしてください)、準備完了です。
ステップ 1: ウィジェットの状態を管理するオブジェクトを決定する
ウィジェットの状態はいくつかの方法で管理できます。
しかし、この例ではウィジェット自体が、FavoriteWidget
、独自の状態を管理します。
この例では、星の切り替えは孤立したものです。
親ウィジェットや残りのウィジェットに影響を与えないアクション
これにより、ウィジェットはその状態を内部で処理できるようになります。
ウィジェットと状態の分離について詳しくは、 そして状態はどのように管理されるのか状態の管理。
ステップ 2: StatefulWidget をサブクラス化する
のFavoriteWidget
クラスは自身の状態を管理し、
それでオーバーライドされますcreateState()
を作成するState
物体。フレームワークが呼び出すのは、createState()
ウィジェットを構築したいとき。
この例では、createState()
を返します
のインスタンス_FavoriteWidgetState
、
これは次のステップで実装します。
class FavoriteWidget extends StatefulWidget {
const FavoriteWidget({super.key});
@override
State<FavoriteWidget> createState() => _FavoriteWidgetState();
}
ステップ 3: サブクラスの状態
の_FavoriteWidgetState
クラスは可変データを格納します
これはウィジェットの存続期間中に変更される可能性があります。
アプリを最初に起動すると、UI に固体が表示されます。
赤い星は湖が「お気に入り」のステータスであることを示します。
41のいいねとともに。これらの値は、_isFavorited
と_favoriteCount
田畑:
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 41;
// ···
}
このクラスはまた、build()
方法、
これにより、赤色を含む行が作成されます。IconButton
、
とText
。あなたが使うIconButton
(それ以外のIcon
)
があるからですonPressed
を定義するプロパティ
コールバック関数 (_toggleFavorite
) タップの処理に使用します。
次にコールバック関数を定義します。
class _FavoriteWidgetState extends State<FavoriteWidget> {
// ···
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(0),
child: IconButton(
padding: const EdgeInsets.all(0),
alignment: Alignment.centerRight,
icon: (_isFavorited
? const Icon(Icons.star)
: const Icon(Icons.star_border)),
color: Colors.red[500],
onPressed: _toggleFavorite,
),
),
SizedBox(
width: 18,
child: SizedBox(
child: Text('$_favoriteCount'),
),
),
],
);
}
}
の_toggleFavorite()
メソッド。IconButton
を押す、電話をかけるsetState()
。
電話をかけるsetState()
これは重要です。
ウィジェットの状態が次の状態であることをフレームワークに伝えます。
変更されたため、ウィジェットを再描画する必要があります。
関数の引数は、setState()
を切り替えます
これら 2 つの状態間の UI:
- あ
star
アイコンと数字の「41」 - あ
star_border
アイコンと数字の 40
void _toggleFavorite() {
setState(() {
if (_isFavorited) {
_favoriteCount -= 1;
_isFavorited = false;
} else {
_favoriteCount += 1;
_isFavorited = true;
}
});
}
ステップ 4: ステートフル ウィジェットをウィジェット ツリーにプラグインする
カスタム ステートフル ウィジェットをウィジェット ツリーに追加します。
アプリのbuild()
方法。まず、次のコードを見つけます。
を作成しますIcon
とText
を削除してください。
同じ場所にステートフル ウィジェットを作成します。
@@ -10,2 +5,2 @@
|
|
10
5
|
class MyApp extends StatelessWidget {
|
11
6
|
const MyApp({super.key});
|
@@ -40,11 +35,7 @@
|
|
40
35
|
]、
|
41
36
|
)、
|
42
37
|
)、
|
43
|
-
|
44
|
-
アイコン.スター、
|
45
|
-
色: Colors.red[500]、
|
46
|
-
)、
|
47
|
-
const テキスト('41')、
|
38
|
+
const お気に入りウィジェット()、
|
48
39
|
]、
|
49
40
|
)、
|
50
41
|
);
|
それでおしまい!アプリをホットリロードすると、 星のアイコンがタップに反応するようになりました。
問題がありますか?
コードを実行できない場合は、 考えられるエラーについては IDE を参照してください。Flutter アプリのデバッグ役立つかもしれません。 それでも問題が見つからない場合は、 GitHub のインタラクティブな Lake サンプルとコードを比較して確認してください。
lib/main.dart
pubspec.yaml
lakes.jpg
ご不明な点がございましたら、開発者にお問い合わせください。コミュニティチャンネル。
このページの残りの部分では、ウィジェットの状態を変化させるいくつかの方法について説明します。 管理対象となり、他の利用可能なインタラクティブ ウィジェットをリストします。
状態の管理
ステートフル ウィジェットの状態は誰が管理するのでしょうか?ウィジェット自体? 親ウィジェット?両方?別の物体? 答えは…それは状況によります。いくつかの有効な方法があります ウィジェットをインタラクティブにします。ウィジェットデザイナーであるあなたは、 ウィジェットがどのように使用されると予想されるかに基づいて決定してください。 状態を管理する最も一般的な方法は次のとおりです。
どのアプローチを使用するかをどのように決定しますか? 次の原則は決定に役立ちます。
-
問題の状態がユーザーデータの場合、 たとえば、チェックが入っているかどうかなど チェックボックスのモード、またはスライダーの位置、 その場合、状態は親ウィジェットによって最もよく管理されます。
-
問題の状態が美的である場合、 たとえばアニメーションの場合、 状態はウィジェット自体によって最もよく管理されます。
疑問がある場合は、親ウィジェットで状態を管理することから始めてください。
状態を管理するさまざまな方法の例を示します
3 つの簡単な例を作成して、TapboxA、TapboxB、
そしてタップボックスC。これらの例はすべて同様に機能します。
タップすると、
緑または灰色のボックス。の_active
ブール値が決定します
色: アクティブの場合は緑色、非アクティブの場合は灰色。
これらの例では、GestureDetector
アクティビティをキャプチャする
でContainer
。
ウィジェットは独自の状態を管理します
場合によっては、ウィジェットにとって最も意味のあることもあります
内部で状態を管理します。例えば、ListView
自動的にスクロールします
コンテンツがレンダー ボックスを超えています。ほとんどの開発者
を使用してListView
管理したくないListView
の
スクロール動作なので、ListView
それ自体がスクロール オフセットを管理します。
の_TapboxAState
クラス:
- の状態を管理します
TapboxA
。 - を定義します
_active
を決定するブール値 ボックスの現在の色。 - を定義します
_handleTap()
更新する関数_active
ボックスがタップされて、setState()
UIを更新する機能。 - ウィジェットのすべてのインタラクティブな動作を実装します。
import 'package:flutter/material.dart';
// TapboxA manages its own state.
//------------------------- TapboxA ----------------------------------
class TapboxA extends StatefulWidget {
const TapboxA({super.key});
@override
State<TapboxA> createState() => _TapboxAState();
}
class _TapboxAState extends State<TapboxA> {
bool _active = false;
void _handleTap() {
setState(() {
_active = !_active;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: _active ? Colors.lightGreen[700] : Colors.grey[600],
),
child: Center(
child: Text(
_active ? 'Active' : 'Inactive',
style: const TextStyle(fontSize: 32, color: Colors.white),
),
),
),
);
}
}
//------------------------- MyApp ----------------------------------
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: const Center(
child: TapboxA(),
),
),
);
}
}
親ウィジェットはウィジェットの状態を管理します
多くの場合、親ウィジェットにとってはこれが最も合理的です
状態を管理し、その子ウィジェットにいつ更新するかを指示します。
例えば、IconButton
治療できるようにします
タップ可能なボタンとしてのアイコン。IconButton
です
ステートレス ウィジェットは親であると判断したため、
ウィジェットはボタンがタップされたかどうかを知る必要があります。
適切なアクションを実行できるようになります。
次の例では、TapboxB はその状態をエクスポートします コールバックを通じてその親に送信されます。なぜならタップボックスB 状態は管理せず、StatelessWidget をサブクラス化します。
ParentWidgetState クラス:
- を管理します
_active
TapboxB の状態。 - 器具
_handleTapboxChanged()
、 ボックスがタップされたときに呼び出されるメソッド。 - 状態が変化すると、呼び出します
setState()
UIを更新します。
TapboxB クラス:
- すべての状態がその親によって処理されるため、StatelessWidget を拡張します。
- タップを検知すると保護者に通知します。
import 'package:flutter/material.dart';
// ParentWidget manages the state for TapboxB.
//------------------------ ParentWidget --------------------------------
class ParentWidget extends StatefulWidget {
const ParentWidget({super.key});
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
bool _active = false;
void _handleTapboxChanged(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return SizedBox(
child: TapboxB(
active: _active,
onChanged: _handleTapboxChanged,
),
);
}
}
//------------------------- TapboxB ----------------------------------
class TapboxB extends StatelessWidget {
const TapboxB({
super.key,
this.active = false,
required this.onChanged,
});
final bool active;
final ValueChanged<bool> onChanged;
void _handleTap() {
onChanged(!active);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: active ? Colors.lightGreen[700] : Colors.grey[600],
),
child: Center(
child: Text(
active ? 'Active' : 'Inactive',
style: const TextStyle(fontSize: 32, color: Colors.white),
),
),
),
);
}
}
組み合わせて使用するアプローチ
一部のウィジェットでは、組み合わせて使用するアプローチにより、 一番センスがある。このシナリオでは、ステートフル ウィジェット 一部の状態と親ウィジェットを管理します 状態の他の側面を管理します。
の中にTapboxC
たとえば、タップダウンすると、
ボックスの周囲に濃い緑色の境界線が表示されます。タップアップすると、
境界線が消え、ボックスの色が変わります。TapboxC
それを輸出する_active
状態を親に渡しますが、その状態を管理します_highlight
内部の状態。この例には 2 つありますState
オブジェクト、_ParentWidgetState
と_TapboxCState
。
の_ParentWidgetState
物体:
- を管理します
_active
州。 - 器具
_handleTapboxChanged()
、 ボックスがタップされたときに呼び出されるメソッド。 - 電話
setState()
タップ時に UI を更新するには が発生し、_active
状態が変化します。
の_TapboxCState
物体:
- を管理します
_highlight
州。 - の
GestureDetector
すべてのタップイベントをリッスンします。 ユーザーがタップダウンすると、ハイライトが追加されます (濃い緑色の境界線として実装されます)。ユーザーが手を離すと、 タップすると、ハイライトが削除されます。 - 電話
setState()
タップダウンで UI を更新するには、 をタップするか、「キャンセル」をタップすると、_highlight
状態が変化します。 - タップ イベントで、その状態の変更を親ウィジェットに渡して取得します。
を使用した適切なアクション
widget
財産。
import 'package:flutter/material.dart';
//---------------------------- ParentWidget ----------------------------
class ParentWidget extends StatefulWidget {
const ParentWidget({super.key});
@override
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
bool _active = false;
void _handleTapboxChanged(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return SizedBox(
child: TapboxC(
active: _active,
onChanged: _handleTapboxChanged,
),
);
}
}
//----------------------------- TapboxC ------------------------------
class TapboxC extends StatefulWidget {
const TapboxC({
super.key,
this.active = false,
required this.onChanged,
});
final bool active;
final ValueChanged<bool> onChanged;
@override
State<TapboxC> createState() => _TapboxCState();
}
class _TapboxCState extends State<TapboxC> {
bool _highlight = false;
void _handleTapDown(TapDownDetails details) {
setState(() {
_highlight = true;
});
}
void _handleTapUp(TapUpDetails details) {
setState(() {
_highlight = false;
});
}
void _handleTapCancel() {
setState(() {
_highlight = false;
});
}
void _handleTap() {
widget.onChanged(!widget.active);
}
@override
Widget build(BuildContext context) {
// This example adds a green border on tap down.
// On tap up, the square changes to the opposite state.
return GestureDetector(
onTapDown: _handleTapDown, // Handle the tap events in the order that
onTapUp: _handleTapUp, // they occur: down, up, tap, cancel
onTap: _handleTap,
onTapCancel: _handleTapCancel,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: widget.active ? Colors.lightGreen[700] : Colors.grey[600],
border: _highlight
? Border.all(
color: Colors.teal[700]!,
width: 10,
)
: null,
),
child: Center(
child: Text(widget.active ? 'Active' : 'Inactive',
style: const TextStyle(fontSize: 32, color: Colors.white)),
),
),
);
}
}
代替実装ではハイライトがエクスポートされている可能性があります アクティブな状態を内部に保持しながら状態を親に送信し、 でも誰かにそのタップボックスを使うように頼んだら、 おそらく彼らは、あまり意味がないと不満を言うでしょう。 開発者は、ボックスがアクティブかどうかを気にします。 開発者はおそらくハイライトの仕方を気にしていないでしょう 管理されており、タップ ボックスがそれらを処理することを好みます。 詳細。
その他のインタラクティブなウィジェット
Flutter は、さまざまなボタンや同様のインタラクティブなウィジェットを提供します。 これらのウィジェットのほとんどは、マテリアル デザインのガイドライン、 独自の UI を持つ一連のコンポーネントを定義します。
必要に応じて、使用できますGestureDetector
構築する
カスタム ウィジェットへのインタラクティブ性。
例を見つけることができますGestureDetector
の状態の管理。詳細については、GestureDetector
のハンドルタップのレシピです。 flutterクックブック。
インタラクティブ性が必要な場合は、次のいずれかを使用するのが最も簡単です。 プレハブのウィジェット。以下にリストの一部を示します。
標準ウィジェット
Form
FormField
材料成分
Checkbox
DropdownButton
TextButton
FloatingActionButton
IconButton
Radio
ElevatedButton
Slider
Switch
TextField
資力
インタラクティブ機能を追加する場合は、次のリソースが役立つ可能性があります。 あなたのアプリに。
ジェスチャーのセクション flutterクックブック。
- ジェスチャーの処理のセクションウィジェットの紹介
- ボタンを作成して入力に応答する方法。
- Flutter のジェスチャー
- Flutter のジェスチャ メカニズムの説明。
- Flutter API ドキュメント
- すべての Flutter ライブラリのリファレンス ドキュメント。
- flutterギャラリー実行中のアプリ、リポジトリ
- 多くのマテリアル コンポーネントと その他の flutter機能。
- Flutterのレイヤードデザイン(ビデオ)
- このビデオには、州に関する情報が含まれています。 ステートレスなウィジェット。 Google エンジニアのイアン ヒクソン氏が発表します。