Flutter: RelativeLayout
How to design RelativeLayout in Flutter
Series
Di Android, ada RelativeLayout dimana, susunan layout-nya disusun secara relatif berdasarkan screen dan view lain. Lalu, di Flutter kita juga bisa membuat layout layaknya RelativeLayout di Android. Caranya ialah dengan menggabungkan widget-widget layout yang ada di Flutter. Jadi, pada artikel ini kita akan mempelajari bagaimana cara kerja dari widget Stack
dan Align
. Namun, sebelum kita memulai artikel ini sangat saya sarankan buat kita semua untuk membaca terlebih dahulu artikel saya sebelumnya yang membahas tentang Flutter: LinearLayout namun, jika kita sudah paham cara kerja dari widget Row
, Column
, Container
, dan Expanded
maka, nggak perlu baca artikel saya sebelumnya pun juga nggak apa-apa.
Stack
Widget ini berfungsi untuk membuat layout dengan pola stack atau menimpa.
Align
Widget ini berfungsi untuk membuat layout dengan cara menyusunnya secara relatif seperti di RelativeLayout.
Goal 1
Untuk goal pertama, kita akan buat aplikasi dengan tampilan seperti berikut.
Di Android, untuk membuat layout seperti diatas kita bisa menggunakan RelativeLayout dengan mudah. Di Flutter, kita juga bisa membuatnya dan ada banyak caranya namun, pada artikel ini saya cuma memberikan 2 cara saja ya.
Stack and Align
Cara pertama, kita bisa gunakan widget Stack
dan Align
seperti berikut.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(
title: Text(
"RelativeLayout",
),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.topLeft,
child: Text(
"Top Left",
),
),
Align(
alignment: Alignment.topCenter,
child: Text(
"Top Center",
),
),
Align(
alignment: Alignment.topRight,
child: Text(
"Top Right",
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
"Center Left",
),
),
Align(
alignment: Alignment.center,
child: Text(
"Center",
),
),
Align(
alignment: Alignment.centerRight,
child: Text(
"Center Right",
),
),
Align(
alignment: Alignment.bottomLeft,
child: Text(
"Bottom Left",
),
),
Align(
alignment: Alignment.bottomCenter,
child: Text(
"Bottom Center",
),
),
Align(
alignment: Alignment.bottomRight,
child: Text(
"Bottom Right",
),
),
],
),
),
),
);
}
}
Pada kode diatas bisa kita lihat bahwa widget Align
memiliki attribute yang hampir mirip seperti di RelativeLayout di Android. Dan widget Stack
berfungsi sebagai penampung dari widget Align
dimana, Stack
polanya adalah menyusun layout-nya secara tertimpa atau menumpuk. Jadi, sebenarnya semua child yang didalam widget Stack
tidak saling berkaitan antara satu dengan yang lainnya. Kalau tidak percaya coba kita buat agar widget Text
dengan label “Top Left” bisa ditimpa oleh widget lain.
Row, Column, Padding, and Expanded
Sama seperti pada artikel sebelumnya kita masih bisa menggunakan perpaduan antara widget Row
, Column
, dan Expanded
lalu, kita juga ganti penggunaan widget Container
dengan Padding
. Berikut kode untuk membuatnya tampilan yang sama seperti sebelumnya namun berbeda kodenya.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(
title: Text(
"RelativeLayout",
),
),
body: Container(
padding: const EdgeInsets.all(16),
child: Row(
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Top Left",
),
Text(
"Center Left",
),
Text(
"Bottom Left",
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"Top Center",
),
Text(
"Center",
),
Text(
"Bottom Center",
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
"Top Right",
),
Text(
"Center Right",
),
Text(
"Bottom Right",
),
],
),
)
],
),
),
),
);
}
}
Sekarang coba jalankan kedua kode kita yang sebelumnya tadi maka, kita akan mendapatkan output yang sama.
Di Flutter triknya adalah kita menggunakan widget sesuai kebutuhan kita. Misal, kita cuma mau menambahkan padding maka, kita gunakan saja widget Padding
Goal 2
Di goal kedua kita coba membuat tampilan seperti berikut.
Untuk lebih jelasnya analisis dari goal 2 seperti berikut.
Perhatikan baik-baik pada layout goal 2 dimana, Column
yang paling kiri itu kita tidak menggunakan Expanded
sehingga layout-nya menjadi wrap_content
namun, pada Text
dengan label Top Left dan Top Left 2 kita beri attribute CrossAxisAlignment.start
sehingga posisi dari kedua Text
tersebut berada di sebelah kiri. Lalu, pada Text
dengan label Center Left itu posisi-nya berada di sebelah kiri dari screen bukan dari Column
. Selanjutnya, pada widget Text
dengan label Top Center dan Top Center 3 itu kita masukkan dia lagi kedalam widget Column
sehingga dia mempunyai penampung-nya tersendiri dan berbeda dengan widget Text
Bottom Center. Lalu, untuk widget Text
dengan label Center Screen itu berada ditengah-tengah screen bukan ditengah-tengah Column
.
Sekarang mari kita buat secara bertahap layout pada goal 2. Kita masih menggunakan codingan yang sama seperti sebelumnya. Sebelum-nya silakan kita tambah key pada setiap widget
di layout kita sebelumnya agar saya lebih gampang memberikan arahannya secara bertahap nanti.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(
title: Text(
"RelativeLayout",
),
),
body: Container(
key: Key("Root"),
padding: const EdgeInsets.all(16),
child: Row(
key: Key("Row Root"),
children: <Widget>[
Expanded(
key: Key("Expanded Row Root Kiri"),
child: Column(
key: Key("Column Expanded Row Root Kiri"),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Top Left",
key: Key("Text Top Left"),
),
Text(
"Center Left",
key: Key("Text Center Left"),
),
Text(
"Bottom Left",
key: Key("Text Bottom Left"),
),
],
),
),
Expanded(
key: Key("Expanded Row Root Tengah"),
child: Column(
key: Key("Column Expanded Row Root Tengah"),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"Top Center",
key: Key("Text Top Center"),
),
Text(
"Center",
key: Key("Text Center"),
),
Text(
"Bottom Center",
key: Key("Text Bottom Center"),
),
],
),
),
Expanded(
key: Key("Expanded Row Root Kanan"),
child: Column(
key: Key("Column Expanded Row Root Kanan"),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
"Top Right",
key: Key("Text Top Right"),
),
Text(
"Center Right",
key: Key("Text Center Right"),
),
Text(
"Bottom Right",
key: Key("Text Bottom Right"),
),
],
),
)
],
),
),
),
);
}
}
Sekarang mari kita ubah agar widget dengan key Expanded Row Root Kiri
menjadi wrap_content
size-nya dengan cara hapus widget Expanded
tersebut. Caranya seperti berikut.
Sekarang coba jalankan maka, outputnya seperti berikut.
Bisa kita lihat hasil dari inspector layout-nya bahwa sekarang sudah wrap_content
size-nya. Sekarang mari kita lanjutkan dengan cara menambahkan widget Text
dengan label Top Left 2. Sebelum kita mengubahnya mari saya ajak untuk menganalisanya dimana, untuk bisa menambahkan widget Text
dengan label Top Left 2 bisa berada dibawah dari widget Text
Top Left maka, kita perlu membungkus kedua widget tersebut kedalam widget Column
seperti berikut.
Sekarang coba jalankan lagi maka, outputnya seperti berikut.
Sekarang sudah kita tambah widget Top Left 2 namun, posisinya tidak rata kiri. Tinggal kita tambahkan attribute CrossAxisAlignment.start
pada widget Column
yang barusan kita tambahkan tadi.
Oops… perhatikan baik-baik pada widget Text Center Left
kok jadi tidak berada ditengah-tengah gitu ya??? 🤔 Berdasarkan hasil analisa saya penyebabnya adalah karena, kita barusan saja menambahkan widget Text
Top Left 2 sehingga posisi dari widget Text Center Left
menjadi tergeser kebawah dan penyebab lainnya bisa tergeser seperti itu ialah karena kita diawal kan sudah menggunakan attribute MainAxisAlignment.spaceBetween
. Ok, sekarang kita perbaiki ya dengan cara mengeluarkan widget Text Center Left
dari widget Column Expanded Row Root Kiri
dan kita masukkan kedalam widget Stack
. Berikut caranya.
Berikut outputnya.
Langkah berikutnya, coba kita tambahkan widget Text
Top Center 3. Analisanya ialah kita harus membungkus widget Text Top Center
dan Text
Top Center 3 kedalam widget Column
.
Coba jalankan lagi maka, sekarang outputnya menjadi seperti berikut.
Eh, tapi sepertinya widget Text Center
kok jadi tidak ditengah-tengah layar gitu. Sama case-nya seperti pada widget Text Center Left
dimana, widget ini bergeser gara-gara kita baru saja menambah widget Text
Top Center 3. Jadi, solusinya adalah kita keluarkan saja widget Text Center
dari widget Column Expanded Row Root Tengah
dan kita masukkan kedalam widget Alignment
seperti berikut.
Dan berikut outputnya.
Kesimpulan
Jadi, setelah kita mempelajari bagaimana cara membuat RelativeLayout seperti di Android pada Flutter saya rasa cukup jelas bahwa tidak ada keterbatasan layout di Flutter sehingga layout apapun yang bisa dibuat di Android maka, bisa dibuat di Flutter.