Flutter: RelativeLayout

How to design RelativeLayout in Flutter

Yudi Setiawan
Nusanet Developers
7 min readDec 22, 2018

--

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.

Goal 1

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.

Widget Stack polanya menumpuk

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.

Goal 2

Untuk lebih jelasnya analisis dari goal 2 seperti berikut.

Analisis Goal 2

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.

Hapus widget Expanded Row Root Kiri

Sekarang coba jalankan maka, outputnya seperti berikut.

Output hapus wiget Expanded Row Root Kiri

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.

Buat rata kiri widget Column pembungkus Text Top Left dan Text Top Left 2
Text Top Left dan Text Top Left 2 sudah rata kiri

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.

Perbaikan widget Text Center Left menjadi ditengah dan sebelah kiri layar

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.

Penambahan widget Text Top Center 3

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.

Perbaikan widget Text Center menjadi ditengah-tengah layar

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.

--

--