Flutter 跨平台 App 程式設計入門】#02 多頁面電子書
Published in
9 min readApr 9, 2024
github連結:https://github.com/cy1227/Flutter_HW2
主題 :推薦小說與電視劇
頁面預覽:
- 製作包含多個頁面的電子書 App。
- 每個頁面定義對應的 StatelessWidget
class MyHomePage extends StatelessWidget
class BookDetail extends StatelessWidget
class DramaDetail extends StatelessWidget
class EpisodeDetailPage extends StatelessWidget
- 定義資料的型別,比方電影 App 定義 Movie 型別。
class Drama {
final String name;
final String imageUrl;
List<String> roleName = [];
List<String> rolePic = [];
Drama(
{required this.name,
required this.imageUrl,
required this.roleName,
required this.rolePic});
}
class Book {
final String name;
final String author;
final String description;
final String imageUrl;
Book({
required this.name,
required this.author,
required this.description,
required this.imageUrl,
});
}
- 使用到 ListView.builder 或 ListView.separated
ListView.builder(
// 設置 ListView 的 padding
padding: const EdgeInsets.all(20),
// 設置 ListView 的項目數量為書籍列表的長度
itemCount: books.length,
// 定義 ListView 的項目構建器
itemBuilder: (context, index) {
// 當項目被點擊時,導航到書籍詳情頁面
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
// 傳遞選擇的書籍到書籍詳情頁面
builder: (context) {
return BookDetail(book: books[index]);
},
),
);
},
// 顯示書籍的縮略信息
child: BookTile(book: books[index]),
);
},
),
- 自訂 StatelessWidget 顯示 ListView 的資料,比方用 BookTile 顯示 Book 的內容。
class DramaTile extends StatelessWidget {
const DramaTile({super.key, required this.drama});
final Drama drama;
@override
Widget build(BuildContext context) {
return Container(
// 包裹卡片的容器
child: Card(
// 卡片的背景色
color: Color.fromARGB(251, 247, 245, 192),
// 卡片的內容
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
// 顯示戲劇圖片
Image.network(
drama.imageUrl,
width: 150,
height: 200,
fit: BoxFit.cover,
),
SizedBox(height: 4), // 上方留白
// 顯示戲劇名稱
Text(
drama.name,
style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
),
],
),
),
),
);
}
}
- 使用 Navigator 切換頁面
ListTile(
// 列表項目的標題,顯示集數
title: Text(
'第 ${index + 1} 集',
textAlign: TextAlign.center,
),
// 當列表項目被點擊時,導航到集數詳情頁面
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
// 傳遞集數標題和內容到集數詳情頁面
builder: (context) => EpisodeDetailPage(
episodeTitle: '第 ${index + 1} 集',
episodeContent: content[index],
),
),
);
},
),
- 使用 GestureDetector、InkWell 或 TextButton 偵測點擊。
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
// 傳遞選擇的書籍到書籍詳情頁面
builder: (context) {
return BookDetail(book: books[index]);
},
),
);
},
// 顯示書籍的縮略信息
child: BookTile(book: books[index]),
);
- 使用 GridView 製作格子狀排列的畫面
GridView.builder(
// 定義網格布局的參數
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // 橫軸方向的列數
crossAxisSpacing: 0, // 橫軸方向的間距
mainAxisSpacing: 0, // 縱軸方向的間距
childAspectRatio: 0.75, // 每個子元素的寬高比
),
// 總共的項目數量為戲劇列表的長度
itemCount: dramas.length,
itemBuilder: (context, index) {
return Container(
// 設置容器的外邊距
margin: EdgeInsets.all(8.0),
child: InkWell(
// 當容器被點擊時,導航到戲劇詳情頁面
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
// 傳遞選擇的戲劇到戲劇詳情頁面
builder: (context) {
return DramaDetail(drama: dramas[index]);
},
),
);
},
// 顯示戲劇的縮略信息
child: DramaTile(drama: dramas[index]),
),
);
},
)
- 使用 DefaultTabController、TabBar、TabBarView 製作 tab 分頁。
bottom: const TabBar(
tabs: [
Tab(text: '小說'),
Tab(text: '電視劇'),
],
),
child: TabBarView(
children: [
...
// 顯示書籍
);
},
),
// 顯示戲劇
],
),
- 使用 Card widget
Card(
color: const Color.fromARGB(255, 156, 208, 250),
child: ListTile(
title: Text(
'第 ${index + 1} 集',
textAlign: TextAlign.center,
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EpisodeDetailPage(
episodeTitle: '第 ${index + 1} 集',
episodeContent: content[index],
),
),
);
},
),
);
心得:這次的作業不只侷限在單一頁面,終於有比較像一個app的感覺了 只是想嘗試上課教的以外的新功能的時候知道為何都沒有成功添加dependency所以沒有成功,此外電子書的功能感覺結合爬蟲會更符有效率就不用複製內文貼上了。