Flutterを使用したレスポンシブWebおよびデスクトップ開発

公開: 2022-03-10
簡単なまとめ↬Flutterは、すでにモバイル開発シーンに大きな影響を与えています。 今では、より大きなデバイスも採用しています。 この素晴らしいクロスプラットフォームフレームワークを使用してWebアプリとデスクトップアプリを開発するタスクを実行する準備をするために知っておく必要があることは次のとおりです。

このチュートリアルは、Flutter自体の紹介ではありません。 Flutterの基本を学ぶのに役立つ簡単な紹介とともに、オンラインで利用できる記事、ビデオ、およびいくつかの本がたくさんあります。 代わりに、次の2つの目的について説明します。

  1. Flutterの非モバイル開発の現状と、デスクトップまたはラップトップコンピューターのブラウザーでFlutterコードを実行する方法。
  2. Flutterを使用してレスポンシブアプリを作成する方法。これにより、特にWebフレームワークとしてのパワーをフルディスプレイで確認でき、URLに基​​づくルーティングに関するメモで終わります。

入りましょう!

フラッターとは何か、なぜそれが重要なのか、何に進化したのか、どこに向かっているのか

FlutterはGoogleの最新のアプリ開発フレームワークです。 Googleは、これを包括的であると想定しています。これにより、すべてのブランドのスマートフォン、タブレット、デスクトップおよびラップトップコンピューターで、ネイティブアプリまたはWebページとして同じコードを実行できるようになります。

これは非常に野心的なプロジェクトですが、Googleはこれまで、特に2つの側面で信じられないほどの成功を収めてきました。AndroidとiOSのネイティブアプリ向けの真にプラットフォームに依存しないフレームワークを作成し、本番環境で使用する準備が整っていることと、印象的なフロントを作成することです。 -互換性のあるFlutterアプリとコードの100%を共有できるエンドWebフレームワーク。

次のセクションでは、アプリの互換性と、現在の非モバイルFlutter開発の状況について説明します。

ジャンプした後もっと! 以下を読み続けてください↓

Flutterを使用した非モバイル開発

Flutterを使用した非モバイル開発は、Google I / O 2019で最初に重要な方法で公開されました。このセクションでは、Flutterを機能させる方法と機能するタイミングについて説明します。

Webおよびデスクトップ開発を有効にする方法

Web開発を有効にするには、最初にFlutterのベータチャネルにアクセスする必要があります。 そのポイントに到達するには2つの方法があります。

  • SDKアーカイブから適切な最新のベータバージョンをダウンロードして、Flutterをベータチャネルに直接インストールします。
  • すでにFlutterがインストールされている場合は、 $ flutter channel betaでベータチャネルに切り替えてから、Flutterバージョン(実際にはFlutterインストールフォルダーのgit pull )を$ flutter upgradeで更新して切り替え自体を実行します。

その後、これを実行できます:

 $ flutter config --enable-web

デスクトップのサポートは、特にLinuxとWindowsのツールが不足しているため、プラグインの開発が特に大きな苦痛であり、それに使用されるAPIが概念実証用であり、製造。 これは、WindowsおよびLinuxのネイティブデスクトップアプリでもサポートされていないリリースビルドに実証済みのdart2jsコンパイラを使用しているWeb開発とは異なります。

macOSのサポートはWindowsやLinuxのサポートよりもわずかに優れていますが、それでもWebのサポートほど良くはなく、モバイルプラットフォームの完全なサポートほど良くはありません。

デスクトップ開発のサポートを有効にするには、 betaチャネルについて前述したのと同じ手順に従って、 masterリリースチャネルに切り替える必要があります。 次に、 <OS_NAME>linuxwindows 、またはmacosのいずれかに置き換えて、以下を実行します。

 $ flutter config --enable-<OS_NAME>-desktop

この時点で、Flutterツールが私が言っていることを実行していないために説明する次の手順のいずれかに問題がある場合、一般的なトラブルシューティング手順は次のとおりです。

  • flutter doctorを実行して問題をチェックします。 このFlutterコマンドの副作用は、必要なツールがない場合はダウンロードする必要があることです。
  • flutter upgradeを実行します。
  • オフにしてからもう一度オンにします。 コンピュータを再起動するという古いティア1テクニカルサポートの答えは、Flutterの豊富な機能を十分に楽しむために必要なものかもしれません。

