1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Custom scrollPhysics that allows overscroll

Discussão em 'Mobile' iniciado por Stack, Outubro 16, 2024 às 05:53.

  1. Stack

    Stack Membro Participativo

    Overscroll should be allowed. When scrolling to the upper and lower limit of the scroll there should be one item left on screen. The list should not bounce back. But the should be a smooth scrolling

    class StickyOverscrollPhysics extends ScrollPhysics {
    final double itemHeight;
    final int itemLength;
    final double maxOverscrollExtent = 70.0; // Allow overscroll but limit it.

    const StickyOverscrollPhysics({
    required this.itemHeight,
    required this.itemLength,
    ScrollPhysics? parent,
    }) : super(parent: parent);

    @override
    StickyOverscrollPhysics applyTo(ScrollPhysics? ancestor) {
    return StickyOverscrollPhysics(
    itemHeight: itemHeight,
    itemLength: itemLength,
    parent: buildParent(ancestor),
    );
    }

    // Ensure one item remains visible at min/max boundaries.
    double _visibleBoundary(ScrollMetrics position) {
    return itemHeight;
    }

    @override
    double applyBoundaryConditions(ScrollMetrics position, double value) {
    print("<value $value> <pixels ${position.pixels}> <ExtentInside ${position.extentInside}>");
    // If scrolling past the upper limit.
    if ( position.extentInside < _visibleBoundary(position)+70) {//minScrollExtent=0.0 maxScrollExtent=157.257..
    return -1;
    }
    // If scrolling past the lower limit.
    if ( position.extentInside > _visibleBoundary(position)-70) {
    return 0;
    }
    return 0.0; // No boundary condition violation.
    }


    @override
    double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
    // Apply friction only beyond the scroll extents to make overscroll smooth.
    if (position.pixels < position.minScrollExtent ||
    position.pixels > position.maxScrollExtent) {
    final overscrollFraction = (offset.abs() / maxOverscrollExtent).clamp(0.0, 1.0);
    return offset * (1 - _overscrollFriction(overscrollFraction));
    }
    return offset; // Normal scrolling without friction.
    }

    double _overscrollFriction(double overscrollFraction) {
    return 0.05 + (0.85 * math.pow(overscrollFraction, 1.5));
    }

    @override
    Simulation? createBallisticSimulation(ScrollMetrics position, double velocity) {
    if (position.pixels < position.minScrollExtent ||
    position.pixels > position.maxScrollExtent) {
    return ClampingScrollSimulation(
    position: position.pixels,
    velocity: velocity,
    tolerance: Tolerance(
    velocity: 1.0 / (0.05 * WidgetsBinding.instance.window.devicePixelRatio),
    ),
    );
    }
    return super.createBallisticSimulation(position, velocity);
    }

    @override
    bool shouldAcceptUserOffset(ScrollMetrics position) => true;
    }



    With this code I have achieve smooth scrolling even when over-scrolling, it don't bounce back as expected. Now I want the first item of the list to be visible at the bottom of the viewport when over-scrolled or the last item of the list to be visible at the top of the viewport when over-scrolled. I think the problem is from applyBoundaryConditions method. Sometimes I get errors like this when scrolling:

    FlutterError (StickyOverscrollPhysics.applyBoundaryConditions returned invalid overscroll value. The method was called to consider a change from 139.94798592776687 to 175.10397097851407, which is a delta of 35.2 units. However, it returned an overscroll of 45.8 units, which has a greater magnitude than the delta. The applyBoundaryConditions method is only supposed to reduce the possible range of movement, not increase it. The scroll extents are 0.0 .. 349.25714285714287, and the viewport dimension is 674.7428571428571.)

    Continue reading...

Compartilhe esta Página