Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
161 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import 'package:flutter/widgets.dart'; | ||
import 'package:flutter/rendering.dart'; | ||
|
||
extension ScrollControllerExtensions on ScrollController { | ||
void handleScrollForFab(AnimationController hideFabController) { | ||
print(position.userScrollDirection); | ||
print(position.pixels); | ||
print(position.atEdge); | ||
switch (position.userScrollDirection) { | ||
case ScrollDirection.idle: | ||
break; | ||
case ScrollDirection.forward: | ||
hideFabController.forward(); | ||
break; | ||
case ScrollDirection.reverse: | ||
hideFabController.reverse(); | ||
break; | ||
} | ||
|
||
if (position.pixels == 0 && position.atEdge) { | ||
//User is at the top, so lets hide the fab | ||
hideFabController.reverse(); | ||
} | ||
} | ||
|
||
void goToTheTop() => animateTo(0, duration: const Duration(milliseconds: 500), curve: Curves.easeInOut); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,57 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
import '../../common/extensions/scroll_controller_extensions.dart'; | ||
import '../widgets/characters/character_detail.dart'; | ||
import '../widgets/common/app_fab.dart'; | ||
|
||
class CharacterPage extends StatelessWidget { | ||
class CharacterPage extends StatefulWidget { | ||
const CharacterPage({Key key}) : super(key: key); | ||
|
||
@override | ||
_CharacterPageState createState() => _CharacterPageState(); | ||
} | ||
|
||
class _CharacterPageState extends State<CharacterPage> with SingleTickerProviderStateMixin { | ||
ScrollController _scrollController; | ||
AnimationController _hideFabAnimController; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
|
||
_scrollController = ScrollController(); | ||
_hideFabAnimController = AnimationController( | ||
vsync: this, | ||
duration: kThemeAnimationDuration, | ||
value: 0, // initially not visible | ||
); | ||
_scrollController.addListener(() => _scrollController.handleScrollForFab(_hideFabAnimController)); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
body: SafeArea( | ||
child: SingleChildScrollView( | ||
child: Stack( | ||
fit: StackFit.passthrough, | ||
clipBehavior: Clip.none, | ||
children: const [CharacterDetailTop(), CharacterDetailBottom()], | ||
)), | ||
controller: _scrollController, | ||
child: Stack( | ||
fit: StackFit.passthrough, | ||
clipBehavior: Clip.none, | ||
children: const [CharacterDetailTop(), CharacterDetailBottom()], | ||
), | ||
), | ||
), | ||
floatingActionButton: AppFab( | ||
hideFabAnimController: _hideFabAnimController, | ||
scrollController: _scrollController, | ||
), | ||
); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_scrollController.dispose(); | ||
_hideFabAnimController.dispose(); | ||
super.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
import '../../../common/extensions/scroll_controller_extensions.dart'; | ||
|
||
class AppFab extends StatelessWidget { | ||
final ScrollController scrollController; | ||
final AnimationController hideFabAnimController; | ||
|
||
const AppFab({ | ||
Key key, | ||
@required this.scrollController, | ||
@required this.hideFabAnimController, | ||
}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return FadeTransition( | ||
opacity: hideFabAnimController, | ||
child: ScaleTransition( | ||
scale: hideFabAnimController, | ||
child: FloatingActionButton( | ||
backgroundColor: Theme.of(context).primaryColor, | ||
mini: true, | ||
onPressed: () => scrollController.goToTheTop(), | ||
heroTag: null, | ||
child: const Icon(Icons.arrow_upward), | ||
), | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import 'package:flutter/material.dart'; | ||
|
||
import '../../../common/extensions/scroll_controller_extensions.dart'; | ||
import 'app_fab.dart'; | ||
|
||
class SliverScaffoldWithFab extends StatefulWidget { | ||
final List<Widget> slivers; | ||
|
||
const SliverScaffoldWithFab({ | ||
Key key, | ||
@required this.slivers, | ||
}) : super(key: key); | ||
|
||
@override | ||
_SliverScaffoldWithFabState createState() => _SliverScaffoldWithFabState(); | ||
} | ||
|
||
class _SliverScaffoldWithFabState extends State<SliverScaffoldWithFab> with SingleTickerProviderStateMixin { | ||
ScrollController _scrollController; | ||
AnimationController _hideFabAnimController; | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
|
||
_scrollController = ScrollController(); | ||
_hideFabAnimController = AnimationController( | ||
vsync: this, | ||
duration: kThemeAnimationDuration, | ||
value: 0, // initially not visible | ||
); | ||
_scrollController.addListener(() => _scrollController.handleScrollForFab(_hideFabAnimController)); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
body: CustomScrollView( | ||
controller: _scrollController, | ||
slivers: widget.slivers, | ||
), | ||
floatingActionButton: AppFab( | ||
hideFabAnimController: _hideFabAnimController, | ||
scrollController: _scrollController, | ||
), | ||
); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
_scrollController.dispose(); | ||
_hideFabAnimController.dispose(); | ||
super.dispose(); | ||
} | ||
} |