Flutter Day 8 — 視差滾動效果 (Parallax PageView)
我將卡片視覺效果、滾動視差效果分成兩個部份來說明如何實作。
第一階段:卡片視覺效果
卡片的效果是一張圖片疊加上了黑到白的透明漸進圖然後放上文字。
文字的部分
分為 titleContainer 和 descriptionContainer 除了設定顏色字體以外,descriptionContainer 設定了上邊距與 titleContainer 保持距離。
漸層的部分
漸層通過 DecoratedBox 包裝起來,從上到下由白到透明黑。
Widget 疊加在一起的效果
最後通過 Stack 讓 image, imageOverlayGradient, textContainer 三個 Widget 疊加在一起,通過 ClipRRect 做圓角效果。
實作滑動效果
第一步:讓卡片可以滑動
將前面建立的卡片(TripPageItem)結合 PageView 放在畫面的中央(Center + SizedBox) 就可以在畫面上做滾動,只是每張卡片都是貼著兩側的。
第二步:顯示左右卡片的一部分
給 PageView 一個 PageViewController 並且修改他的 viewportFraction 就可以控制每一張卡片顯示的大小的比例。
當 viewportFraction 等於 1.0 的時候就是沾滿一個畫面。
第三步:增加卡片的水平間距
在 TripPageItem 中加入 Padding 讓卡片之間在水平方向有相同的距離。
第二階段:視差滾動效果
圓角卡片準備好了,也已經可以通過 PageView 滑動了,接下來該輪到視差滾動效果了。
簡單的說,視差滾動給人的感受應該是這樣的
我在移動卡片而卡片裡面的圖片也同時在「被」移動。
在 Card 中放置一張大於顯示範圍的 Image,如果固定 Image 的顯示範圍(比如只看到 Image 中間的部分)那麼滑動起來就會像下面的效果。
那我們要做到滾動視差的效果,可以這樣做
滑動卡片的時候同時改變卡片中圖片的顯示範圍
開發思路
- 取得拖動卡片的事件 (NotificationListener<ScrollNotification>)
- 計算卡片相對畫面中央移動的距離的百分比(這裏記做 pagePosition)
- 改變圖片顯示的範圍(通過 Alignment 移動圖片)
- 重新渲染卡片
第一部分:渲染卡片
就像前面「卡片視覺效果」實作的介紹,TripPageItem 負責渲染卡片的介面,而 Trip 定義了卡片需要的資訊。
其中 TripPageItem 會接收 tripVisibility 屬性,這個屬性包含了 pagePosition, 通過修改 Alignment 來改變圖片的可視範圍。
第二部分:計算卡片移動距離
TripPageTransformer 接收 ScrollMetrics 參數(來自 Notification<ScrollNotification>)結合 viewPortFraction 來計算卡片相對中心點的移動距離。
第三步:滾動視圖的管理
通過 NotificationListener<ScrollNotification> 監聽滑動卡片的事件,在滑動時重新計算 pagePosition(包在 TripPageVisiblity 中),然後藉由 setState() 方法重新渲染卡片中的圖片顯示範圍。
最後一步
通過 Center 讓 card 居中,然後 sizedBox 設定高度,最後就是套用 TripPageTransformer.