元のリンク
序文
Flutterを学ぶと、公式Webサイトで最初の例が間違いなく表示されます:中国語 または 英語。しかし、初心者として、あなたはそれを読むのに苦労しているかもしれません。この記事の目的は、この例をよりよく理解するのを助けることです。
最終的なレンダリング:
まず、上の図の効果を実現する方法を分析しましょう。
Android開発者
1.データの準備:リストデータと選択したデータは、それぞれ2つのリストまたは配列に保存できます。2.インターフェイスリスト:ListViewまたはRecyclerViewを使用します。3。インターフェイスジャンプ:インテントを使用して、データを新しいリストページに移動できます。 |
iOS開発者
1.データの準備:リストデータと選択したデータは、それぞれ2つの配列に保存できます。2.インターフェイスリスト:TableViewまたはCollectionViewを使用します3.インターフェイスジャンプ:NavigationControllerを使用し、新しいページオブジェクトに値を直接割り当てることができます |
結論として
ネイティブのAndroid開発であろうとiOS開発であろうと、実行する必要のある手順は次のとおりです。
- 表示するデータを保存し、選択したデータを保存します
- リストを表示し、データを表示します
- 新しいページにジャンプするように設定
したがって、Flutter開発では、次の手順に従って理解を深めてください
フラッターの開発
*データの準備:リストデータは配列に保存され、選択したデータはセットに保存できます(セットは重複を自動的に削除できるため)。*インターフェイスリスト:ListViewを使用します*インターフェイスジャンプ:ナビゲーターを使用できます |
公式コードを逆アセンブルして分析し、すぐに理解できるようにします
公式ウェブサイトでは、約110行のコードを使用して上記の例を実装しています。学習に役立つように、これらのコードを3つの主要部分に分解しました。
前提条件:最初にAndroid Studioまたはその他の開発ツールを使用してFlutterプロジェクトを作成する必要があります。この手順について学習する必要がある場合は、 ここですばやく学習できます。
まったく新しいFlutterプロジェクトを作成して実行すると、おなじみの「Helloworld」がインターフェースに表示されます。Flutterのコードをより簡単に理解するために、最初に最初の作成コードを分析して、少なくともどこから始めればよいかを知ってみましょう。
ここで編集したいのはmain.dart ファイルです 。他の言語と同様に、Flutterの入力関数が主な関数です。
import 'package:flutter/material.dart';
void main() => runApp(new MyApp()); //分析 1
class MyApp extends StatelessWidget { //分析 2 (StatelessWidget)
@override
Widget build(BuildContext context) { //分析 3
return new MaterialApp(
title: 'Welcome to Flutter',
home: new Scaffold( //分析 4
appBar: new AppBar(
title: new Text('Welcome to Flutter'),
),
body: new Center( //分析 5
child: new Text('Hello World'),
),
),
);
}
}
分析
- ここで => は、Dartの1行関数の省略形であり、次と同等です。
void main() {
runApp(new MyApp());
}
-
StatelessWidgetは、StatefulWidgetに対応する状態が1つしかないコンポーネントを表します(つまり、複数の状態が存在する可能性があります)。ここで原理を掘り下げる必要はありません。これはフラッターのリフレッシュなどに関連していることを知っておいてください。
-
ウィジェットコンポーネントでは、buildメソッドを使用してその内部構造を記述します。ここでのビルドは、MaterialAppのシステムコンポーネントがMyAppの構築に使用されることを意味します。
-
ホームタグの値:Scaffoldは、マテリアルライブラリで提供されるコンポーネントであり、ホーム画面を含むウィジェットツリーのナビゲーションバー、タイトル、およびbody属性を設定できます。ここで、AppBarとテキストがページに追加されていることがわかります。
-
センターは、サブコンポーネントを中央に配置できるコンポーネントです。
改造を開始します
私たちの目標は、ページにhello_worldを表示しているTextViewをListViewに置き換えることです。上記の分析から、上記のポイント4のホームタグの値をListViewに置き換えると、ページに表示されるコンテンツが変更される可能性があることがわかります。ただし、その前に、表示するデータを準備する必要があります。これは 、表示される単語データの生成に役立つ、english_wordsという3つのパッケージです。まず、依存パッケージを追加する方法を学びます。
- pubspec.yamlファイルを開いて、サードパーティのライブラリを追加します。
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.0
english_words: ^3.1.0
- [パッケージの取得]をクリック し て、追加したパッケージを取得します。
english_wordsライブラリを追加した後、このライブラリを使用して次のようなデータを作成できます。
//创造5个随机词组,并返回词组的迭代器
generateWordPairs().take(5)
StatefulWidgetの使い方を学ぶ
ListViewのソースコードを見ると、最終的にはStatelessWidgetから継承されているため、状態は一意であることがわかります。ただし、実装するListViewのデータは動的に変化するため、StatefulWidgetを使用してListViewのデータを動的に変更する必要があります。
StatefulWidgetコンポーネントを使用するには、さまざまな状況での表示状態を自分で制御する必要があるため、Stateクラスを実装して、さまざまな状況での表示方法をStatefulWidgetクラスに指示する必要があります。 |
表示されるListViewを表す、動的に変化するコンポーネントクラスを作成します。
class RandomWords extends StatefulWidget {
@override
State<StatefulWidget> createState() { //分析1
return new RandomWordsState();
}
}
分析:
- Stateクラスを作成するメソッドは、ここではシステムのStateを継承して、RandomWordsStateという名前のクラスを作成し、ListViewの各状態での表示を制御します。
class RandomWordsState extends State<RandomWords> {
}
-
复制代码
表示データを完成させてクリックデータを保存するには、arrayとsetを使用してそれぞれ保存します(setは重複排除できるため、setを使用してクリックデータを保存します。他の保存方法を選択することもできます)
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[]; //分析 1
final _saved = new Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0); //分析 2
}
分析:
- 民営化を示すためにダートに_を追加
- フォントサイズの定数
データセットを作成し、ListViewを構築します
次の2つのメソッドをRandomWordsStateクラスに追加して、データセットの作成とListViewの構築を表します。
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
// 对于每个建议的单词对都会调用一次itemBuilder,然后将单词对添加到ListTile行中
// 在偶数行,该函数会为单词对添加一个ListTile row.
// 在奇数行,该函数会添加一个分割线widget,来分隔相邻的词对。
// 注意,在小屏幕上,分割线看起来可能比较吃力。
itemBuilder: (context, i) {
// 在每一列之前,添加一个1像素高的分隔线widget
if (i.isOdd) return new Divider();
// 语法 "i ~/ 2" 表示i除以2,但返回值是整形(向下取整),比如i为:1, 2, 3, 4, 5
// 时,结果为0, 1, 1, 2, 2, 这可以计算出ListView中减去分隔线后的实际单词对数量
final index = i ~/ 2;
// 如果是建议列表中最后一个单词对
if (index >= _suggestions.length) {
// ...接着再生成10个单词对,然后添加到建议列表
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
コードには詳細なコメントがありますが、理解を容易にするために、ここに簡単な説明があります。
- _buildSuggestionsメソッドはListViewを返すことです
- _buildRowメソッドは、表示方法をListView(ListTile)に行を返すことです。
_buildSuggestionsメソッドの場合:
- コード内のitemBuilderは、行の構成(ListTile)を表示する方法であり、その戻り値は_buildRowメソッドです。
_suggestions.addAll(generateWordPairs().take(10));
毎回ディスプレイ配列に10個のデータを追加することです
_buildRowメソッドの場合:
- 行を設定する(ListTileはiOSおよびAndroidではセルと呼ばれるコンテンツの行を表します)表示方法
- ListTileは、タイトル、末尾(右側のアイコン)を設定し、イベントonTap()をクリックします。
- 保存されているかどうかに応じて、右側に表示するアイコンを決定します
- クリックすると、クリックされていないコンテンツが_savedコンテナに保存されます。
ジャンプロジックを追加する
_pushSavedメソッドを追加して、新しいページにジャンプし、選択したデータを表示する方法を示します。
main.dart
void _pushSaved() {
Navigator.of(context).push( // 分析 1
new MaterialPageRoute( // 分析 2
builder: (context) {
final tiles = _saved.map( //数据
(pair) {
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return new Scaffold( // 分析 3
appBar: new AppBar(
title: new Text('Saved Suggestions'),
),
body: new ListView(children: divided),
);
},
),
);
}
分析:1。Navigator.of(context).pushを使用してジャンプを処理します。必要なパラメーターはルートです。2。ページを作成します。ルート3。新しいページに戻ると、内部の本文のコンテンツはListViewであり、データが表示されます。 _savedで読む
最終的に、すべてのコード統合は次のようになります。
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Welcome to Flutter',
theme: new ThemeData(
primaryColor: Colors.red,
),
home: RandomWords(),
);
}
}
class RandomWords extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new RandomWordsState();
}
}
class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = new Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0);
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Startup Name Generator'),
actions: <Widget>[
new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved),
],
),
body: _buildSuggestions(),
);
}
void _pushSaved() {
Navigator.of(context).push(
new MaterialPageRoute(
builder: (context) {
final tiles = _saved.map(
(pair) {
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();
return new Scaffold(
appBar: new AppBar(
title: new Text('Saved Suggestions'),
),
body: new ListView(children: divided),
);
},
),
);
}
Widget _buildSuggestions() {
return new ListView.builder(
padding: const EdgeInsets.all(16.0),
itemBuilder: (context, i) {
if (i.isOdd) return new Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
});
}
Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return new ListTile(
title: new Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: new Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
);
}
}
それを実行すると、最高の効果を見ることができます。