Bài thực hành Flutter thiết kế giao diện trang (1)
Bài học này chúng ta sẽ thiết kế một trang giống như hình minh hoạ dưới đây.
File ảnh được sử dụng trong bài học này:
Bài viết mà bạn đang đọc nằm trong khoá học Flutter miễn phí dưới đây của chúng tôi, nơi bạn có thể tìm thấy các bài thực hành khác để tự học Flutter.
- Khoá học Flutter miễn phí cho người mới bắt đầu
1. Phác thảo thiết kế
Để thiết kế một trang bạn cần phải phân chia nó thành các phần (section) riêng biệt:
TitleSection:
ButtonSection:
2. ImageSection
ImageSection là nơi hiển thị một ảnh. Trong vùng này chúng ta sẽ hiển thị một ảnh với chiều cao cố định và chiều rộng lấp đầy màn hình.
image_section.dart
import 'package:flutter/material.dart';
class ImageSection extends StatelessWidget {
final String imageUrl;
const ImageSection({required this.imageUrl, super.key});
@override
Widget build(BuildContext context) {
return Image.network(
imageUrl,
width: double.infinity,
height: 240,
fit: BoxFit.fitWidth,
);
}
}
3. TitleSection
TitleSection là một Row với 3 widget con. Trong đó Widget đầu tiên có chiều rộng lớn nhất có thể.
title_section.dart
import 'package:flutter/material.dart';
class TitleSection extends StatelessWidget {
final String name;
final String location;
const TitleSection({
super.key,
required this.name,
required this.location,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Expanded(
child: buildTitle(),
),
Icon(
Icons.star,
color: Colors.red[500],
),
const Text('41'),
],
),
);
}
Widget buildTitle() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Text(
name,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
Text(
location,
style: TextStyle(
color: Colors.grey[500],
),
),
],
);
}
}
4. ButtonSection
ButtonSection là một Row chứa 3 button tuỳ biến (CustomVerticalButton).
Chúng ta tạo lớp CustomVerticalButton như là một button tuỳ biến và có thể tái sử dụng nó ở nhiều nơi.
custom_vertical_button.dart
import 'package:flutter/material.dart';
class CustomVerticalButton extends StatelessWidget {
const CustomVerticalButton({
super.key,
required this.color,
required this.iconData,
required this.label,
});
final Color color;
final IconData iconData;
final String label;
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(iconData, color: color),
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
}
Sử dụng CustomVerticalButton để tạo 3 button trong ButtonSection:
button_section.dart
import 'package:flutter/material.dart';
import 'custom_vertical_button.dart';
class ButtonSection extends StatelessWidget {
const ButtonSection({super.key});
@override
Widget build(BuildContext context) {
final Color color = Theme.of(context).primaryColor;
return SizedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CustomVerticalButton(
color: color,
iconData: Icons.call,
label: 'CALL',
),
CustomVerticalButton(
color: color,
iconData: Icons.near_me,
label: 'ROUTE',
),
CustomVerticalButton(
color: color,
iconData: Icons.share,
label: 'SHARE',
),
],
),
);
}
}
5. DescriptionSection
description_section.dart
import 'package:flutter/material.dart';
class DescriptionSection extends StatelessWidget {
final String description;
const DescriptionSection({
super.key,
required this.description,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(32),
child: Text(
description,
softWrap: true,
),
);
}
}
6. MainScreen
Cuối cùng lắp ráp tất cả các phần (section) lại với nhau để tạo ra một trang.
main_screen.dart
import 'package:flutter/material.dart';
import 'button_section.dart';
import 'image_section.dart';
import 'description_section.dart';
import 'title_section.dart';
class MainScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Flutter Layout")),
body: Center(
child: _buildMainWidget(context),
),
);
}
Widget _buildMainWidget(BuildContext context) {
return const SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ImageSection(
imageUrl:
'https://raw.githubusercontent.com/o7planning/rs/master/flutter/mountain-1.webp',
),
SizedBox(height: 20),
TitleSection(
name: "Oeschinen Lake Campground",
location: "Kandersteg, Switzerland",
),
SizedBox(height: 20),
ButtonSection(),
SizedBox(height: 20),
DescriptionSection(
description:
'Lake Oeschinen lies at the foot of the Blüemlisalp in the '
'Bernese Alps. Situated 1,578 meters above sea level, it '
'is one of the larger Alpine Lakes. A gondola ride from '
'Kandersteg, followed by a half-hour walk through pastures '
'and pine forest, leads you to the lake, which warms to 20 '
'degrees Celsius in the summer. Activities enjoyed here '
'include rowing, and riding the summer toboggan run.',
),
],
),
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'main_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: MainScreen(),
);
}
}
Các hướng dẫn lập trình Flutter
- Hướng dẫn và ví dụ Flutter Column
- Hướng dẫn và ví dụ Flutter Stack
- Hướng dẫn và ví dụ Flutter IndexedStack
- Hướng dẫn và ví dụ Flutter Spacer
- Hướng dẫn và ví dụ Flutter Expanded
- Hướng dẫn và ví dụ Flutter SizedBox
- Hướng dẫn và ví dụ Flutter Tween
- Cài đặt Flutter SDK trên Windows
- Cài đặt Flutter Plugin cho Android Studio
- Tạo ứng dụng Flutter đầu tiên của bạn - Hello Flutter
- Hướng dẫn và ví dụ Flutter Scaffold
- Hướng dẫn và ví dụ Flutter AppBar
- Hướng dẫn và ví dụ Flutter BottomAppBar
- Hướng dẫn và ví dụ Flutter SliverAppBar
- Hướng dẫn và ví dụ Flutter TextButton
- Hướng dẫn và ví dụ Flutter ElevatedButton
- Hướng dẫn và ví dụ Flutter ShapeBorder
- Hướng dẫn và ví dụ Flutter EdgeInsetsGeometry
- Hướng dẫn và ví dụ Flutter EdgeInsets
- Hướng dẫn và ví dụ Flutter CircularProgressIndicator
- Hướng dẫn và ví dụ Flutter LinearProgressIndicator
- Hướng dẫn và ví dụ Flutter Center
- Hướng dẫn và ví dụ Flutter Align
- Hướng dẫn và ví dụ Flutter Row
- Hướng dẫn và ví dụ Flutter SplashScreen
- Hướng dẫn và ví dụ Flutter Alignment
- Hướng dẫn và ví dụ Flutter Positioned
- Hướng dẫn và ví dụ Flutter ListTile
- Hướng dẫn và ví dụ Flutter SimpleDialog
- Hướng dẫn và ví dụ Flutter AlertDialog
- Navigation và Routing trong Flutter
- Hướng dẫn và ví dụ Flutter Navigator
- Hướng dẫn và ví dụ Flutter TabBar
- Hướng dẫn và ví dụ Flutter Banner
- Hướng dẫn và ví dụ Flutter BottomNavigationBar
- Hướng dẫn và ví dụ Flutter FancyBottomNavigation
- Hướng dẫn và ví dụ Flutter Card
- Hướng dẫn và ví dụ Flutter Border
- Hướng dẫn và ví dụ Flutter ContinuousRectangleBorder
- Hướng dẫn và ví dụ Flutter RoundedRectangleBorder
- Hướng dẫn và ví dụ Flutter CircleBorder
- Hướng dẫn và ví dụ Flutter StadiumBorder
- Hướng dẫn và ví dụ Flutter Container
- Hướng dẫn và ví dụ Flutter RotatedBox
- Hướng dẫn và ví dụ Flutter CircleAvatar
- Hướng dẫn và ví dụ Flutter TextField
- Hướng dẫn và ví dụ Flutter IconButton
- Hướng dẫn và ví dụ Flutter FlatButton
- Hướng dẫn và ví dụ Flutter SnackBar
- Hướng dẫn và ví dụ Flutter Drawer
- Ví dụ Flutter Navigator pushNamedAndRemoveUntil
- Hiển thị hình ảnh trên Internet trong Flutter
- Hiển thị ảnh Asset trong Flutter
- Flutter TextInputType các kiểu bàn phím
- Hướng dẫn và ví dụ Flutter NumberTextInputFormatter
- Hướng dẫn và ví dụ Flutter Builder
- Làm sao xác định chiều rộng của Widget cha trong Flutter
- Bài thực hành Flutter thiết kế giao diện màn hình đăng nhập
- Bài thực hành Flutter thiết kế giao diện trang (1)
- Khuôn mẫu thiết kế Flutter với các lớp trừu tượng
- Bài thực hành Flutter thiết kế trang Profile với Stack
- Bài thực hành Flutter thiết kế trang profile (2)
- Hướng dẫn và ví dụ Flutter ListView
- Hướng dẫn và ví dụ Flutter GridView
- Bài thực hành Flutter với gói http và dart:convert (2)
- Bài thực hành Flutter với gói http và dart:convert (1)
- Ứng dụng Flutter Responsive với Menu Drawer
- Flutter GridView với SliverGridDelegate tuỳ biến
- Hướng dẫn và ví dụ Flutter image_picker
- Flutter upload ảnh sử dụng http và ImagePicker
- Hướng dẫn và ví dụ Flutter SharedPreferences
- Chỉ định cổng cố định cho Flutter Web trên Android Studio
- Tạo Module trong Flutter
- Hướng dẫn và ví dụ Flutter SkeletonLoader
- Hướng dẫn và ví dụ Flutter Slider
- Hướng dẫn và ví dụ Flutter Radio
- Bài thực hành Flutter SharedPreferences
- Hướng dẫn và ví dụ Flutter InkWell
- Hướng dẫn và ví dụ Flutter GetX GetBuilder
- Hướng dẫn và ví dụ Flutter GetX obs Obx
- Hướng dẫn và ví dụ Flutter flutter_form_builder
- Xử lý lỗi 404 trong Flutter GetX
- Ví dụ đăng nhập và đăng xuất với Flutter Getx
- Hướng dẫn và ví dụ Flutter multi_dropdown
Show More