1. Pengantar
Komponen Material (MDC) membantu developer menerapkan Desain Material. Dibuat oleh tim engineer dan desainer UX di Google, MDC memiliki banyak komponen UI yang indah dan fungsional serta tersedia untuk Android, iOS, web, dan Flutter.material.io/develop |
Kini Anda dapat menggunakan MDC untuk lebih menyesuaikan gaya unik aplikasi Anda. Ekspansi yang baru-baru ini dilakukan oleh Desain Material meningkatkan fleksibilitas desainer dan developer untuk mengekspresikan merek produk mereka.
Dalam codelab MDC-101 dan MDC-102, Anda menggunakan Komponen Material (MDC) untuk membangun dasar-dasar aplikasi bernama Shrine, sebuah aplikasi e-commerce yang menjual pakaian serta perlengkapan rumah. Aplikasi ini berisi alur penggunaan yang dimulai dengan layar login, kemudian mengarahkan pengguna ke layar utama yang menampilkan produk.
Yang akan Anda buat
Dalam codelab ini, Anda akan menyesuaikan aplikasi Shrine menggunakan:
- Warna
- Tipografi
- Ketinggian
- Bentuk
- Tata Letak
Android | iOS |
Komponen dan subsistem MDC-Flutter di codelab ini
- Tema
- Tipografi
- Ketinggian
- Daftar gambar
Bagaimana Anda menilai tingkat pengalaman Anda menggunakan pengembangan Flutter?
2. Menyiapkan lingkungan pengembangan Flutter Anda
Anda memerlukan dua software untuk menyelesaikan lab ini—Flutter SDK dan editor.
Anda dapat menjalankan codelab menggunakan salah satu perangkat berikut:
- Perangkat Android atau iOS fisik yang terhubung ke komputer dan disetel ke mode Developer.
- Simulator iOS (perlu menginstal alat Xcode).
- Android Emulator (memerlukan penyiapan di Android Studio).
- Browser (Chrome diperlukan untuk proses debug).
- Aplikasi desktop Windows, Linux, atau macOS. Anda harus melakukan pengembangan di platform tempat Anda berencana men-deploy aplikasi. Jadi, jika ingin mengembangkan aplikasi desktop Windows, Anda harus mengembangkannya di Windows untuk mengakses rantai build yang sesuai. Ada persyaratan spesifik per sistem operasi yang dibahas secara mendetail di docs.flutter.dev/desktop.
3. Mendownload aplikasi awal codelab
Melanjutkan dari MDC-102?
Jika Anda sudah menyelesaikan MDC-102, kode Anda seharusnya siap untuk codelab ini. Lewati ke langkah: Mengubah warna.
Memulai dari awal?
Mendownload aplikasi codelab awal
Aplikasi awal terletak di direktori material-components-flutter-codelabs-103-starter_and_102-complete/mdc_100_series
.
...atau meng-clone codelab dari GitHub
Untuk meng-clone codelab ini dari GitHub, jalankan perintah berikut:
git clone https://github.com/material-components/material-components-flutter-codelabs.git cd material-components-flutter-codelabs/mdc_100_series git checkout 103-starter_and_102-complete
Membuka project dan menjalankan aplikasi
- Buka project di editor pilihan Anda.
- Ikuti petunjuk untuk "Run the app" (Jalankan aplikasi) di Get Started: Test drive pada editor pilihan Anda.
Berhasil! Anda akan melihat halaman login Shrine dari codelab sebelumnya di perangkat Anda.
Android | iOS |
Klik "Next" untuk melihat halaman beranda dari codelab sebelumnya.
Android | iOS |
4. Mengubah warna
Skema warna yang merepresentasikan merek Shrine telah dibuat, dan desainer ingin Anda mengimplementasikan skema warna tersebut ke aplikasi Shrine
Untuk memulai, mari kita impor warna tersebut ke project kita.
Membuat colors.dart
Buat file dart baru di lib
bernama colors.dart
. Impor Komponen Material dan tambahkan nilai const Color:
import 'package:flutter/material.dart';
const kShrinePink50 = Color(0xFFFEEAE6);
const kShrinePink100 = Color(0xFFFEDBD0);
const kShrinePink300 = Color(0xFFFBB8AC);
const kShrinePink400 = Color(0xFFEAA4A4);
const kShrineBrown900 = Color(0xFF442B2D);
const kShrineErrorRed = Color(0xFFC5032B);
const kShrineSurfaceWhite = Color(0xFFFFFBFA);
const kShrineBackgroundWhite = Colors.white;
Palet warna kustom
Tema warna ini telah dibuat oleh desainer dengan warna kustom (ditampilkan di gambar di bawah). Tema warna ini berisi warna yang telah dipilih dari merek Shrine dan diterapkan ke Material Theme Editor, yang telah memperluasnya untuk membuat palet yang lebih lengkap. (Warna ini bukan dari palet warna Material 2014.)
Material Theme Editor telah mengatur warna-warna tersebut menjadi shade yang diberi label secara numerik, meliputi label 50, 100, 200, .... hingga 900 untuk setiap warna. Shrine hanya menggunakan shade 50, 100, dan 300 dari swatch merah muda dan 900 dari swatch cokelat.
Setiap parameter widget berwarna dipetakan ke warna dari skema ini. Misalnya, warna untuk dekorasi kolom teks ketika menerima input secara aktif harus berupa Warna primer tema. Jika warna tersebut tidak dapat diakses (mudah dilihat pada latar belakangnya), gunakan PrimaryVariant sebagai gantinya.
Variasi ini dibuat untuk Pedoman Material 2014 dan masih tersedia di pedoman (artikel Color System ) dan MDC-Flutter saat ini. Untuk mengaksesnya dalam kode, cukup panggil warna dasar kemudian shade-nya (umumnya nilai ratusan). Misalnya, Merah Muda 400 diambil dengan perintah: Colors.pink[400]
.
Anda dapat menggunakan palet ini untuk desain dan kode Anda. Jika sudah memiliki warna yang spesifik untuk merek Anda, Anda dapat membuat palet harmonis Anda sendiri menggunakan alat pembuatan palet atau Material Theme Editor.
Setelah memiliki warna yang ingin digunakan, kita dapat menerapkannya ke UI. Kita akan melakukan ini dengan menyetel nilai widget ThemeData yang kita terapkan ke instance MaterialApp di bagian atas hierarki widget kita.
Menyesuaikan ThemeData.light()
Flutter menyertakan beberapa tema bawaan. Salah satunya adalah tema terang. Kita akan menyalin tema terang dan mengubah nilainya agar sesuai untuk aplikasi kita, bukan membuat widget ThemeData dari awal.
Mari kita impor colors.dart
di app.dart.
import 'colors.dart';
Kemudian, tambahkan hal berikut ke app.dart di luar cakupan class ShrineApp:
// TODO: Build a Shrine Theme (103)
final ThemeData _kShrineTheme = _buildShrineTheme();
ThemeData _buildShrineTheme() {
final ThemeData base = ThemeData.light();
return base.copyWith(
colorScheme: base.colorScheme.copyWith(
primary: kShrinePink100,
onPrimary: kShrineBrown900,
secondary: kShrineBrown900,
error: kShrineErrorRed,
),
// TODO: Add the text themes (103)
// TODO: Add the icon themes (103)
// TODO: Decorate the inputs (103)
);
}
Sekarang, tetapkan theme:
di bagian akhir fungsi build()
ShrineApp (di widget MaterialApp) agar menjadi tema baru kita:
// TODO: Add a theme (103)
theme: _kShrineTheme, // New code
Simpan project Anda. Layar login Anda sekarang akan terlihat seperti ini:
Android | iOS |
Dan layar utama Anda akan terlihat seperti ini:
Android | iOS |
5. Mengubah gaya label dan tipografi
Selain perubahan warna, desainer juga telah memberi kita tipografi spesifik untuk digunakan. ThemeData Flutter mencakup 3 tema teks. Setiap tema teks adalah koleksi gaya teks, seperti "headline" dan "title". Kita akan menggunakan beberapa gaya untuk aplikasi kita dan mengubah beberapa nilainya.
Menyesuaikan tema teks
Untuk mengimpor font ke project, font harus ditambahkan ke file pubspec.yaml.
Di pubspec.yaml, tambahkan kode berikut langsung setelah tag flutter:
:
# TODO: Insert Fonts (103)
fonts:
- family: Rubik
fonts:
- asset: fonts/Rubik-Regular.ttf
- asset: fonts/Rubik-Medium.ttf
weight: 500
Sekarang Anda dapat mengakses dan menggunakan font Rubik.
Memecahkan masalah file pubspec
Anda mungkin mengalami error saat menjalankan pub get jika Anda memotong dan menempel deklarasi di atas. Jika Anda mengalami error, mulai dengan menghapus spasi kosong di awal dan menggantinya dengan indentasi 2 spasi. (Dua spasi sebelumnya
fonts:
, empat spasi sebelumnya
family: Rubik
, dan seterusnya.)
Jika Anda melihat Mapping values are not allowed here, periksa indentasi baris yang memiliki masalah dan indentasi baris di atasnya.
Di login.dart
, ubah kode berikut di dalam Column()
:
Column(
children: <Widget>[
Image.asset('assets/diamond.png'),
const SizedBox(height: 16.0),
Text(
'SHRINE',
style: Theme.of(context).textTheme.headline5,
),
],
)
Di app.dart
, tambahkan kode berikut setelah _buildShrineTheme()
:
// TODO: Build a Shrine Text Theme (103)
TextTheme _buildShrineTextTheme(TextTheme base) {
return base.copyWith(
headline5: base.headline5!.copyWith(
fontWeight: FontWeight.w500,
),
headline6: base.headline6!.copyWith(
fontSize: 18.0,
),
caption: base.caption!.copyWith(
fontWeight: FontWeight.w400,
fontSize: 14.0,
),
bodyText1: base.bodyText1!.copyWith(
fontWeight: FontWeight.w500,
fontSize: 16.0,
),
).apply(
fontFamily: 'Rubik',
displayColor: kShrineBrown900,
bodyColor: kShrineBrown900,
);
}
Tindakan ini mengambil TextTheme dan mengubah tampilan headline, judul, dan teks.
Menerapkan fontFamily
dengan cara ini akan menerapkan perubahan hanya ke nilai skala tipografi yang ditentukan di copyWith()
(judul utama, judul, teks).
Untuk beberapa font, kita menyetel fontWeight kustom dalam kelipatan 100: w500 (ketebalan 500) sesuai dengan medium dan w400 sesuai dengan reguler.
Menggunakan tema teks baru
Tambahkan tema berikut ke _buildShrineTheme
setelah error:
// TODO: Add the text themes (103)
textTheme: _buildShrineTextTheme(base.textTheme),
textSelectionTheme: const TextSelectionThemeData(
selectionColor: kShrinePink100,
),
Simpan project Anda. Kali ini, mulai ulang juga aplikasi (dikenal sebagai Hot Restart), karena kita mengubah font.
Android | iOS |
Teks di layar utama dan layar login terlihat berbeda—beberapa teks menggunakan font Rubik, dan teks lainnya dirender dengan warna cokelat, bukan hitam atau putih. Ikon juga dirender dengan warna cokelat.
Menyusutkan teks
Labelnya sedikit terlalu besar.
Di home.dart
, ubah children:
dari Column terdalam:
// TODO: Change innermost Column (103)
children: <Widget>[
// TODO: Handle overflowing labels (103)
Text(
product.name,
style: theme.textTheme.button,
softWrap: false,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
const SizedBox(height: 4.0),
Text(
formatter.format(product.price),
style: theme.textTheme.caption,
),
// End new code
],
Menempatkan teks di tengah bawah
Kita ingin menempatkan label di tengah, dan meratakan teks ke bagian bawah setiap kartu, bukan ke bagian bawah setiap gambar.
Pindahkan label ke akhir (bawah) sumbu utama dan ubah ke posisi tengah:
// TODO: Align labels to the bottom and center (103)
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
Simpan project Anda.
Android | iOS |
Ubahan ini membuat halaman terlihat jauh lebih baik.
Memberi tema kolom teks
Anda juga dapat memberi tema dekorasi di kolom teks dengan InputDecorationTheme.
Di app.dart
, di metode _buildShrineTheme()
, tentukan nilai inputDecorationTheme:
:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
),
Saat ini, kolom teks memiliki dekorasi filled
. Mari kita hapus. Menghapus filled
dan menentukan inputDecorationTheme
akan memberikan gaya garis batas untuk kolom teks.
Di login.dart
, hapus nilai filled: true
:
// Remove filled: true values (103)
TextField(
controller: _usernameController,
decoration: const InputDecoration(
// Removed filled: true
labelText: 'Username',
),
),
const SizedBox(height: 12.0),
TextField(
controller: _passwordController,
decoration: const InputDecoration(
// Removed filled: true
labelText: 'Password',
),
obscureText: true,
),
Hot restart. Layar login Anda akan terlihat seperti ini ketika kolom Username aktif (saat Anda mengetik di kolom tersebut):
Android | iOS |
Ketik di dalam kolom teks—batas dan label mengambang akan dirender dengan warna primer. Tetapi kita tidak dapat melihatnya dengan mudah. Teks tersebut tidak dapat diakses bagi orang yang kesulitan membedakan piksel dan tidak memiliki kontras warna yang cukup. (Untuk mengetahui informasi selengkapnya, lihat "Warna yang tersedia" di artikel tentang Warna Pedoman Material.)
Di app.dart
, tentukan focusedBorder:
di bawah inputDecorationTheme:
:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
),
Selanjutnya, tentukan floatingLabelStyle:
di bawah inputDecorationTheme:
:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
floatingLabelStyle: TextStyle(
color: kShrineBrown900,
),
),
Terakhir, gunakan warna sekunder, bukan warna primer, pada tombol Cancel untuk meningkatkan kontras.
TextButton(
child: const Text('CANCEL'),
onPressed: () {
_usernameController.clear();
_passwordController.clear();
},
style: TextButton.styleFrom(
primary: Theme.of(context).colorScheme.secondary,
),
),
Simpan project Anda.
Android | iOS |
6. Menyesuaikan ketinggian
Setelah Anda memberikan gaya pada halaman dengan warna dan tipografi spesifik yang cocok dengan Shrine, mari kita sesuaikan ketinggian.
Mengubah ketinggian tombol NEXT
Ketinggian default untuk ElevatedButton
adalah 2. Mari kita naikkan lebih tinggi.
Di login.dart
, tambahkan nilai style:
ke ElevatedButton NEXT:
ElevatedButton(
child: const Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
elevation: 8.0,
),
),
Simpan project Anda.
Menyesuaikan ketinggian Kartu
Saat ini, kartu diletakkan di atas permukaan putih di samping navigasi situs.
Di home.dart
, tambahkan nilai elevation:
ke Kartu:
// TODO: Adjust card heights (103)
elevation: 0.0,
Simpan project.
Android | iOS |
Anda telah menghapus bayangan di bawah kartu.
7. Menambahkan Bentuk
Shrine memiliki gaya geometrik yang keren, yang menentukan elemen dengan bentuk persegi delapan atau persegi panjang. Mari kita terapkan pemberian gaya pada bentuk pada kartu di layar utama, serta kolom serta tombol teks di layar login.
Mengubah bentuk kolom teks di layar login
Di app.dart
, impor file berikut:
import 'supplemental/cut_corners_border.dart';
Masih di app.dart
, ubah tema dekorasi kolom teks untuk menggunakan batas sudut yang dipotong:
// TODO: Decorate the inputs (103)
inputDecorationTheme: const InputDecorationTheme(
border: CutCornersBorder(),
focusedBorder: CutCornersBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrineBrown900,
),
),
floatingLabelStyle: TextStyle(
color: kShrineBrown900,
),
),
Mengubah bentuk tombol di layar login
Di login.dart
, tambahkan batas persegi panjang yang miring ke tombol CANCEL:
TextButton(
child: const Text('CANCEL'),
onPressed: () {
_usernameController.clear();
_passwordController.clear();
},
style: TextButton.styleFrom(
primary: Theme.of(context).colorScheme.secondary,
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
),
),
TextButton tidak memiliki bentuk yang terlihat, jadi mengapa kita menambahkan bentuk batas? Agar animasi ripple terikat dengan bentuk yang sama saat disentuh.
Sekarang tambahkan bentuk yang sama ke tombol NEXT:
ElevatedButton(
child: const Text('NEXT'),
onPressed: () {
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
elevation: 8.0,
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
),
Untuk mengubah bentuk semua tombol, kita juga dapat menggunakan elevatedButtonTheme
atau textButtonTheme
di app.dart
. Ini merupakan tantangan bagi orang yang mempelajarinya.
Hot restart.
Android | iOS |
8. Mengubah tata letak
Selanjutnya, mari kita ubah tata letak untuk menampilkan kartu dalam ukuran dan rasio aspek yang berbeda, sehingga setiap kartu terlihat unik dari kartu lain.
Mengganti GridView dengan AsymmetricView
Kita sudah menulis file untuk tata letak asimetris.
Di home.dart
, tambahkan impor berikut:
import 'supplemental/asymmetric_view.dart';
Hapus _buildGridCards
dan ganti dengan body
:
body: AsymmetricView(
products: ProductsRepository.loadProducts(Category.all),
),
Simpan project.
Android | iOS |
Sekarang produk di-scroll secara horizontal dalam pola seperti anyaman.
9. Mencoba tema yang lain (Opsional)
Warna adalah cara efektif untuk mengekspresikan merek Anda, dan perubahan kecil pada warna dapat berpengaruh besar pada pengalaman pengguna Anda. Untuk mengujinya, mari kita lihat tampilan Shrine jika skema warna mereknya sedikit berbeda.
Mengubah warna
Di colors.dart
, tambahkan warna berikut:
const kShrinePurple = Color(0xFF5D1049);
Di app.dart
, ubah fungsi _buildShrineTheme()
menjadi:
ThemeData _buildShrineTheme() {
final ThemeData base = ThemeData.light();
return base.copyWith(
colorScheme: base.colorScheme.copyWith(
primary: kShrinePurple,
secondary: kShrinePurple,
error: kShrineErrorRed,
),
scaffoldBackgroundColor: kShrineSurfaceWhite,
textSelectionTheme: const TextSelectionThemeData(
selectionColor: kShrinePurple,
),
inputDecorationTheme: const InputDecorationTheme(
border: CutCornersBorder(),
focusedBorder: CutCornersBorder(
borderSide: BorderSide(
width: 2.0,
color: kShrinePurple,
),
),
floatingLabelStyle: TextStyle(
color: kShrinePurple,
),
),
);
}
Hot restart. Sekarang, tema baru akan muncul.
Android | iOS |
Android | iOS |
Hasilnya sangatlah berbeda. Mari kita ubah kembali _buildShrineTheme
di app.dart's
menjadi seperti semula. Atau, download kode awal untuk 104.
10. Selamat!
Sekarang, Anda telah membuat aplikasi yang menyerupai spesifikasi desain dari desainer Anda.
Langkah berikutnya
Sekarang Anda telah menggunakan komponen MDC berikut: tema, tipografi, ketinggian, dan bentuk. Anda dapat mempelajari lebih banyak komponen dan subsistem di library MDC-Flutter.
Temukan file-file di direktori supplemental
untuk mempelajari cara kita membuat scroll horizontal, petak tata letak asimetris.
Bagaimana jika desain rencana aplikasi Anda berisi elemen yang tidak memiliki komponen di library MDC? Di MDC-104: Komponen Lanjutan Desain Material, kami menunjukkan cara membuat komponen kustom menggunakan library MDC untuk mencapai tampilan yang spesifik.