iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 4
1
Mobile Development

新手試試用Flutter做Netflix UI系列 第 4

[Day4]Flutter 用ListView做Netflix推薦影片List

  • 分享至 

  • xImage
  •  

今天我們將要做推薦影片List,我們會用到ListViewInkInkWellSingleChildScrollViewBoxDecoration。當然也需要前面提到的像是ColumnSizedBox

在前一篇中我們做的主推薦影片區域,我已經把這些程式碼包起來變成_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,
})

獻上今天的程式效果圖
https://ithelp.ithome.com.tw/upload/images/20200919/20130593s1FX6g4TEf.jpg

今天做這個主要碰到的就是InkWell的問題,我有參考了這篇解決,做完之後是不是覺得這個App好像有點樣子了,但是離完成還有好長一段路,加油!

GitHub連結: flutter-netflix-clone


上一篇
[Day3]Flutter使用Column以及Row初步建立主頁面之推薦區
下一篇
[Day5]Flutter UI做Netflix排行榜前10名
系列文
新手試試用Flutter做Netflix UI30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言