FlutterWebアプリの実行と構築

Flutter Webのサポートはまったく悪くありません。これは、Webの開発のしやすさに反映されています。

これを実行しています…

 $ flutter devices

…次のようなエントリをすぐに表示する必要があります。

 Web Server • web-server • web-javascript • Flutter Tools

さらに、Chromeブラウザを実行すると、Flutterにもそのエントリが表示されます。 互換性のあるFlutterプロジェクトでFlutter flutter runと(詳細は後で説明します)、表示される「接続されたデバイス」がWebサーバーのみの場合、Flutterはlocalhost:<RANDOM_PORT>でWebサーバーを起動します。これにより、Flutterにアクセスできるようになります。任意のブラウザからのWebアプリ。

Chromeをインストールしても表示されない場合は、 CHROME_EXECUTABLE環境変数をChrome実行可能ファイルへのパスに設定する必要があります。

Flutterデスクトップアプリの実行と構築

Flutterデスクトップサポートを有効にした後、Flutterアプリを開発ワークステーションでflutter run -d <OS_NAME>を使用してネイティブに実行し、 <OS_NAME>をデスクトップサポートを有効にするときに使用したのと同じ値に置き換えることができます。 flutter build <OS_NAME>を使用して、 buildディレクトリにバイナリをビルドすることもできます。

ただし、そのいずれかを実行する前に、Flutterがプラットフォーム用に構築する必要があるものを含むディレクトリが必要です。 これは、新しいプロジェクトを作成するときに自動的に作成されますが、 flutter create . 。 また、LinuxおよびWindows APIは不安定であるため、Flutterの更新後にアプリが機能しなくなった場合は、これらのプラットフォーム用にAPIを再生成する必要があります。

アプリはいつ互換性がありますか?

FlutterアプリがデスクトップまたはWebで機能するためには、「互換性のあるプロジェクト」である必要があると言ったとき、私はずっと何を意味していましたか? 簡単に言うと、ビルドしようとしているプラ​​ットフォームのプラットフォーム固有の実装がないプラグインを使用してはならないということです。

この点をすべての人に完全に明確にし、誤解を避けるために、 Flutterプラグインは、その機能を提供するために必要なプラットフォーム固有のコードを含む特定のFlutterパッケージであることに注意してください。

たとえば、Googleが開発したurl_launcherパッケージを好きなだけ使用できます(Webがハイパーリンク上に構築されている場合は、必要に応じて使用できます)。

Googleが開発したパッケージの例として、Web開発が不可能になる場合はpath_providerがあります。これは、ファイルを保存するローカルストレージパスを取得するために使用されます。 これは、ちなみにWebアプリには役に立たないパッケージの例であるため、使用できないことは、コードを変更する必要があるという事実を除いて、実際には厄介なことではありません。あなたがそれを使用している場合、それはウェブ上で動作します。

たとえば、Web上のlocalStorageに依存するshared_preferencesパッケージを使用できます。

デスクトッププラットフォームに関しても同様の警告が当てはまります。デスクトッププラットフォームと互換性のあるプラグインはほとんどありません。これは繰り返し発生するテーマであるため、Flutter for the webで実際に必要な作業よりも、デスクトップ側で行う必要のある作業がはるかに多くなります。

Flutterでレスポンシブレイアウトを作成する

上記で説明したことと簡単にするために、この投稿の残りの部分では、ターゲットプラットフォームはWebであると想定しますが、基本的な概念はデスクトップ開発にも適用されます。

Webをサポートすることには、利点と責任があります。 さまざまな画面サイズをサポートすることを余儀なくされることは欠点のように聞こえるかもしれませんが、Webブラウザーでアプリを実行すると、別々に実行しなくても、さまざまなサイズとアスペクト比の画面でアプリがどのように表示されるかを非常に簡単に確認できることを考慮してください。モバイルデバイスエミュレーター。

それでは、コードについて話しましょう。 アプリをレスポンシブにするにはどうすればよいですか?

