Yura Luchaninovの報告の後、私はFlutterを自分で試すことにしました。 脳を伸ばすために、台所で男性と一緒に冷やしていることがありました。 物事はなくなっています。 私は見て、読み、書き始めました。 そして、すべてがうまくいくように見え、アプリケーションが起動され、それらが説明することは理解でき、すべてが簡単です。 しかし、「しかし」なしではありません-誰もが説明しているわけではありません。 プラットフォーム、YP、アプローチ、さらにはサブジェクトエリアも私にとって新しいものなので、この種の迷惑なのは、あなたが「開始しない」で、グーグルのことも知らないからです:Dart / Flutter / Window / Screen / Route / Widget?
もちろん、Dart、Flutter、およびそのウィジェットのすべてのドキュメントを読み直したくはありませんでした。時間があまりなかったので、Flutterを詳しく見てみたいだけでした。 Flutterで複雑すぎないアプリケーションを理解して作成するために、必要なものすべてを説明する小さなガイドがあればいいのですが、それはもうありません。
ガイドについて
このトピックに関する記事のほとんどはよく書かれており、複雑ではありません。 問題は、それらのほとんどが基本的な基礎とみなされる知識を必要とすることですが、基本について説明する他の記事では言及されていません。 この一連の記事では、この状況を修正したいと思います。 ゼロから始めましょう。前述のいずれも注意せずに残すことなく、1つまたは複数のアプリケーションを起動します。 このプロセスでは、すべての主要コンポーネントの使用方法、 独自のインターフェイスの作成方法、 ネイティブモジュールの操作方法 、そしてもちろん、 両方のプラットフォーム向けにアプリケーションをアセンブルする方法を学びます 。
Web開発者の観点から書きます。 あなたのほとんどはウェブスタックに精通している可能性が高く、おなじみのプラットフォームとのアナロジーは、家やその他の動物、犬、フー、バーなどの建築物とのアナロジーよりも優れています...
遅延しないように、簡単に概要を説明します。 そして、最も好奇心for盛な人のために、議論したトピックに関する有用なリンクを残します。
プラットフォームについて
Flutterは、 アプリケーションを立ち上げた大企業の注目を集めている、若くて非常に有望なプラットフォームです 。 このプラットフォームは、Webアプリケーションの開発に匹敵するシンプルさ、およびネイティブアプリケーションと同等の作業速度で興味深いものです。 いくつかの手法により、高いアプリケーションパフォーマンスと開発速度が実現します。
- 現在よく知られている多くのモバイルプラットフォームとは異なり、Flutter はJavaScriptをいかなる形式でも使用していません 。 Flutterのプログラミング言語として、Dartを選択しました。これはバイナリコードにコンパイルされ、Objective-C、Swift、Java、またはKotlinに匹敵する操作速度を実現します。
- Flutter は 、 ネイティブコンポーネントを使用しません 。これも、どのような形式でも、通信するためにレイヤーを作成する必要はありません。 代わりに、ゲームエンジンのように(そしてゲームには非常に動的なUIがあることを知っています)、インターフェイス全体を独自に描画します。 ボタン、テキスト、メディア要素、背景-これらはすべてFlutter自体のグラフィックエンジン内に描画されます。 上記の後、Flutterの「Hello World」アプリケーションが占有するスペースはごくわずかです:iOS≈2.5MbおよびAndroid≈4Mb。
- Flutter は、ウィジェット(コンポーネントと呼ばれるWebの世界)に基づくReactJS Webフレームワークに触発された宣言型アプローチを使用して 、UIを構築します。 インターフェイスの速度をさらに向上させるために、 ウィジェットは必要に応じて再描画されます - ウィジェットに何かが変更された場合のみ(フロントエンドの世界でVirtual DOMが行うように)。
- これに加えて、フレームワークには組み込みの Hot-reloadがあります。これはWebになじみがあり、ネイティブプラットフォームではまだ利用できませんでした。
これらの要因の実際的な利点については、アプリケーションをJavaからDartに書き直し、印象を共有したAndroid開発者による記事を読むことを強くお勧めします。 ここでは、彼が名前を付けたファイル/行の数(Javaで書かれた)-179/12176、および(Dartで書かれた)-1735年1月31日を取り出します。 ドキュメントでは、プラットフォームの技術的特徴の詳細な説明を見つけることができます。 動作するアプリケーションの他の例をご覧になりたい場合は、別のリンクをご覧ください。
Dartについて
Dartは、Flutterの下でアプリケーションを作成する必要があるプログラミング言語です。 これは非常に単純であり、JavaまたはJavaScriptの経験がある場合は、すぐに習得できます。
Flutterを学習するために必要な最低限のみを説明しようとして、Dartに関するレビュー記事を書きました。 しかし、この言語には非常に多くのニュアンスがあり、そのような記事を書くためのいくつかの試みにもかかわらず、私はそれをまだ完全なものにすることはできませんでした。 一方、「 ダーツ言語のツアー」の著者は、これについて素晴らしい仕事をしました。
トレーニングについて
このトピックは、Dartと同様に、公式ガイドで非常に詳しく説明されています。 ここでしかコピーできませんでしたが、できません。
何も待つことなく、インストールガイドページに移動し、プラットフォームを選択し、手順に従ってシステムにプラットフォームをインストールします。 エディターで、プラグインを接続します。 同じガイドには、 VS CodeとIntelliJをセットアップするための指示があります。 エディター用のDartおよびFlutter用のプラグインもあります(通常、2つをインストールする必要があります)。 アプリケーションを起動し、そのパフォーマンスを確認します 。
OSXユーザーのヒント。 iOSエミュレーターの電話のペイントされたフレームが占めるスペースを残念に思うので、それらをオフにしてiPhone 8に切り替えました(それほど長くはありません)。
Hardware → Device → iOS # → iPhone 8
-
Window → Show Device Bezels
ホットキーがあるため、ボタンなしで生きることができます: Shift + Cmd + H
これはホーム、 Cmd + Right
-そしてこれは電話を裏返すことです、残りはHardware
メニューで見つけることができます ただし、スクリーンキーボードをオンにすることをお勧めします。これは、キーボードで画面の半分が定期的にブロックされている場合にアプリケーションで作業できるかどうかを理解することが重要だからです: Cmd + K
(フォーカスが入力フィールドにあるときに機能します)。
フレーム付きのiPhone 8およびiPhone X
iPhone 8およびiPhone Xボーダレス
構造について
生成されたアプリケーションのあるフォルダーに移動して、そこにあるものを確認します。 すべてではなく、正しいもので:
-
lib/
-pub (Dartのパッケージマネージャー)の原則により、すべてのコードはこのサブフォルダーにあります。 -
pubspec.yml
-package.json
と同様に、実行するためにインストールする必要があるアプリケーションの依存関係が書き込まれますが、微妙な違いがあります。上記の標準のDartユーティリティではなく、Flutterコマンドを使用してインストールする必要があります:flutter pub get <package_name>
; -
test/
-そこに何があるか知っていますか?flutter test
呼び出すことで実行できます。 -
ios/
&android/
-各プラットフォームの設定を含むフォルダー。アプリケーションを実行するために必要な権限(場所へのアクセス、Bluetooth)、アイコン、およびプラットフォーム固有のすべてを示します。
構造を理解し、 main.dart
ファイルが待機しているlib/
フォルダーにmain.dart
ます。 ご想像のとおり、これはまさにアプリケーションを実行しなければならないファイルです。 そして、 main()
関数を呼び出すことにより、C(および他の多くの場合と同様)のように開始します。
ウィジェットについて(Hello Worldこちら)
Flutterでは、すべてがWidgetに基づいて構築されます。ビュー、テーマのあるスタイル、ウィジェットの状態があります。 ウィジェットには主に2つのタイプがあります。状態ありと状態なしですが、それについてはまだです。 簡単にしましょう。
main.dartからすべてを削除します。 コメントを注意深く読んで次のコードを貼り付けます。
import 'package:flutter/widgets.dart'; // // Dart main() main() => runApp( // runApp Flutter Text( // , , <span> 'Hello, World!!!', // — textDirection: TextDirection.ltr, // ), );
runApp(…)
は単一の引数を取ります-プロジェクト全体のルートとなるウィジェット。 ところで、Hot-reloadはそれを取得できないため、アプリケーションを再起動する必要があります。
Text(…)
-Flutterは画面上に文字列を表示することはできません。 テキストを表示するには、 Text
指定する必要があります。 textDirection
。 そして、これはtext-align
ようなテキスト配置ではなく、ウェブと比較した場合、 direction
類似物です。 アプリケーションを国際化するためのAPIの一部。 Text
は方向がわかるまで機能しませんが、どこでも指定する必要はありません。次に、アプリケーション全体のテキストの方向を調整する方法を分析します。
すでにアプリを起動しましたか? 「こんにちは、世界!」出てきました! どうやら...はい? しかし、明らかに何かがおかしかった。
テキストはシステム情報によってブロックされます。 すべての画面スペースを自由に使用でき、最初からウィジェットを取り出しました。ここには、とりわけシステム情報が表示されます。 テキストをどこかに移動してみましょう。
import 'package:flutter/widgets.dart'; main() => runApp( Center( // , child: Text( 'Hello, World!', textDirection: TextDirection.ltr, ), ), );
Center(…)
は、 child
引数で渡された別のウィジェットを水平および垂直方向の中央に配置できるウィジェットです。 ほとんどすべてのウィジェットがこれらの名前を使用して、呼び出されたウィジェット内に描画する必要があるウィジェットを伝達するため、Flutterアプリケーションでchild
とchild
がよく表示されます。
ウィジェットコンポジションは、FlutterでUIのレンダリング、外観の変更、さらにはデータの転送に使用されます。 たとえば、 Directionality(…)
ウィジェットDirectionality(…)
は、すべての子ウィジェットのテキストの方向を設定します。
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Center( child: Text('Hello, World!'), ), ), );
別の非常に重要なウィジェットを見て、同時にアプリケーションの外観を変えましょう。
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container( // ! <div> Flutter' // Container color color: Color(0xFF444444), child: Center( child: Text( 'Hello, World!', style: TextStyle( // , color: Color(0xFFFD620A), // fontSize: 32.0, // ), ), ), ), ), );
Color(…)
-色。 ドキュメントはそれを設定するさまざまな方法を示していますが、主なことは単にクラスコンストラクターに番号を渡すことです。 上記の例では、16進形式で記述された数値をコンストラクターに渡します。これは、HEXに非常に似ていますが、最初に、色の透明度を示す2つの文字を追加しました(0x00は完全に透明で、0xFFはまったく透明ではありません)。
TextStyle(…)
-さらに興味深いウィジェット。色、サイズ、太さ、行間を設定したり、下線を追加したりできます。
Flutterアプリケーションの作成、完了! ドックでは、 AndroidおよびiOS用にアセンブルする方法を読むことができます。同じ場所に、目的のストアに送信する方法を知らせるリンクがあります。 これだけでは不十分な人のために、Flutterについてさらに2、3行追加しました。
プロステートレスウィジェット
ウィジェットの使用方法-わかったので、今度はウィジェットの作成方法を理解しましょう。 状態を持っているウィジェットと持っていないウィジェットがあることは既に上で述べました。 これまで、ステートレスウィジェットのみを使用してきました。 これは、ウィジェットが単なるクラスであり、プロパティを変更できるため、まったく持っていないという意味ではありません。 ウィジェットがレンダリングされた直後に、その状態を変更しても、UIでこのウィジェットが更新されることはありません。 たとえば、画面上のテキストを変更する必要がある場合、別のText
ウィジェットを生成し、表示する新しいコンテンツを指定する必要があります。 そのようなウィジェットは、私が何を意味するか知っていれば、定数と呼ぶことができます。 そして、それらはシンプルなので、それらから始めましょう。
ステートレスウィジェットを作成するには、次のものが必要です。
- 新しいクラスに美しい名前を付けます。
-
StatelessWidget
からクラスを継承します。 -
BuildContext
を引数として受け取り、ある種のWidget
を返すbuild()
メソッドを実装します。
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Center( child: MyStatelessWidget() ), ), ); class MyStatelessWidget extends StatelessWidget { // @override , , // // , @override Widget build(BuildContext context) { // [context] return Text('Hello!'); } }
引数が1つのウィジェットの例:
// … class MyStatelessWidget extends StatelessWidget { // Stateless final, const final String name; // MyStatelessWidget(this.name); // @override Widget build(BuildContext context) { // [context] return Text('Hello, $name!'); } }
ステートレスと追加するものについて...
ホットリロードについて
ウィジェットのコンテンツを変更すると、アプリケーションが自動的に再描画されることに注意してください。 main()
関数からウィジェットを削除した後、Hot-reloadが役立ちました。
また、ホットスワップ用に起動されたモジュールにより、アプリケーションの実行速度が1桁遅くなることを理解することも重要です。
GestureDetectorについて
次のセクションでは、 StatefulWidget
(状態が変化すると変化するウィジェット)を扱います。 これを面白くするために、この状態を何らかの形で変更する必要があります、同意しますか? 画面上のタッチに応じて、ウィジェットの状態を変更します。 これを行うには、 GestureDetector(…)
を使用しGestureDetector(…)
ウィジェットは何もレンダリングしませんが、スマートフォンの画面上のタッチを監視し、転送された機能を呼び出すことについて報告します。
画面の中央にボタンを作成します。クリックすると、コンソールにメッセージが表示されます。
import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container( color: Color(0xFFFFFFFF), child: App(), ), ), ); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: GestureDetector( // onTap: () { // GestureDetector // , print('You pressed me'); }, child: Container( // decoration: BoxDecoration( // shape: BoxShape.circle, // color: Color(0xFF17A2B8), // ), width: 80.0, height: 80.0, ), ), ); } }
青いボタンをクリックして、コンソールにメッセージを表示します。 もう一度クリックすると、コンソールにメッセージが表示されます。 もう一度...大丈夫、固執を停止します。
ステートフルウィジェット
StatefulWidget
シンプル、 StatelessWidget
よりもさらにシンプル。 ただし、微妙な違いがあります。それらは単独では存在しません。作業のために、このウィジェットの状態を保存する別のクラスが必要です。 同時に、その視覚部分(それを構成するウィジェット)もその状態になります。
開始するには、ウィジェットクラスを見てください。
// … class Counter extends StatefulWidget { // , , // createState() @override State<Counter> createState() => _CounterState(); // State, // State<> }
上記では、非常に単純なcreateState()
メソッドを実装する「空の」ウィジェットを作成しました。 このプレゼンテーションと状態の分離により、Flutterはアプリケーションを大幅に最適化できます。
状態オブジェクトは完全に複雑ではありません。 さらに、上記のStatelessWidget
とほぼ同じです。 主な違いは親クラスです。
// … class _CounterState extends State<Counter> { // - , // . // , int counter = 0; // , // , Stateless . @override Widget build(BuildContext context) { // , // — : return Center( child: GestureDetector( onTap: () { // , , // counter. setState(() { // setState() , // , ++counter; }); }, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF17A2B8), ), width: 80.0, child: Center( child: Text( // counter '$counter', // style: TextStyle(fontSize: 30.0), ), ), ), ), ); } }
クラス名は下線で始まることに注意してください。 Dartでは、アンダースコアで始まるすべての名前はプライベート値を識別します。 また、Flutterのウィジェットの状態は通常プライベートのままですが、これは必須ではありません。
なんて素晴らしいアプリケーションでしょう! これは素晴らしい結果です。 しかし、コースのこの部分を完了する前に、さらにいくつかの興味深いウィジェットを見てみましょう。 今回だけ、より興味深いコードにするために、より多くのコードを作成します。 アプリケーションの大部分はユーザーに馴染みのあるものであり、残りは既に理解しているはずです。
import 'package:flutter/widgets.dart'; main() => runApp(App()); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.ltr, child: Container( padding: EdgeInsets.symmetric( vertical: 60.0, horizontal: 20.0, ), color: Color(0xFFFFFFFF), child: Content(), ), ); } } class Content extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: [ Counter('Manchester United'), Counter('Juventus'), ], ); } } class Counter extends StatefulWidget { final String _name; Counter(this._name); @override State<Counter> createState() => _CounterState(); } class _CounterState extends State<Counter> { int count = 0; @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: 10.0), padding: EdgeInsets.all(4.0), decoration: BoxDecoration( border: Border.all(color: Color(0xFFFD6A02)), borderRadius: BorderRadius.circular(4.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // widget — State, // , _CounterLabel(widget._name), _CounterButton( count, onPressed: () { setState(() { ++count; }); }, ), ], ), ); } } class _CounterLabel extends StatelessWidget { static const textStyle = TextStyle( color: Color(0xFF000000), fontSize: 26.0, ); final String _label; _CounterLabel(this._label); @override Widget build(BuildContext context) { return Text( _label, style: _CounterLabel.textStyle, ); } } class _CounterButton extends StatelessWidget { final _count; final _onPressed; _CounterButton(this._count, {@required this._onPressed}); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { _onPressed(); }, child: Container( padding: EdgeInsets.symmetric(horizontal: 6.0), decoration: BoxDecoration( color: Color(0xFFFD6A02), borderRadius: BorderRadius.circular(4.0), ), child: Center( child: Text( '$_count', style: TextStyle(fontSize: 20.0), ), ), ), ); } }
Column()
とRow()
2つの新しいウィジェットがあります。 彼らが何をしているかを理解してみてください。 次の記事では、それらをさらに詳しく調べ、他のウィジェットを一緒に構成できる複数のウィジェットを見て、マテリアルと呼ばれるFlutterライブラリを使用して素晴らしいアプリケーションを作成します。
宿題について
暇なときに他の何かを読みたい場合は、ここに興味深いリンクのリストがあります: