Skip to content

Commit

Permalink
Added some fabs
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Jan 5, 2021
1 parent 893b5bc commit 89b9c41
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 9 deletions.
27 changes: 27 additions & 0 deletions lib/common/extensions/scroll_controller_extensions.dart
@@ -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);
}
3 changes: 2 additions & 1 deletion lib/ui/pages/artifacts_page.dart
Expand Up @@ -12,6 +12,7 @@ import '../widgets/artifacts/artifact_info_card.dart';
import '../widgets/common/loading.dart';
import '../widgets/common/sliver_nothing_found.dart';
import '../widgets/common/sliver_page_filter.dart';
import '../widgets/common/sliver_scaffold_with_fab.dart';

class ArtifactsPage extends StatefulWidget {
@override
Expand All @@ -31,7 +32,7 @@ class _ArtifactsPageState extends State<ArtifactsPage> with AutomaticKeepAliveCl
builder: (context, state) {
return state.map(
loading: (_) => const Loading(),
loaded: (state) => CustomScrollView(
loaded: (state) => SliverScaffoldWithFab(
slivers: [
SliverPageFilter(
search: state.search,
Expand Down
48 changes: 42 additions & 6 deletions lib/ui/pages/character_page.dart
@@ -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();
}
}
3 changes: 2 additions & 1 deletion lib/ui/pages/characters_page.dart
Expand Up @@ -11,6 +11,7 @@ import '../widgets/characters/character_card.dart';
import '../widgets/common/loading.dart';
import '../widgets/common/sliver_nothing_found.dart';
import '../widgets/common/sliver_page_filter.dart';
import '../widgets/common/sliver_scaffold_with_fab.dart';

class CharactersPage extends StatefulWidget {
@override
Expand All @@ -30,7 +31,7 @@ class _CharactersPageState extends State<CharactersPage> with AutomaticKeepAlive
builder: (context, state) {
return state.map(
loading: (_) => const Loading(),
loaded: (state) => CustomScrollView(
loaded: (state) => SliverScaffoldWithFab(
slivers: [
SliverPageFilter(
search: state.search,
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/pages/weapons_page.dart
Expand Up @@ -10,6 +10,7 @@ import '../../models/weapons/weapon_card_model.dart';
import '../widgets/common/loading.dart';
import '../widgets/common/sliver_nothing_found.dart';
import '../widgets/common/sliver_page_filter.dart';
import '../widgets/common/sliver_scaffold_with_fab.dart';
import '../widgets/weapons/weapon_bottom_sheet.dart';
import '../widgets/weapons/weapon_card.dart';

Expand All @@ -30,7 +31,7 @@ class _WeaponsPageState extends State<WeaponsPage> with AutomaticKeepAliveClient
builder: (context, state) {
return state.map(
loading: (_) => const Loading(),
loaded: (state) => CustomScrollView(
loaded: (state) => SliverScaffoldWithFab(
slivers: [
SliverPageFilter(
search: state.search,
Expand Down
31 changes: 31 additions & 0 deletions lib/ui/widgets/common/app_fab.dart
@@ -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),
),
),
);
}
}
55 changes: 55 additions & 0 deletions lib/ui/widgets/common/sliver_scaffold_with_fab.dart
@@ -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();
}
}

0 comments on commit 89b9c41

Please sign in to comment.