この分析を行うには、次の2つの観点があります。

  1. 「どのウィジェットを使用していますか、またはさまざまなサイズの画面に適応できる、または適応する必要があるウィジェットを使用できますか?」
  2. 「画面のサイズに関する情報を取得するにはどうすればよいですか。また、UIコードを作成するときにそれを使用するにはどうすればよいですか?」

最初の質問には後で答えます。 後者については、最初に話しましょう。これは非常に簡単に処理でき、問題の中心にあるためです。 これを行うには2つの方法があります。

  1. 1つの方法は、 MediaQueryルートのMediaQueryDataから情報を取得することです。この情報は、Flutterアプリ( MaterialApp/WidgetsApp/CupertinoApp InheritedWidget一部)が機能するためにウィジェットツリーに存在する必要があります。これは、次のように取得できます。 MediaQuery.of(context)を使用するその他のInheritedWidgetは、 Size型のsizeプロパティを持ち、したがってdouble型の2つのwidthプロパティとheightプロパティを持ちます。
  2. もう1つの方法は、 LayoutBuilderを使用することです。これはビルダーウィジェット( StreamBuilderFutureBuilderと同様)であり、 minHeightmaxHeightminWidthmaxWidthプロパティを持つBoxConstraintsオブジェクトを( contextとともに) builder関数に渡します。

これは、 MediaQueryを使用して制約を取得するDartPadの例であり、そのコードは次のとおりです。

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { @override Widget build(context) => Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( "Width: ${MediaQuery.of(context).size.width}", style: Theme.of(context).textTheme.headline4 ), Text( "Height: ${MediaQuery.of(context).size.height}", style: Theme.of(context).textTheme.headline4 ) ] ) ) ); }

そして、これが同じことのためにLayoutBuilderを使用しているものです:

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { @override Widget build(context) => Scaffold( body: LayoutBuilder( builder: (context, constraints) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( "Width: ${constraints.maxWidth}", style: Theme.of(context).textTheme.headline4 ), Text( "Height: ${constraints.maxHeight}", style: Theme.of(context).textTheme.headline4 ) ] ) ) ) ); }

それでは、どのウィジェットが制約に適応できるかを考えてみましょう。

まず、画面のサイズに応じて複数のウィジェットをレイアウトするさまざまな方法について考えてみましょう。

最も簡単に適応できるウィジェットはGridViewです。 実際、 GridViewコンストラクターを使用して構築されたGridView.extentは、この非常に単純な例でわかるように、レスポンシブにするために関与する必要さえありません。

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { final List elements = [ "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit" ]; @override Widget build(context) => Scaffold( body: GridView.extent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, children: elements.map((el) => Card(child: Center(child: Padding(padding: EdgeInsets.all(8.0), child: Text(el))))).toList() ) ); } import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { final List elements = [ "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit" ]; @override Widget build(context) => Scaffold( body: GridView.extent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, children: elements.map((el) => Card(child: Center(child: Padding(padding: EdgeInsets.all(8.0), child: Text(el))))).toList() ) ); }

maxCrossAxisExtentを変更することで、さまざまなサイズのコンテンツに対応できます。

この例は主にGridView.extentコンストラクターの存在を示す目的を果たしましたが、それを行うためのはるかに賢い方法は、 SliverGridDelegateWithMaxCrossAxisExtentGridViewを使用することです。この場合、ウィジェットはグリッドに表示されGridView.builder 。この例でわかるように、別のデータ構造から動的に作成されます。

 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: MyHomePage() ); } class MyHomePage extends StatelessWidget { final List<String> elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => Scaffold( body: GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ) ); }

さまざまな画面に適応するGridViewの例は、私の個人的なランディングページです。これは、 Cardsが少し複雑で大きいことを除いて、前のサンプルコードと同じように、多数のCardsを備えたGridViewで構成される非常に単純なFlutterWebアプリです。 。

電話用に設計されたアプリに加えることができる非常に簡単な変更は、スペースがあるときにDrawerを左側の永続的なメニューに置き換えることです。

