Flutter列表滑動曝光埋點,支援SliverList、SliverGrid

SBDavid發表於2020-02-01

flutter_sliver_tracker

GitHub連線

滑動曝光埋點框架,支援SliverList、SliverGrid

什麼是滑動曝光埋點

滑動曝光埋點用於滑動列表元件中的模組曝光,例如Flutter中的SliverListSliverGrid。 當SliverList中的某一個行(或列)移動到ViewPort中,並且顯示比例超過一定閾值時,我們把這個事件記為一次滑動曝光事件。

當然我們對滑動曝光有一些額外的要求:

  • 需要滑出一定比例的時候才出發曝光(已實現)
  • 滑動速度快時不觸發曝光事件(需要throttle)
  • 滑出視野的模組,再次滑入視野時需要再次上報(已實現)
  • 模組在視野中上下反覆移動只觸發一次曝光(還未實現)

執行Demo

圖片名稱
  • 克隆程式碼到本地: git clone git@github.com:SBDavid/flutter_sliver_tracker.git
  • 切換工作路徑: cd flutter_sliver_tracker/example/
  • 啟動模擬器
  • 執行: flutter run

內部原理

滑動曝光的核心難點是計算元件的露出比例。也是說我們需要知道ListView中的元件的總高度當前顯示高度。 這兩個高度做除法就可以得出比例。

元件總高度

元件的總高度可以在renderObject中獲取。我們可以獲取renderObject下的size屬性,其中包含了元件的長寬。

當前顯示高度

顯示高度可以從SliverGeometry.paintExtent中獲取。

使用文件

1. 安裝

dependencies:
  flutter_sliver_tracker: ^1.0.0
複製程式碼

2. 引用外掛

import 'package:xm_sliver_listener/flutter_sliver_tracker.dart';
複製程式碼

3. 傳送滑動埋點事件

3.1 通過ScrollViewListener捕獲滾動事件,ScrollViewListener必須包裹在CustomScrollView之上。

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 通過ScrollViewListener捕獲滾動事件
      body: ScrollViewListener(
        child: CustomScrollView(
          slivers: <Widget>[
          ],
        ),
      ),
    );
  }
}
複製程式碼

3.2 在SliverToBoxAdapter中監聽滾動停止事件,並計算顯示比例

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 通過ScrollViewListener捕獲滾動事件
      body: ScrollViewListener(
        child: CustomScrollView(
          slivers: <Widget>[
            SliverToBoxAdapter(
              // 監聽停止事件,如果在頁面上展示比例,可以自行setState
              child: SliverEndScrollListener(
                onScrollInit: (SliverConstraints constraints, SliverGeometry geometry) {
                  // 顯示高度 / sliver高度
                  Fluttertoast.showToast(msg: "展示比例:${geometry.paintExtent / geometry.scrollExtent}");
                },
                onScrollEnd: (ScrollEndNotification notification,
                    SliverConstraints constraints,
                    SliverGeometry geometry) {
                  Fluttertoast.showToast(msg: "展示比例:${geometry.paintExtent / geometry.scrollExtent}");
                },
                child: Container(
                  height: 300,
                  color: Colors.amber,
                 
                  ),
                ),
            ),
          ],
        ),
      ),
    );
  }
}
複製程式碼

3.3 在SliverListSliverGrid中監聽滾動停止事件,並計算顯示比例

  • itemLength:列表項佈局高度
  • displayedLength:列表項展示高度
  • 如果需要在widget中顯示高度,可以自行setState
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 通過ScrollViewListener捕獲滾動事件
      body: ScrollViewListener(
        child: CustomScrollView(
          slivers: <Widget>[
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  // 監聽滾動停止
                  return SliverMultiBoxScrollEndListener(
                    debounce: 1000,
                    child: Container(
                      height: 300,
                      color: Colors.redAccent,
                      child: Center(
                        child: Text("SliverList Item", style: TextStyle(fontSize: 30, color: Colors.white))
                      ),
                    ),
                    onScrollInit: (double itemLength, double displayedLength) {
                      Fluttertoast.showToast(msg: "顯示高度:${displayedLength}");
                    },
                    onScrollEnd: (double itemLength, double displayedLength) {
                      Fluttertoast.showToast(msg: "顯示高度:${displayedLength}");
                    },
                  );
                },
                childCount: 1
              ),
            ),
          ],
        ),
      ),
    );
  }
}
複製程式碼

3.4 在SliverListSliverGrid中監聽滾動更新事件,並計算顯示比例

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 通過ScrollViewListener捕獲滾動事件
      body: ScrollViewListener(
        child: CustomScrollView(
          slivers: <Widget>[
            SliverList(
              delegate: SliverChildBuilderDelegate(
                      (BuildContext context, int index) {
                // 監聽滾動更新事件
                return SliverMultiBoxScrollUpdateListener(
                  onScrollInit: (double percent) {
                    // percent 列表項顯示比例
                  },
                  onScrollUpdate: (double percent) {
                    // percent 列表項顯示比例
                  },
                  debounce: 1000,
                  // percent 列表項顯示比例
                  builder: (BuildContext context, double percent) {
                    return Container(
                      height: 200,
                      color: Colors.amber.withAlpha((percent * 255).toInt()),
                      child: Center(
                          child: Text("SliverList Item Percent ${percent.toStringAsFixed(2)}", style: TextStyle(fontSize: 30, color: Colors.white))
                      ),
                    );
                  },
                );
              },
              childCount: 6
              ),
            ),
          ],
        ),
      ),
    );
  }
}
複製程式碼

相關文章