今天我們將要做推薦影片List,我們會用到ListView
、Ink
、InkWell
、SingleChildScrollView
、BoxDecoration
。當然也需要前面提到的像是Column
、SizedBox
。
在前一篇中我們做的主推薦影片區域,我已經把這些程式碼包起來變成_buildMajorRecommendedVideo()
,今天要做的就是_buildRecommendedMenu(context, "現正熱播")
。
在這裡要特別說明的步驟是前一篇我們使用Column,但Column是不可滑動的,當children的高度超出屏幕高度就會報錯。所以我們可以使用一個簡單的方法,套一個SingleChildScrollView
套完之後就能滾動啦。
class _HomePageState extends State<HomePage> {
GlobalKey<ScaffoldState> _globalKey =
GlobalKey(debugLabel: "test scaffoldState");
@override
Widget build(BuildContext context) {
return Scaffold(
key: _globalKey,
body: SingleChildScrollView(
child: Column(mainAxisSize: MainAxisSize.max, children: [
_buildMajorRecommendedVideo(),
_buildRecommendedMenu("現正熱播"),
_buildRecommendedMenu("為您推薦"),
]),
),
);
}
接著看到_buildRecommendedMenu
,基本上每一個推薦類別可能有不同的title以及list所以我設了兩個參數。然後跟前一篇同樣邏輯,我用Column顯示標題以及ListView
只是這邊要注意的是ListView要用SizedBox限制高度,不然會跑出高度infinity的錯誤
Widget _buildRecommendedMenu( String title,
{List playList}) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 24.0),
Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
title,
style: TextStyle(fontSize: 24.0),
),
),
SizedBox(
height: 150, //限制高度不然報錯
child: ListView(...),
)
],
);
}
接著我們來看ListView,先看ListView (Flutter Widget of the Week),我最愛這個系列影片了,簡單易懂。
這邊我使用List.generate
來產生我需要的Widgets,當然ListView
的實現方式有很多,有興趣的朋友可以再多看看官網
ListView(
scrollDirection: Axis.horizontal,
children: List.generate(8, (index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Ink(
width: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.0),
image: DecorationImage(
image: AssetImage(
"assets/videolist/videolist${index + 1}.jpg"),
fit: BoxFit.cover)),
child: InkWell(
borderRadius: BorderRadius.circular(8.0),
onLongPress: () {
_globalKey.currentState
.showSnackBar(SnackBar(content: Text("動畫名字")));
},
),
),
);
}),
)
要特別講的就是這些圖案都有水波紋動畫,實現水波紋由的InkWell達成。
原本我在InkWell
外套Container
導圓角和放背景圖片,但是效果是InkWell的水波紋全部被擋住
。後來查到正確用法是需要在InkWell外面套Ink。
Ink說明有這樣一句話,不是特別理解,但顯然我們這個情境需要用Ink而不是Container
/// If there is no intention to render anything on this decoration, consider
/// using a [Container] with a [BoxDecoration] instead.
最後要講到的是BoxDecoration
這東西。我覺得這超級有用。先看Container的介紹,裡面有講到一些些。
它可以我們可以去設定顏色、背景圖案、圓角、陰影、形狀等等,功能蠻豐富的。
const BoxDecoration({
this.color,
this.image,
this.border,
this.borderRadius,
this.boxShadow,
this.gradient,
this.backgroundBlendMode,
this.shape = BoxShape.rectangle,
})
獻上今天的程式效果圖
今天做這個主要碰到的就是InkWell的問題,我有參考了這篇解決,做完之後是不是覺得這個App好像有點樣子了,但是離完成還有好長一段路,加油!
GitHub連結: flutter-netflix-clone