たとえば、ナビゲーションに使用される次のようなウィジェットのListViewを作成できます。

 class Menu extends StatelessWidget { @override Widget build(context) => ListView( children: [ FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_one), title: Text("First Link"), ) ), FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_two), title: Text("Second Link"), ) ) ] ); }

スマートフォンでは、 Drawerの中にある一般的な使用場所(ハンバーガーメニューとも呼ばれます)。

これに代わる方法は、 BottomNavigationBarまたはTabBarとTabBarViewの組み合わせTabBarが、どちらの場合も、ドロワーで必要とされるよりも多くの変更を加える必要があるため、ドロワーを使用します。

以前に見たMenuを含むDrawerを小さな画面でのみ表示するには、次のスニペットのようなコードを記述し、 MediaQuery.of(context)を使用して幅を確認し、 DrawerオブジェクトをScaffoldに渡す場合のみアプリに適していると思われる幅の値よりも小さい値:

 Scaffold( appBar: AppBar(/* ... \*/), drawer: MediaQuery.of(context).size.width < 500 ? Drawer( child: Menu(), ) : null, body: /* ... \*/ )

それでは、 Scaffoldbodyについて考えてみましょう。 アプリのメインコンテンツのサンプルとして、以前に作成したGridViewを使用します。これは、混乱を避けるためにContentという名前の別のウィジェットに保持されます。

 class Content extends StatelessWidget { final List elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); } class Content extends StatelessWidget { final List elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); }

より大きな画面では、本文自体が2つのウィジェットを表示するRowである場合があります。1つは固定幅に制限されているMenuで、もう1つは画面の残りの部分を埋めるContentです。

小さい画面では、 body全体がContentになります。

すべてをSafeAreaウィジェットとCenterウィジェットでラップします。これは、Flutter Webアプリウィジェットが、特にRowColumnを使用している場合に、表示されている画面領域の外側になってしまうことがあり、 SafeAreaCenterで修正されるためです。

これは、 Scaffoldbodyが次のようになることを意味します。

 SafeArea( child:Center( child: MediaQuery.of(context).size.width < 500 ? Content() : Row( children: [ Container( width: 200.0, child: Menu() ), Container( width: MediaQuery.of(context).size.width-200.0, child: Content() ) ] ) ) )

これらすべてをまとめると、次のようになります。

(大プレビュー)
 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( home: HomePage() ); } class HomePage extends StatelessWidget { @override Widget build(context) => Scaffold( appBar: AppBar(title: Text("test")), drawer: MediaQuery.of(context).size.width < 500 ? Drawer( child: Menu(), ) : null, body: SafeArea( child:Center( child: MediaQuery.of(context).size.width < 500 ? Content() : Row( children: [ Container( width: 200.0, child: Menu() ), Container( width: MediaQuery.of(context).size.width-200.0, child: Content() ) ] ) ) ) ); } class Menu extends StatelessWidget { @override Widget build(context) => ListView( children: [ FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_one), title: Text("First Link"), ) ), FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_two), title: Text("Second Link"), ) ) ] ); } class Content extends StatelessWidget { final List<String> elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); }

これは、FlutterのレスポンシブUIの一般的な紹介として必要なもののほとんどです。 そのアプリケーションの多くはアプリの特定のUIに依存し、アプリをレスポンシブにするために何ができるかを正確に特定することは困難であり、好みに応じて多くのアプローチをとることができます。 ただし、ここで、一般的なアプリ要素とUIフローについて考えて、より完全な例をレスポンシブアプリにする方法を見てみましょう。

コンテキストに入れる:アプリをレスポンシブにする

これまでのところ、画面だけがあります。 これを、URLベースのナビゲーションが機能する2画面アプリに拡張しましょう。

レスポンシブログインページの作成

アプリにログインページがある可能性があります。 どうすればそれをレスポンシブにすることができますか?

