import "package:flutter/widgets.dart"; /// Wraps a scrollable panel body so content approaching the top or bottom /// edge fades to transparent over [fadeExtent] pixels instead of getting cut /// off flat by the scroll view's own default hard clip. Purely a paint /// effect - the scroll views clip still keeps everything contained, this /// just masks the alpha near each edge on top of that. /// /// Colour-blind on purpose: the gradient only carries alpha (dstIn blends /// against whatever's already painted), so it works unchanged over any panel /// background/scheme rather than needing its own colour token. class ScrollEdgeFade extends StatelessWidget { const ScrollEdgeFade({super.key, required this.child, this.fadeExtent = 6}); final Widget child; final double fadeExtent; @override Widget build(BuildContext context) { return ShaderMask( shaderCallback: (bounds) { // fraction of the box height the fade eats into from each end - a // fixed pixel extent thats clamped so a very short panel doesnt end // up with the two fades overlapping and cancelling out the middle. final fraction = bounds.height > 0 ? (fadeExtent / bounds.height).clamp(0.0, 0.5) : 0.0; return LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, stops: [0.0, fraction, 1 - fraction, 1.0], colors: const [ Color(0x00ffffff), Color(0xffffffff), Color(0xffffffff), Color(0x00ffffff), ], ).createShader(bounds); }, blendMode: BlendMode.dstIn, child: child, ); } }