Introduced MiniplayerWillPopScope as a drop-in replacement for WillPopScope to work with a nested architecture

This commit is contained in:
David 2021-01-16 09:34:09 +01:00
parent 6918f18f8a
commit 23628f7b2a
2 changed files with 71 additions and 1 deletions

View File

@ -3,8 +3,11 @@ library miniplayer;
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:miniplayer/src/miniplayer_will_pop_scope.dart';
import 'package:miniplayer/src/utils.dart';
export 'package:miniplayer/src/miniplayer_will_pop_scope.dart';
///Type definition for the builder function
typedef Widget MiniplayerBuilder(double height, double percentage);
@ -142,7 +145,7 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
Widget build(BuildContext context) {
if (dismissed) return Container();
return WillPopScope(
return MiniplayerWillPopScope(
onWillPop: () async {
if (heightNotifier.value > widget.minHeight) {
_snapToPosition(PanelState.MIN);

View File

@ -0,0 +1,67 @@
import 'package:flutter/material.dart';
class MiniplayerWillPopScope extends StatefulWidget {
const MiniplayerWillPopScope({
Key key,
@required this.child,
@required this.onWillPop,
}) : assert(child != null),
super(key: key);
final Widget child;
final WillPopCallback onWillPop;
@override
_MiniplayerWillPopScopeState createState() => _MiniplayerWillPopScopeState();
static _MiniplayerWillPopScopeState of(BuildContext context) {
return context.findAncestorStateOfType<_MiniplayerWillPopScopeState>();
}
}
class _MiniplayerWillPopScopeState extends State<MiniplayerWillPopScope> {
ModalRoute<dynamic> _route;
_MiniplayerWillPopScopeState _descendant;
set descendant(state) {
_descendant = state;
updateRouteCallback();
}
Future<bool> onWillPop() async {
bool willPop;
if (_descendant != null) {
willPop = await _descendant.onWillPop();
}
if (willPop == null || willPop) {
willPop = await widget.onWillPop();
}
return willPop;
}
void updateRouteCallback() {
_route?.removeScopedWillPopCallback(onWillPop);
_route = ModalRoute.of(context);
_route?.addScopedWillPopCallback(onWillPop);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
var parentGuard = MiniplayerWillPopScope.of(context);
if (parentGuard != null) {
parentGuard.descendant = this;
}
updateRouteCallback();
}
@override
void dispose() {
_route?.removeScopedWillPopCallback(onWillPop);
super.dispose();
}
@override
Widget build(BuildContext context) => widget.child;
}