Flutter Day 8 — 視差滾動效果 (Parallax PageView)

陳董 Don Chen
5 min readFeb 17, 2020

--

這條海岸線真是太棒了 Italy, Path of Gods— Photo by Don

我將卡片視覺效果、滾動視差效果分成兩個部份來說明如何實作。

第一階段:卡片視覺效果

卡片的效果是一張圖片疊加上了黑到白的透明漸進圖然後放上文字。

文字的部分

分為 titleContainer 和 descriptionContainer 除了設定顏色字體以外,descriptionContainer 設定了上邊距與 titleContainer 保持距離。

漸層的部分

漸層通過 DecoratedBox 包裝起來,從上到下由白到透明黑。

Widget 疊加在一起的效果

Roma Colosseum

最後通過 Stack 讓 image, imageOverlayGradient, textContainer 三個 Widget 疊加在一起,通過 ClipRRect 做圓角效果。

實作滑動效果

第一步:讓卡片可以滑動

將前面建立的卡片(TripPageItem)結合 PageView 放在畫面的中央(Center + SizedBox) 就可以在畫面上做滾動,只是每張卡片都是貼著兩側的。

第二步:顯示左右卡片的一部分

PageViewController — viewportFraction

給 PageView 一個 PageViewController 並且修改他的 viewportFraction 就可以控制每一張卡片顯示的大小的比例。

當 viewportFraction 等於 1.0 的時候就是沾滿一個畫面。

第三步:增加卡片的水平間距

水平間距

在 TripPageItem 中加入 Padding 讓卡片之間在水平方向有相同的距離。

第二階段:視差滾動效果

圓角卡片準備好了,也已經可以通過 PageView 滑動了,接下來該輪到視差滾動效果了。

視差滾動效果

簡單的說,視差滾動給人的感受應該是這樣的

我在移動卡片而卡片裡面的圖片也同時在「被」移動。

水平間距

在 Card 中放置一張大於顯示範圍的 Image,如果固定 Image 的顯示範圍(比如只看到 Image 中間的部分)那麼滑動起來就會像下面的效果。

固定顯示圖片的一部分

那我們要做到滾動視差的效果,可以這樣做

滑動卡片的時候同時改變卡片中圖片的顯示範圍

開發思路

  • 取得拖動卡片的事件 (NotificationListener<ScrollNotification>)
  • 計算卡片相對畫面中央移動的距離的百分比(這裏記做 pagePosition)
  • 改變圖片顯示的範圍(通過 Alignment 移動圖片)
  • 重新渲染卡片
滾動視圖效果相關的 class

第一部分:渲染卡片

就像前面「卡片視覺效果」實作的介紹,TripPageItem 負責渲染卡片的介面,而 Trip 定義了卡片需要的資訊。

其中 TripPageItem 會接收 tripVisibility 屬性,這個屬性包含了 pagePosition, 通過修改 Alignment 來改變圖片的可視範圍。

第二部分:計算卡片移動距離

TripPageTransformer 接收 ScrollMetrics 參數(來自 Notification<ScrollNotification>)結合 viewPortFraction 來計算卡片相對中心點的移動距離。

計算 pagePosition

第三步:滾動視圖的管理

滾動視圖的管理

通過 NotificationListener<ScrollNotification> 監聽滑動卡片的事件,在滑動時重新計算 pagePosition(包在 TripPageVisiblity 中),然後藉由 setState() 方法重新渲染卡片中的圖片顯示範圍。

最後一步

通過 Center 讓 card 居中,然後 sizedBox 設定高度,最後就是套用 TripPageTransformer.

最終效果

--

--