Flutter - wprowadzenie do układów
Ponieważ podstawową koncepcją Fluttera jest wszystko jest widgetem , Flutter włącza funkcjonalność układu interfejsu użytkownika do samych widżetów. Flutter zapewnia sporo specjalnie zaprojektowanych widżetów, takich jak Container, Center, Align itp., Tylko w celu rozplanowania interfejsu użytkownika. Widżety tworzone przez komponowanie innych widżetów zwykle używają widżetów układu. Nauczmy się koncepcji układu Flutter w tym rozdziale.
Typ widżetów układu
Widżety układu można podzielić na dwie odrębne kategorie na podstawie ich elementów podrzędnych -
- Widget wspierający jedno dziecko
- Widget obsługujący wiele dzieci
W kolejnych sekcjach poznajmy zarówno rodzaje widżetów, jak i ich funkcjonalność.
Pojedyncze widżety dla dzieci
W tej kategorii widżety będą miały tylko jeden widżet jako dziecko, a każdy widżet będzie miał specjalną funkcjonalność układu.
Na przykład widżet Centrum po prostu wyśrodkowuje widżet podrzędny w odniesieniu do widżetu nadrzędnego, a widżet Kontener zapewnia pełną elastyczność umieszczania go podrzędnego w dowolnym miejscu wewnątrz przy użyciu różnych opcji, takich jak dopełnienie, dekoracja itp.
Pojedyncze widżety podrzędne to świetne opcje tworzenia wysokiej jakości widgetów posiadających jedną funkcjonalność, taką jak przycisk, etykieta itp.,
Kod do utworzenia prostego przycisku za pomocą widżetu Kontener wygląda następująco:
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)
),
),
);
}
}
Tutaj użyliśmy dwóch widżetów - widżetu Kontener i widżetu Tekst . Efektem działania widżetu jest niestandardowy przycisk, jak pokazano poniżej -
Sprawdźmy niektóre z najważniejszych widżetów układu podrzędnego dostarczonych przez Flutter -
Padding- Służy do układania widgetu podrzędnego według podanego wypełnienia. W tym przypadku dopełnienie może zapewnić klasa EdgeInsets .
Align- Wyrównaj widżet podrzędny w sobie, używając wartości właściwości wyrównania . Wartość właściwości wyrównania można podać w klasie FractionalOffset . FractionalOffset klasa określa przesunięć pod względem odległości od lewego górnego.
Niektóre z możliwych wartości przesunięć są następujące -
FractionalOffset (1,0, 0,0) reprezentuje prawy górny róg.
FractionalOffset (0,0, 1,0) reprezentuje lewy dolny róg.
Przykładowy kod dotyczący przesunięć pokazano poniżej -
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 - Skaluje widżet podrzędny, a następnie ustawia go zgodnie z określonym dopasowaniem.
AspectRatio - Próbuje dopasować widżet podrzędny do określonego współczynnika proporcji
ConstrainedBox
Baseline
FractinallySizedBox
IntrinsicHeight
IntrinsicWidth
LiimitedBox
OffStage
OverflowBox
SizedBox
SizedOverflowBox
Transform
CustomSingleChildLayout
Nasza aplikacja Hello world wykorzystuje do projektowania strony głównej widżety układu oparte na materiałach. Zmodyfikujmy naszą aplikację hello world, aby zbudować stronę główną przy użyciu podstawowych widżetów układu, jak określono poniżej -
Container - Ogólny widżet kontenera oparty na jednym podrzędnym polu z wyrównaniem, dopełnieniem, obramowaniem i marginesem, a także bogate funkcje stylizacji.
Center - Prosty, pojedynczy widżet kontenera podrzędnego, który wyśrodkowuje widget podrzędny.
Zmodyfikowany kod MyHomePage i MojaApl widżet jest poniżej -
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,
),
)
);
}
}
Tutaj,
Widżet kontenera to widget najwyższego poziomu lub widget główny. Kontener jest konfigurowany przy użyciu właściwości dekoracji i dopełnienia w celu rozmieszczenia zawartości.
BoxDecoration ma wiele właściwości, takich jak kolor, obramowanie itp., Które służą do ozdabiania widżetu Pojemnik, a tutaj kolor służy do ustawiania koloru pojemnika.
wyściółka z Container widżet jest ustawiony za pomocą dgeInsets klasę, która zapewnia możliwość określenia wartości dopełnienia.
Centrum to widget podrzędny widżetu Kontener . Ponownie, tekst jest elementem podrzędnym widżetu Centrum . Tekst jest używany do wyświetlania wiadomości, a Środek służy do wyśrodkowania wiadomości tekstowej w odniesieniu do widżetu nadrzędnego Kontener .
Ostatecznym wynikiem powyższego kodu jest przykład układu, jak pokazano poniżej -
Wiele widżetów podrzędnych
W tej kategorii dany widżet będzie miał więcej niż jeden widżet podrzędny, a układ każdego widżetu jest niepowtarzalny.
Na przykład widżet Wiersz umożliwia układanie swoich elementów podrzędnych w kierunku poziomym, natomiast widżet Kolumna umożliwia układanie swoich elementów podrzędnych w kierunku pionowym. Komponując wiersz i kolumnę , można zbudować widget o dowolnym poziomie złożoności.
Poznajmy niektóre z często używanych widżetów w tej sekcji.
Row - Pozwala ustawić swoje dzieci w poziomie.
Column - Pozwala ustawić swoje dzieci w pionie.
ListView - Pozwala uporządkować swoje dzieci jako listę.
GridView - Pozwala ustawić swoje dzieci jako galerię.
Expanded - Służy do tego, aby elementy podrzędne widżetu Row and Column zajmowały maksymalny możliwy obszar.
Table - Widżet oparty na tabeli.
Flow - Widżet oparty na przepływie.
Stack - Widżet oparty na stosie.
Zaawansowana aplikacja układu
W tej sekcji dowiemy się, jak utworzyć złożony interfejs użytkownika z listą produktów z niestandardowym projektem przy użyciu zarówno jednego, jak i wielu widżetów układu podrzędnego.
W tym celu postępuj zgodnie z kolejnością podaną poniżej -
Utwórz nową aplikację Flutter w Android Studio, product_layout_app .
Zastąp kod main.dart następującym kodem -
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,
Stworzyliśmy widżet MyHomePage , rozszerzając StatelessWidget zamiast domyślnego StatefulWidget, a następnie usunęliśmy odpowiedni kod.
Teraz utwórz nowy widżet ProductBox zgodnie z określonym projektem, jak pokazano poniżej -
Kod produktu ProductBox jest następujący.
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()),
],
)
)
)
]
)
)
);
}
}
W kodzie należy przestrzegać następujących wskazówek -
ProductBox użył czterech argumentów, jak określono poniżej -
name - nazwa produktu
description - opis produktu
cena - cena produktu
image - zdjęcie produktu
ProductBox wykorzystuje siedem wbudowanych widżetów, jak określono poniżej -
- Container
- Expanded
- Row
- Column
- Card
- Text
- Image
ProductBox został zaprojektowany przy użyciu wyżej wymienionego widgetu. Rozmieszczenie lub hierarchię widżetu określa poniższy diagram -
Teraz umieść fikcyjny obraz (patrz poniżej) w celu uzyskania informacji o produkcie w folderze zasobów aplikacji i skonfiguruj folder zasobów w pliku pubspec.yaml, jak pokazano poniżej -
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
Wreszcie, należy użyć ProductBox widget w MyHomePage widget, jak określono poniżej -
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"
),
],
)
);
}
}
Tutaj użyliśmy ProductBox jako elementów podrzędnych widżetu ListView .
Pełny kod (main.dart) aplikacji układu produktu (product_layout_app) wygląda następująco -
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()
),
],
)
)
)
]
)
)
);
}
}
Końcowy wynik aplikacji jest następujący -