Flutter-레이아웃 소개
Flutter 의 핵심 개념 은 Everything is widget 이므로 Flutter 는 사용자 인터페이스 레이아웃 기능을 위젯 자체에 통합합니다. Flutter 는 사용자 인터페이스를 레이아웃하기위한 목적으로 만 Container, Center, Align 등과 같이 특별히 디자인 된 많은 위젯을 제공합니다. 다른 위젯을 구성하여 빌드하는 위젯은 일반적으로 레이아웃 위젯을 사용합니다. 이 장에서 Flutter 레이아웃 개념을 배우십시오 .
레이아웃 위젯 유형
레이아웃 위젯은 자식을 기준으로 두 개의 별개 카테고리로 그룹화 할 수 있습니다.
- 한 자녀를 지원하는 위젯
- 여러 자녀를 지원하는 위젯
다음 섹션에서 위젯 유형과 기능에 대해 알아 보겠습니다.
단일 자식 위젯
이 범주에서 위젯은 자식으로 하나의 위젯 만 가지며 모든 위젯에는 특별한 레이아웃 기능이 있습니다.
예를 들어 Center 위젯은 상위 위젯과 관련하여 하위 위젯을 중앙 에 배치 하고 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)
),
),
);
}
}
여기에서는 컨테이너 위젯과 텍스트 위젯 이라는 두 가지 위젯을 사용했습니다 . 위젯의 결과는 아래와 같이 사용자 정의 버튼입니다.
우리가 제공하는 가장 중요한 하나의 아이의 레이아웃 위젯의 일부를 확인하자 플러터를 -
Padding− 주어진 패딩으로 자식 위젯을 정렬하는 데 사용됩니다. 여기서 패딩은 EdgeInsets 클래스에서 제공 할 수 있습니다 .
Align− 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
Baseline
FractinallySizedBox
IntrinsicHeight
IntrinsicWidth
LiimitedBox
OffStage
OverflowBox
SizedBox
SizedOverflowBox
Transform
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,
),
)
);
}
}
여기,
컨테이너 위젯은 최상위 또는 루트 위젯입니다. 컨테이너 는 내용을 레이아웃하기 위해 장식 및 패딩 속성을 사용하여 구성 됩니다.
BoxDecoration 은 컨테이너 위젯 을 꾸미기위한 색상, 테두리 등의 많은 속성을 가지고 있으며 여기서 색상 은 컨테이너의 색상을 설정하는 데 사용됩니다.
패딩 의 컨테이너 를 사용하여 설정 한 위젯 dgeInsets의 패딩 값을 지정하는 옵션을 제공합니다 클래스를.
Center 는 컨테이너 위젯 의 하위 위젯입니다 . 다시 말하지만 Text 는 Center 위젯 의 자식입니다 . 텍스트 는 메시지를 표시하는 데 사용되며 Center 는 상위 위젯 인 Container에 대해 텍스트 메시지를 중앙에 배치하는 데 사용됩니다 .
위에 주어진 코드의 최종 결과는 아래와 같은 레이아웃 샘플입니다.
여러 하위 위젯
이 카테고리에서 주어진 위젯은 둘 이상의 하위 위젯을 가지며 각 위젯의 레이아웃은 고유합니다.
예를 들어 행 위젯은 자식을 가로 방향으로 배치 할 수있는 반면 열 위젯은 자식을 세로 방향으로 배치 할 수 있습니다. Row 및 Column 을 구성 하여 모든 수준의 복잡성을 가진 위젯을 구축 할 수 있습니다.
이 섹션에서 자주 사용되는 위젯에 대해 알아 보겠습니다.
Row − 자식을 수평으로 배열 할 수 있습니다.
Column − 자식을 수직으로 배열 할 수 있습니다.
ListView − 자식을 목록으로 정렬 할 수 있습니다.
GridView − 자녀를 갤러리로 정렬 할 수 있습니다.
Expanded − 행 및 열 위젯의 자식이 가능한 최대 영역을 차지하도록 만드는 데 사용됩니다.
Table − 테이블 기반 위젯.
Flow − 흐름 기반 위젯.
Stack − 스택 기반 위젯.
고급 레이아웃 애플리케이션
이 섹션에서는 단일 및 다중 하위 레이아웃 위젯을 모두 사용하여 맞춤형 디자인 으로 제품 목록 의 복잡한 사용자 인터페이스를 만드는 방법을 알아 보겠습니다 .
이를 위해 아래 주어진 순서를 따르십시오.
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', )),
);
}
}
Here,
기본 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 개의 인수를 사용했습니다.
이름-제품 이름
설명-제품 설명
가격-제품 가격
image-제품 이미지
ProductBox 는 아래에 지정된대로 7 개의 내장 위젯을 사용합니다.
- Container
- Expanded
- Row
- Column
- Card
- Text
- Image
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
마지막으로, 사용 ProductBox는 에 위젯 MyHomePage 아래에 지정된 위젯 -
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"
),
],
)
);
}
}
여기에서는 ProductBox 를 ListView 위젯의 자식으로 사용했습니다 .
제품 레이아웃 애플리케이션 (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()
),
],
)
)
)
]
)
)
);
}
}
응용 프로그램의 최종 출력은 다음과 같습니다.