From 2eb10f3ba31d6ca2182abc9c6b6cb0db585dbfa9 Mon Sep 17 00:00:00 2001 From: David Peters <8vsxdxd@gmail.com> Date: Sat, 6 Mar 2021 11:41:29 +0100 Subject: [PATCH] Update README.md --- README.md | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 150 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1c6c2ae..0f343a6 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Stack( Parameter Implementation - Explanation + Example onDismiss @@ -71,14 +71,31 @@ Miniplayer(

Allows you to use a global ValueNotifier with the current progress. This can be used to hide the BottomNavigationBar.

+ + + controller + +
+final MiniplayerController controller = MiniplayerController();
+    
+Miniplayer( + controller: controller, +), +
+controller.animateToHeight(state: PanelState.MAX); +
+ + + ## Persistence -Implementing the miniplayer as described under [usage](https://pub.dev/packages/miniplayer#usage) - for instance by wrapping it in a stack alongside the `Scaffold` body - would work out of the box but has some disadvantages. If you push a new screen via `Navigator.push` the miniplayer would disappear. What we want is a persistent miniplayer which stays on every screen. +Implementing the miniplayer as described under [usage](https://pub.dev/packages/miniplayer#usage) - for instance by wrapping it inside a `Stack` in the `Scaffold` body - would work out of the box but has some disadvantages. If you push a new screen via `Navigator.push` the miniplayer would disappear. What we want is a persistent miniplayer which stays on the screen. -You have the option of two methods when it comes to archiving the miniplayer's persistent state, which depends on the use case. The first method is only recommended for simple apps and use cases. If you want to use dialogs or persistent widgets such as a BottomNavigationBar, use the second (slightly more advanced) method +If you want to archive persistency, you have the choice between two embedding options, which depends on your use case. The [first method](https://pub.dev/packages/miniplayer#first-method-simple) is only recommended for simple apps. If you want to use dialogs or other persistent widgets such as a BottomNavigationBar, the [second](https://pub.dev/packages/miniplayer#second-method-advanced) (slightly more advanced) method is the right fit for you. ## First method (Simple) +Using a `Stack` in the [builder](https://api.flutter.dev/flutter/material/MaterialApp/builder.html) method ```dart import 'package:flutter/material.dart'; import 'package:miniplayer/miniplayer.dart'; @@ -89,7 +106,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Miniplayer Demo', + title: 'Miniplayer example', theme: ThemeData( visualDensity: VisualDensity.adaptivePlatformDensity, ), @@ -117,9 +134,137 @@ class MyApp extends StatelessWidget { ``` ## Second method (Advanced) +Using a `Stack` in combination with a custom `Navigator` -[See example](https://pub.dev/packages/miniplayer/example) +```dart +import 'package:flutter/material.dart'; +import 'package:miniplayer/miniplayer.dart'; + +void main() => runApp(MyApp()); + +final _navigatorKey = GlobalKey(); + +class MyApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Miniplayer example', + debugShowCheckedModeBanner: false, + theme: ThemeData( + primaryColor: Color(0xFFFAFAFA), + ), + home: MyHomePage(), + ); + } +} + +class MyHomePage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MiniplayerWillPopScope( + onWillPop: () async { + final NavigatorState navigator = _navigatorKey.currentState; + if (!navigator.canPop()) return true; + navigator.pop(); + + return false; + }, + child: Scaffold( + body: Stack( + children: [ + Navigator( + key: _navigatorKey, + onGenerateRoute: (RouteSettings settings) => MaterialPageRoute( + settings: settings, + builder: (BuildContext context) => FirstScreen(), + ), + ), + Miniplayer( + minHeight: 70, + maxHeight: 370, + builder: (height, percentage) => Center( + child: Text('$height, $percentage'), + ), + ), + ], + ), + bottomNavigationBar: BottomNavigationBar( + currentIndex: 0, + fixedColor: Colors.blue, + items: [ + BottomNavigationBarItem( + icon: Icon(Icons.home), + label: 'Home', + ), + BottomNavigationBarItem( + icon: Icon(Icons.mail), + label: 'Messages', + ), + BottomNavigationBarItem( + icon: Icon(Icons.person), + label: 'Profile', + ) + ], + ), + ), + ); + } +} + +class FirstScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Demo: FirstScreen')), + body: Container( + constraints: BoxConstraints.expand(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: () => Navigator.push( + context, + MaterialPageRoute(builder: (context) => SecondScreen()), + ), + child: const Text('Open SecondScreen'), + ), + ElevatedButton( + onPressed: () => Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute(builder: (context) => ThirdScreen()), + ), + child: const Text('Open ThirdScreen with root Navigator'), + ), + ], + ), + ), + ); + } +} + +class SecondScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Demo: SecondScreen')), + body: Center(child: Text('SecondScreen')), + ); + } +} + +class ThirdScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Demo: ThirdScreen')), + body: Center(child: Text('ThirdScreen')), + ); + } +} +``` ## Roadmap +- [ ] Provide better examples - [ ] Add an option to handle horizontal gestures as well (like Spotify does) - [ ] Rewrite the API for onDismiss (breaking change) + - [x] Marked onDismiss ad deprecated