Flutter-introduction-to-layouts
Flutter-レイアウトの概要
_Flutter_の中心概念は_Everything_が_widget_であるため、_Flutter_はウィジェット自体にユーザーインターフェイスレイアウト機能を組み込んでいます。 _Flutter_は、_Container、Center、Align_などの特別に設計された多くのウィジェットを提供しますが、これらはユーザーインターフェイスをレイアウトするためだけのものです。 ウィジェットは、他のウィジェットを構成することにより構築され、通常はレイアウトウィジェットを使用します。 この章の_Flutter_レイアウトの概念を学んでみましょう。
レイアウトウィジェットのタイプ
レイアウトウィジェットは、その子に基づいて2つの異なるカテゴリにグループ化することができます-
- 単一の子をサポートするウィジェット
- 複数の子をサポートするウィジェット
今後のセクションで、ウィジェットのタイプとその機能の両方を学びましょう。
単一の子ウィジェット
このカテゴリでは、ウィジェットには子として1つのウィジェットのみがあり、すべてのウィジェットには特別なレイアウト機能があります。
たとえば、_Center_ウィジェットは、親ウィジェットに対して子ウィジェットを中央に配置するだけで、_Container_ウィジェットは、パディング、装飾などのさまざまなオプションを使用して、その内部の任意の場所に子を配置する完全な柔軟性を提供します。
単一の子ウィジェットは、ボタン、ラベルなどの単一の機能を備えた高品質のウィジェットを作成するための優れたオプションです。
_Container_ウィジェットを使用してシンプルなボタンを作成するコードは次のとおりです-
class MyButton extends StatelessWidget {
MyButton({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
border: Border(
top: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
left: BorderSide(width: 1.0, color: Color(0xFFFFFFFFFF)),
right: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
bottom: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
),
),
child: Container(
padding: const
EdgeInsets.symmetric(horizontal: 20.0, vertical: 2.0),
decoration: const BoxDecoration(
border: Border(
top: BorderSide(width: 1.0, color: Color(0xFFFFDFDFDF)),
left: BorderSide(width: 1.0, color: Color(0xFFFFDFDFDF)),
right: BorderSide(width: 1.0, color: Color(0xFFFF7F7F7F)),
bottom: BorderSide(width: 1.0, color: Color(0xFFFF7F7F7F)),
),
color: Colors.grey,
),
child: const Text(
'OK',textAlign: TextAlign.center, style: TextStyle(color: Colors.black)
),
),
);
}
}
ここでは、_Container_ウィジェットと_Text_ウィジェットの2つのウィジェットを使用しました。 ウィジェットの結果は、以下に示すようにカスタムボタンとしてです-
_Flutter_が提供する最も重要な単一の子レイアウトウィジェットのいくつかをチェックしましょう−
- Padding -指定されたパディングで子ウィジェットを配置するために使用されます。 ここでは、_EdgeInsets_クラスによってパディングを提供できます。
- Align -_alignment_プロパティの値を使用して、子ウィジェットをそれ自体内で位置合わせします。 _alignment_プロパティの値は、_FractionalOffset_クラスによって提供できます。 _FractionalOffset_クラスは、左上からの距離でオフセットを指定します。
オフセットの可能な値のいくつかは次のとおりです-
- FractionalOffset(1.0、0.0)は右上を表します。
- FractionalOffset(0.0、1.0)は左下を表します。
オフセットに関するサンプルコードを以下に示します-
Center(
child: Container(
height: 100.0,
width: 100.0,
color: Colors.yellow, child: Align(
alignment: FractionalOffset(0.2, 0.6),
child: Container( height: 40.0, width:
40.0, color: Colors.red,
),
),
),
)
- FittedBox -子ウィジェットをスケーリングし、指定されたフィットに応じて配置します。
- AspectRatio -指定されたアスペクト比に子ウィジェットのサイズを変更しようとします
- ConstrainedBox
- ベースライン
- FractinallySizedBox
- IntrinsicHeight
- IntrinsicWidth
- LiimitedBox
- オフステージ
- OverflowBox
- SizedBox
- SizedOverflowBox
- 変換する
- CustomSingleChildLayout
私たちのhello worldアプリケーションは、マテリアルベースのレイアウトウィジェットを使用してホームページを設計しています。 hello worldアプリケーションを変更して、以下に指定されている基本的なレイアウトウィジェットを使用してホームページを構築します。
- Container -位置合わせ、パディング、境界線、マージンを備えた汎用の単一の子、ボックスベースのコンテナウィジェットと豊富なスタイリング機能。
- Center -子ウィジェットを中央に配置するシンプルな単一の子コンテナウィジェット。
_MyHomePage_および_MyApp_ウィジェットの変更されたコードは以下のとおりです-
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MyHomePage(title: "Hello World demo app");
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.white,),
padding: EdgeInsets.all(25), child: Center(
child:Text(
'Hello World', style: TextStyle(
color: Colors.black, letterSpacing: 0.5, fontSize: 20,
),
textDirection: TextDirection.ltr,
),
)
);
}
}
ここに、
- _Container_ウィジェットは、トップレベルまたはルートウィジェットです。 _Container_は、_decoration_および_padding_プロパティを使用してコンテンツをレイアウトするように構成されます。
- _BoxDecoration_には、_Container_ウィジェットを装飾するための色、境界線などの多くのプロパティがあり、ここでは、_color_を使用してコンテナの色を設定します。
- _Container_ウィジェットの_padding_は、パディング値を指定するオプションを提供する_dgeInsets_クラスを使用して設定されます。
- _Center_は、_Container_ウィジェットの子ウィジェットです。 繰り返しますが、_Text_は_Center_ウィジェットの子です。 _Text_はメッセージを表示するために使用され、_Center_は親ウィジェット_Container_に対してテキストメッセージを中央に配置するために使用されます。
上記のコードの最終結果は、以下に示すようなレイアウトサンプルです-
複数の子ウィジェット
このカテゴリでは、特定のウィジェットに複数の子ウィジェットがあり、各ウィジェットのレイアウトは一意です。
たとえば、_Row_ウィジェットでは、子を水平方向にレイアウトできますが、_Column_ウィジェットでは、子を垂直方向にレイアウトできます。 _Row_と_Column_を構成することにより、あらゆるレベルの複雑さを持つウィジェットを構築できます。
このセクションで頻繁に使用されるウィジェットのいくつかを学びましょう。
- 行-子を水平方向に配置できます。
- 列-子を垂直方向に配置できます。
- ListView -子をリストとして配置できます。
- GridView -子をギャラリーとして配置できます。
- Expanded -Row and Columnウィジェットの子を作成して、可能な限り最大の領域を占めるようにします。
- Table -テーブルベースのウィジェット。
- Flow -フローベースのウィジェット。
- Stack -スタックベースのウィジェット。
高度なレイアウトアプリケーション
このセクションでは、単一および複数の子レイアウトウィジェットを使用して、カスタムデザインで_product Listing_の複雑なユーザーインターフェイスを作成する方法を学びましょう。
この目的のために、以下に示すシーケンスに従ってください-
- Androidスタジオで_product_layout_app_に新しい_Flutter_アプリケーションを作成します。
- _main.dart_コードを次のコードに置き換えます-
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
//This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo', theme: ThemeData(
primarySwatch: Colors.blue,),
home: MyHomePage(title: 'Product layout demo home page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(this.title),),
body: Center(child: Text( 'Hello World', )),
);
}
}
- ここに、
- デフォルトの_StatefulWidget_の代わりに_StatelessWidget_を拡張して_MyHomePage_ウィジェットを作成し、関連するコードを削除しました。
- 次に、以下に示すように、指定されたデザインに従って、_ProductBox_という新しいウィジェットを作成します-
- _ProductBox_のコードは次のとおりです。
class ProductBox extends StatelessWidget {
ProductBox({Key key, this.name, this.description, this.price, this.image})
: super(key: key);
final String name;
final String description;
final int price;
final String image;
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2), height: 120, child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[
Image.asset("assets/appimages/" +image), Expanded(
child: Container(
padding: EdgeInsets.all(5), child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(this.name, style: TextStyle(fontWeight:
FontWeight.bold)), Text(this.description),
Text("Price: " + this.price.toString()),
],
)
)
)
]
)
)
);
}
}
- コードで次のことに注意してください-
_ProductBox_は、以下に指定されている4つの引数を使用しています-
- name-製品名
- 説明-製品の説明
- 価格-製品の価格
- 画像-製品の画像
_ProductBox_は、以下に指定されている7つの組み込みウィジェットを使用します-
- 容器
- 拡大
- Row
- カラム
- Card
- Text
- 画像
_ProductBox_は、上記のウィジェットを使用して設計されています。 ウィジェットの配置または階層は、以下に示す図で指定されています-
- さて、アプリケーションのassetsフォルダに製品情報のダミー画像(以下を参照)を配置し、以下に示すようにpubspec.yamlファイルでassetsフォルダを設定します-
assets:
- assets/appimages/floppy.png
- assets/appimages/iphone.png
- assets/appimages/laptop.png
- assets/appimages/pendrive.png
- assets/appimages/pixel.png
- assets/appimages/tablet.png
iPhone.png
Pixel.png
Laptop.png
Tablet.png
Pendrive.png
Floppy.png
最後に、以下に指定されているように、_MyHomePage_ウィジェットで_ProductBox_ウィジェットを使用します-
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title:Text("Product Listing")),
body: ListView(
shrinkWrap: true, padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0),
children: <Widget> [
ProductBox(
name: "iPhone",
description: "iPhone is the stylist phone ever",
price: 1000,
image: "iphone.png"
),
ProductBox(
name: "Pixel",
description: "Pixel is the most featureful phone ever",
price: 800,
image: "pixel.png"
),
ProductBox(
name: "Laptop",
description: "Laptop is most productive development tool",
price: 2000,
image: "laptop.png"
),
ProductBox(
name: "Tablet",
description: "Tablet is the most useful device ever for meeting",
price: 1500,
image: "tablet.png"
),
ProductBox(
name: "Pendrive",
description: "Pendrive is useful storage medium",
price: 100,
image: "pendrive.png"
),
ProductBox(
name: "Floppy Drive",
description: "Floppy drive is useful rescue storage medium",
price: 20,
image: "floppy.png"
),
],
)
);
}
}
- ここでは、_ListView_ウィジェットの子として_ProductBox_を使用しました。
- 製品レイアウトアプリケーション_(product_layout_app)の完全なコード(main.dart)_は次のとおりです-
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
//This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo', theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Product layout demo home page'),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Product Listing")),
body: ListView(
shrinkWrap: true,
padding: const EdgeInsets.fromLTRB(2.0, 10.0, 2.0, 10.0),
children: <Widget>[
ProductBox(
name: "iPhone",
description: "iPhone is the stylist phone ever",
price: 1000,
image: "iphone.png"
),
ProductBox(
name: "Pixel",
description: "Pixel is the most featureful phone ever",
price: 800,
image: "pixel.png"
),
ProductBox(
name: "Laptop",
description: "Laptop is most productive development tool",
price: 2000,
image: "laptop.png"
),
ProductBox(
name: "Tablet",
description: "Tablet is the most useful device ever for meeting",
price: 1500,
image: "tablet.png"
),
ProductBox(
name: "Pendrive",
description: "Pendrive is useful storage medium",
price: 100,
image: "pendrive.png"
),
ProductBox(
name: "Floppy Drive",
description: "Floppy drive is useful rescue storage medium",
price: 20,
image: "floppy.png"
),
],
)
);
}
}
class ProductBox extends StatelessWidget {
ProductBox({Key key, this.name, this.description, this.price, this.image}) :
super(key: key);
final String name;
final String description;
final int price;
final String image;
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(2),
height: 120,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Image.asset("assets/appimages/" + image),
Expanded(
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
this.name, style: TextStyle(
fontWeight: FontWeight.bold
)
),
Text(this.description), Text(
"Price: " + this.price.toString()
),
],
)
)
)
]
)
)
);
}
}
アプリケーションの最終的な出力は次のとおりです-