モバイルデバイスのログイン画面は、通常、互いに非常によく似ています。 利用可能なスペースはそれほど多くありません。 これは通常、ウィジェットの周りにいくつかのPaddingがある単なるColumnであり、ユーザー名とパスワードを入力するためのTextFieldと、ログインするためのボタンが含まれています。したがって、かなり標準的です(ただし、必要に応じて機能しません。 、各TextFieldTextEditingController )モバイルアプリのログインページは次のようになります。

 Scaffold( body: Container( padding: const EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text("Welcome to the app, please log in"), TextField( decoration: InputDecoration( labelText: "username" ) ), TextField( obscureText: true, decoration: InputDecoration( labelText: "password" ) ), RaisedButton( color: Colors.blue, child: Text("Log in", style: TextStyle(color: Colors.white)), onPressed: () {} ) ] ), ), )

モバイルデバイスでは問題ないように見えますが、これらの非常に広いTextFieldは、大きな画面は言うまでもなく、タブレットでは耳障りに見え始めます。 ただし、携帯電話は画面サイズが異なるため、固定幅だけを決めることはできず、ある程度の柔軟性を維持する必要があります。

たとえば、実験を通じて、最大幅を500にする必要があることがわかります。まあ、 Containerconstraintsを500に設定します(前の例では、これでどこに行くのかがわかっていたので、 Paddingの代わりにContainerを使用しました)そして、私たちは行ってもいいですよね? 実際にはそうではありません。ログインウィジェットが画面の左側に固定されるため、すべてを拡大するよりもさらに悪い場合があります。 したがって、次のようにCenterウィジェットでラップします。

 Center( child: Container( constraints: BoxConstraints(maxWidth: 500), padding: const EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), child: Column(/* ... \*/) ) )

これはすでに問題ないように見え、 LayoutBuilderまたはMediaQuery.of MediaQuery.of(context).sizeのいずれかを使用する必要さえありませんでした。 ただし、これを非常に見栄えよくするために、さらに一歩進んでみましょう。 私の見解では、前景部分が背景から何らかの方法で分離されていると、見栄えが良くなります。 これは、入力ウィジェットを使用してContainerの背後にあるものに背景色を付け、前景のContainerを白に保つことで実現できます。 見栄えを少し良くするために、大きなデバイスでContainerが画面の上下に伸びないようにし、角を丸くして、2つのレイアウト間でアニメーション化された素敵なトランジションを与えましょう。

これらすべてに、背景色を設定し、大きな画面の側面だけでなくContainer全体にパディングを追加するために、 LayoutBuilderと外部Containerが必要になりました。 また、パディング量の変更をアニメーション化するには、その外側のContainerAnimatedContainerに変換する必要があります。これには、アニメーションのdurationが必要です。これは、0.5秒に設定されDuration(milliseconds: 500)コード。

レスポンシブログインページの例を次に示します。

(大プレビュー)
 class LoginPage extends StatelessWidget { @override Widget build(context) => Scaffold( body: LayoutBuilder( builder: (context, constraints) { return AnimatedContainer( duration: Duration(milliseconds: 500), color: Colors.lightGreen[200], padding: constraints.maxWidth < 500 ? EdgeInsets.zero : EdgeInsets.all(30.0), child: Center( child: Container( padding: EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), constraints: BoxConstraints( maxWidth: 500, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5.0), ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text("Welcome to the app, please log in"), TextField( decoration: InputDecoration( labelText: "username" ) ), TextField( obscureText: true, decoration: InputDecoration( labelText: "password" ) ), RaisedButton( color: Colors.blue, child: Text("Log in", style: TextStyle(color: Colors.white)), onPressed: () { Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) => HomePage() ) ); } ) ] ), ), ) ); } ) ); }

ご覧のとおり、 RaisedButtononPressedを、 HomePageという名前の画面(たとえば、 GridViewとメニューまたはドロワーを使用して以前に作成したビューなど)に移動するコールバックに変更しました。 ただし、ここでは、そのナビゲーション部分に焦点を当てます。

名前付きルート:アプリのナビゲーションを適切なWebアプリのようにする

Webアプリに共通するのは、URLに基​​づいて画面を変更する機能です。 たとえば、 https://appurl/loginにアクセスすると、 https://appurl/somethingelse somethingelseとは異なるものが表示されます。 実際、Flutterは名前付きルートをサポートしています。これには2つの目的があります。

  1. Webアプリでは、前の文で述べたのとまったく同じ機能があります。
  2. どのアプリでも、アプリのルートを事前に定義して名前を付け、名前を指定するだけでそのルートに移動できます。

