-
Notifications
You must be signed in to change notification settings - Fork 108
/
Copy pathsliver_fill_remaining.dart
127 lines (108 loc) · 3.57 KB
/
sliver_fill_remaining.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';
import 'diagram_step.dart';
import 'fake_drag_scroll_activity.dart';
import 'utils.dart';
const Duration _kScrollUpDuration = Duration(seconds: 1);
const Duration _kScrollPauseDuration = Duration(seconds: 1);
final Duration _kTotalDuration =
_kScrollPauseDuration + _kScrollUpDuration + _kScrollPauseDuration;
class SliverFillRemainingDiagram extends StatefulWidget with DiagramMetadata {
const SliverFillRemainingDiagram({super.key});
@override
String get name => 'sliver_fill_remaining_fill_overscroll';
@override
State<StatefulWidget> createState() => _SliverFillRemainingDiagramState();
@override
Duration? get duration => _kTotalDuration;
}
class _SliverFillRemainingDiagramState extends State<SliverFillRemainingDiagram>
with TickerProviderStateMixin, LockstepStateMixin {
_SliverFillRemainingDiagramState();
final ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
SchedulerBinding.instance.scheduleFrameCallback((Duration _) {
_play();
});
}
@override
void didUpdateWidget(SliverFillRemainingDiagram oldWidget) {
super.didUpdateWidget(oldWidget);
_scrollController.jumpTo(0.0);
SchedulerBinding.instance.scheduleFrameCallback((Duration _) {
_play();
});
}
Future<void> _play() async {
await waitLockstep(_kScrollPauseDuration);
await _animate(to: 400.0, duration: _kScrollUpDuration);
await waitLockstep(_kScrollPauseDuration);
}
Future<void> _animate({required double to, required Duration duration}) {
final ScrollPositionWithSingleContext position =
_scrollController.position as ScrollPositionWithSingleContext;
final FakeDragScrollActivity activity = FakeDragScrollActivity(
position,
from: _scrollController.offset,
to: to,
duration: duration,
curve: Curves.easeIn,
vsync: this,
);
_scrollController.position.beginActivity(activity);
return activity.done;
}
@override
Widget build(BuildContext context) {
List<Widget> slivers;
slivers = <Widget>[
SliverToBoxAdapter(
child: Container(color: Colors.tealAccent[700], height: 150.0),
),
SliverFillRemaining(
hasScrollBody: false,
fillOverscroll: true,
child: Container(
color: Colors.teal[100],
child: Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: OutlinedButton(
onPressed: () {},
child: const Text('Bottom Pinned Button!'),
),
),
),
),
),
];
return Container(
color: Colors.white,
height: 500.0,
width: 250.0,
child: Scaffold(
appBar: AppBar(title: const Text('SliverFillRemaining')),
body: CustomScrollView(
physics: const BouncingScrollPhysics(),
controller: _scrollController,
slivers: slivers,
),
),
);
}
}
class SliverFillRemainingDiagramStep extends DiagramStep {
@override
final String category = 'widgets';
@override
Future<List<SliverFillRemainingDiagram>> get diagrams async =>
<SliverFillRemainingDiagram>[const SliverFillRemainingDiagram()];
}