Flutter ScrollMetrics


简介

包含当前ViewPort及滚动位置等信息

  • pixels:当前滚动位置
  • maxScrollExtent:最大可滚动长度。
  • extentBefore:滑出ViewPort顶部的长度;
  • extentInside:ViewPort内部长度;此示例中屏幕显示的列表部分的长度
  • extentAfter:列表中未滑入ViewPort部分的长度;此示例中列表底部未显示到屏幕范围部分的长度
  • atEdge:是否滑到了Scrollable Widget的边界

基本用法

抽象类,不可被实例化

  • FixedScrollMetrics,它是实现此接口的不可变对象
  • 下方Demo中,在接收到滚动事件时,参数类型为ScrollNotification,它包括一个metrics属性,它的类型是ScrollMetrics

实例演示

import 'package:flutter/material.dart';

class ScrollMetricsDemo extends StatefulWidget {
  _ScrollMetricsDemoState createState() => _ScrollMetricsDemoState();
}

class _ScrollMetricsDemoState extends State<ScrollMetricsDemo> {
  String _progress = "0%";

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 400.0,
      child: Scrollbar(
        child: NotificationListener<ScrollNotification>(
          onNotification: (ScrollNotification notification) {
            double progress = notification.metrics.pixels /
                notification.metrics.maxScrollExtent;
            //重新构建
            setState(() {
              _progress = "${(progress * 100).toInt()}%";
            });
            print("BottomEdge: ${notification.metrics.extentAfter == 0}");
            //return true; //放开此行注释后,进度条将失效
          },
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              ListView.builder(
                  itemCount: 100,
                  itemExtent: 50.0,
                  itemBuilder: (context, index) {
                    return Container(
                      color: Theme.of(context).primaryColor,
                      margin: const EdgeInsets.symmetric(vertical: 10.0),
                      child: Text(
                        'test$index',
                        style: TextStyle(
                            fontSize: 20.0,
                            fontWeight: FontWeight.bold,
                            color: Colors.white),
                      ),
                    );
                  }),
              CircleAvatar(
                //显示进度百分比
                radius: 30.0,
                child: Text(_progress),
                backgroundColor: Colors.black54,
              )
            ],
          ),
        ),
      ),
    );
  }
}