これを行うには、 MaterialAppコンストラクターを次のようなものに変更する必要があります。

 MaterialApp( initialRoute: "/login", routes: { "/login": (context) => LoginPage(), "/home": (context) => HomePage() } );

次に、Navigator.push(context、route)とNavigator.pushReplacement(context, route) (context、route)の代わりに、 Navigator.push(context, route) Navigator.pushNamed(context, routeName)Navigator.pushReplacementNamed(context, routeName) )を使用して別のルートに切り替えることができます。

これは、この記事の残りの部分で作成した架空のアプリに適用されたものです。 DartPadで実際に動作中の名前付きルートを確認することはできないため、 flutter runを使用して自分のマシンでこれを試すか、動作中の例を確認する必要があります。

(大プレビュー)
 import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(context) => MaterialApp( initialRoute: "/login", routes: { "/login": (context) => LoginPage(), "/home": (context) => HomePage() } ); } class LoginPage extends StatelessWidget { @override Widget build(context) => Scaffold( body: LayoutBuilder( builder: (context, constraints) { return AnimatedContainer( duration: Duration(milliseconds: 500), color: Colors.lightGreen[200], padding: constraints.maxWidth < 500 ? EdgeInsets.zero : const EdgeInsets.all(30.0), child: Center( child: Container( padding: const EdgeInsets.symmetric( vertical: 30.0, horizontal: 25.0 ), constraints: BoxConstraints( maxWidth: 500, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(5.0), ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Text("Welcome to the app, please log in"), TextField( decoration: InputDecoration( labelText: "username" ) ), TextField( obscureText: true, decoration: InputDecoration( labelText: "password" ) ), RaisedButton( color: Colors.blue, child: Text("Log in", style: TextStyle(color: Colors.white)), onPressed: () { Navigator.pushReplacementNamed( context, "/home" ); } ) ] ), ), ) ); } ) ); } class HomePage extends StatelessWidget { @override Widget build(context) => Scaffold( appBar: AppBar(title: Text("test")), drawer: MediaQuery.of(context).size.width < 500 ? Drawer( child: Menu(), ) : null, body: SafeArea( child:Center( child: MediaQuery.of(context).size.width < 500 ? Content() : Row( children: [ Container( width: 200.0, child: Menu() ), Container( width: MediaQuery.of(context).size.width-200.0, child: Content() ) ] ) ) ) ); } class Menu extends StatelessWidget { @override Widget build(context) => ListView( children: [ FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_one), title: Text("First Link"), ) ), FlatButton( onPressed: () {}, child: ListTile( leading: Icon(Icons.looks_two), title: Text("Second Link"), ) ), FlatButton( onPressed: () {Navigator.pushReplacementNamed( context, "/login");}, child: ListTile( leading: Icon(Icons.exit_to_app), title: Text("Log Out"), ) ) ] ); } class Content extends StatelessWidget { final List<String> elements = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "A Million Billion Trillion", "A much, much longer text that will still fit"]; @override Widget build(context) => GridView.builder( itemCount: elements.length, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: 130.0, crossAxisSpacing: 20.0, mainAxisSpacing: 20.0, ), itemBuilder: (context, i) => Card( child: Center( child: Padding( padding: EdgeInsets.all(8.0), child: Text(elements[i]) ) ) ) ); }

フラッターアドベンチャーで

これにより、大画面、特にWebでFlutterを使用して何ができるかがわかります。 それは素敵なフレームワークであり、非常に使いやすく、その極端なクロスプラットフォームのサポートにより、学習して使い始めることがより重要になります。 だから、先に進んで、WebアプリのFlutterも信頼し始めてください!

その他のリソース

  • 「デスクトップシェル」、GitHub
    デスクトップ上のFlutterの現在の常に最新の状態
  • 「Flutterのデスクトップサポート」、Flutter
    完全にサポートされているデスクトッププラットフォームに関する情報
  • 「FlutterのWebサポート」、Flutter
    ウェブ用のFlutterに関する情報
  • 「すべてのサンプル」、Flutter
    Flutterサンプルとアプリの厳選されたリスト