Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 35 additions & 41 deletions lib/src/fading_edge_scrollview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@ class FadingEdgeScrollView extends StatefulWidget {
class FadingEdgeScrollViewState extends State<FadingEdgeScrollView>
with WidgetsBindingObserver {
late ScrollController _controller;
_ScrollState _scrollState = _ScrollState.notScrollable;

double _offsetFromStart = 0;
double _offsetFromEnd = 0;

int lastScrollViewListLength = 0;

@override
Expand Down Expand Up @@ -202,7 +205,11 @@ class FadingEdgeScrollViewState extends State<FadingEdgeScrollView>

@override
Widget build(BuildContext context) => ShaderMask(
shaderCallback: (bounds) => _createShaderGradient().createShader(
shaderCallback: (bounds) => _createShaderGradient(
widget.scrollDirection == Axis.vertical
? bounds.height
: bounds.width)
.createShader(
bounds.shift(Offset(-bounds.left, -bounds.top)),
textDirection: Directionality.of(context),
),
Expand All @@ -220,7 +227,7 @@ class FadingEdgeScrollViewState extends State<FadingEdgeScrollView>
),
);

Gradient _createShaderGradient() => LinearGradient(
Gradient _createShaderGradient(double size) => LinearGradient(
begin: _gradientStart,
end: _gradientEnd,
stops: [
Expand All @@ -229,11 +236,16 @@ class FadingEdgeScrollViewState extends State<FadingEdgeScrollView>
1 - widget.gradientFractionOnEnd * 0.5,
1,
],
colors: _getColors(
widget.gradientFractionOnStart > 0 &&
_scrollState.isShowGradientAtStart,
widget.gradientFractionOnEnd > 0 &&
_scrollState.isShowGradientAtEnd),
colors: <Color>[
widget.gradientFractionOnStart > 0
? fadeInColor(_offsetFromStart, size * widget.gradientFractionOnStart)
: Colors.white,
Colors.white,
Colors.white,
widget.gradientFractionOnEnd > 0
? fadeInColor(_offsetFromEnd, size * widget.gradientFractionOnEnd)
: Colors.white
]
);

AlignmentGeometry get _gradientStart =>
Expand All @@ -258,12 +270,16 @@ class FadingEdgeScrollViewState extends State<FadingEdgeScrollView>
? AlignmentDirectional.centerStart
: AlignmentDirectional.centerEnd;

List<Color> _getColors(bool showGradientAtStart, bool showGradientAtEnd) => [
(showGradientAtStart ? Colors.transparent : Colors.white),
Colors.white,
Colors.white,
(showGradientAtEnd ? Colors.transparent : Colors.white)
];
Color fadeInColor(double offsetFromEdge, double threshold) {
if (offsetFromEdge <= 0) {
return Colors.white;
}
if (offsetFromEdge >= threshold) {
return Colors.transparent;
}
int alpha = 255 - (255 * offsetFromEdge / threshold).round();
return Color.fromARGB(alpha, 255, 255, 255);
}

void _updateScrollState() {
if (!_controllerIsReady) {
Expand All @@ -274,35 +290,13 @@ class FadingEdgeScrollViewState extends State<FadingEdgeScrollView>
final minOffset = _controller.positions.last.minScrollExtent;
final maxOffset = _controller.positions.last.maxScrollExtent;

final isScrolledToEnd = offset >= maxOffset;
final isScrolledToStart = offset <= minOffset;

final scrollState = switch ((isScrolledToStart, isScrolledToEnd)) {
(true, true) => _ScrollState.notScrollable,
(true, false) => _ScrollState.scrollableAtStart,
(false, true) => _ScrollState.scrollableAtEnd,
(false, false) => _ScrollState.scrollableInTheMiddle
};

if (_scrollState != scrollState) {
final offsetFromStart = offset - minOffset;
final offsetFromEnd = maxOffset - offset;
if (offsetFromStart != _offsetFromStart || offsetFromEnd != _offsetFromEnd) {
setState(() {
_scrollState = scrollState;
_offsetFromStart = offsetFromStart;
_offsetFromEnd = offsetFromEnd;
});
}
}
}

enum _ScrollState {
notScrollable,
scrollableAtStart,
scrollableAtEnd,
scrollableInTheMiddle;

bool get isShowGradientAtStart =>
this == _ScrollState.scrollableAtEnd ||
this == _ScrollState.scrollableInTheMiddle;

bool get isShowGradientAtEnd =>
this == _ScrollState.scrollableAtStart ||
this == _ScrollState.scrollableInTheMiddle;
}