Trình phát nhạc: sáng và tối
Thuộc phần Bố cục phù hợp với mọi màn hình trong hành trình Flutter của Coddy. Bài học 30 trên 30.
Mọi người nghe nhạc vào ban đêm, nên trình phát có chế độ tối, với một nút trên thanh trên cùng để chuyển đổi.
AppBar nhận actions:, một danh sách nút hiển thị ở phía bên phải. Một IconButton ở đó chuyển đổi giá trị bool trong trạng thái, và themeMode: thay đổi theo. Biểu tượng của nút cho biết chức năng của nút: mặt trăng, Icons.dark_mode, khi trình phát ở chế độ sáng, và mặt trời, Icons.light_mode, khi trình phát ở chế độ tối.
Mọi màu trên màn hình lấy từ giao diện đều thay đổi theo: nền, văn bản, thanh trượt và các nút. Ảnh bìa album vẫn giữ màu riêng, như một bức ảnh.
Thử thách
DễThêm chế độ tối:
- một trường
bool _dark = false; - một
darkTheme:dùng màu hạt giốngColors.deepPurplevớibrightness: Brightness.dark, vàthemeMode:được chọn dựa trên_dark - trong
actions:củaAppBar, mộtIconButtonhiển thịIcons.light_modekhi ở chế độ tối vàIcons.dark_modekhi ở chế độ sáng, nút này đổi giá trị_darktrongsetState
Tự làm thử
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
double _position = 0.3;
bool _playing = false;
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: Scaffold(
appBar: AppBar(title: const Text('Now Playing')),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
children: [
Stack(
children: [
Container(
width: double.infinity,
height: 300,
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(24),
),
child: const Center(
child: Icon(Icons.album, size: 120, color: Colors.white),
),
),
Positioned(
top: 12,
right: 12,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.black54,
borderRadius: BorderRadius.circular(8),
),
child: const Text(
'HD',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
),
],
),
const SizedBox(height: 24),
const Text(
'Midnight Drive',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 4),
const Text('The Night Owls', style: TextStyle(color: Colors.grey)),
const SizedBox(height: 16),
Slider(
value: _position,
onChanged: (value) {
setState(() {
_position = value;
});
},
),
const Row(
children: [
Text('1:12'),
Spacer(),
Text('3:45'),
],
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: IconButton(
iconSize: 40,
icon: const Icon(Icons.skip_previous),
onPressed: () {},
),
),
Expanded(
child: IconButton(
iconSize: 64,
icon: Icon(_playing ? Icons.pause : Icons.play_arrow),
onPressed: () {
setState(() {
_playing = !_playing;
});
},
),
),
Expanded(
child: IconButton(
iconSize: 40,
icon: const Icon(Icons.skip_next),
onPressed: () {},
),
),
],
),
],
),
),
),
);
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Bố cục phù hợp với mọi màn hình
1Chia sẻ không gian trong hàng
Expanded lấp đầy hàngChia sẻ không gian với flexFlexible ôm sát phần tử conSpacer đẩy các phần tử ra xa nhau4Kích thước và điểm ngắt
Toàn bộ chiều rộng: double.infinityChiều rộng tối đaKích thước màn hình: MediaQueryĐiểm ngắt của LayoutBuilder7Dự án: trình phát nhạc
Trình phát nhạc: ảnh bìa albumTrình phát nhạc: thông tin bài hát3Xếp chồng các widget
Xếp chồng widget lên trênĐặt ở một gócCăn chỉnh bên trong hộpSafeArea và phần khuyết6Giao diện chủ đề và chế độ tối
Tạo giao diện chủ đề từ một seedMàu sắc Theme.of(context)Kiểu chữ từ giao diện chủ đềGiao diện chủ đề tốiCông tắc chế độ tốiTự luyện tập: Trình biên dịch Flutter online