Flutter flutter_zoom_drawer - flutter

I am watching a tutorial on youtube (https://youtu.be/Evu19gTKaFo) to build a menu for my mobile application. I followed the steps but I had a problem when I ran the application:
-how it's supposed to look: goodLook
-how it's actually looking:
badLook
import 'package:flutter/material.dart';
import 'package:flutter_zoom_drawer/config.dart';
import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart';
import 'main_screen.dart';
import 'menu_page.dart';
class Dashboard extends StatefulWidget {
const Dashboard({Key? key}) : super(key: key);
#override
State<Dashboard> createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return const ZoomDrawer(
style: DrawerStyle.style1,
mainScreen: MainScreen(),
menuScreen: MenuPage(),
);
}
}
import 'package:dashboard/menu_widget.dart';
import 'package:flutter/material.dart';
import 'package:authentication/authentication.dart';
import 'package:firebase_auth/firebase_auth.dart';
class MainScreen extends StatefulWidget {
const MainScreen({Key? key}) : super(key: key);
#override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: const Text('Main page'),
leading: const MenuWidget(),
),
body: ElevatedButton(
onPressed: _signOut,
child: const Text('Logout'),
),
);
}
Future<void> _signOut() async {
await FirebaseAuth.instance.signOut();
if (!mounted) {
return;
}
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => const Authentication()),
(route) => false);
}
}
import 'package:flutter/material.dart';
class MenuPage extends StatelessWidget {
const MenuPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) => const Scaffold(
backgroundColor: Colors.indigo,
);
}
import 'package:flutter/material.dart';
import 'package:flutter_zoom_drawer/flutter_zoom_drawer.dart';
class MenuWidget extends StatelessWidget {
const MenuWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return IconButton(
icon: const Icon(Icons.menu),
onPressed: () => ZoomDrawer.of(context)!.toggle(),
);
}
}
I've been searching for a solution but I couldn't find it. If you know how to solve this problem, please help me.
Thank you!

Problem solved:
ZoomDrawer(
controller: z,
borderRadius: 24,
style: DrawerStyle.defaultStyle,
openCurve: Curves.fastOutSlowIn,
slideWidth: MediaQuery.of(context).size.width * 0.65,
duration: const Duration(milliseconds: 500),
menuBackgroundColor: Colors.indigo,
mainScreen: MainScreen(),
menuScreen: MenuPage(),
)
https://github.com/medyas/flutter_zoom_drawer/issues/105

Related

Unable to naviagte to another screen in flutter

I'm trying to take value from the method channel and using the value I'm trying to navigate another screen. When I try to navigate from TextButton onclick it's navigating but when I try to navigate from the value received by the method channel it's not navigating to another screen.
Example: I'm receiving openScreen1 from the method channel in the below code from methodCall.method and assigning the method to route variable but the page is not navigating
main_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gg_app/screen1.dart';
import 'package:gg_app/screen2.dart';
class HomeScreen extends StatefulWidget {
static const routeName = "Home-Screen";
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
static const channel = MethodChannel('scribeemr.in/mic');
#override
void initState() {
// TODO: implement initState
channel.setMethodCallHandler(nativeMethodCallHandler);
super.initState();
}
Future<dynamic> nativeMethodCallHandler(MethodCall methodCall) async {
var route = methodCall.method;
await navigateTo(route, context);
}
Future<dynamic> navigateTo(String route, BuildContext context) async {
switch (route) {
case "openScreen1":
await Navigator.of(context).pushNamed(Screen1.routeName);
break;
case "openScreen2":
await Navigator.of(context).pushNamed(Screen2.routeName);
break;
default:
break;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Home Screen")),
body: Column(
children: [
TextButton(
onPressed: () {
navigateTo("openScreen1", context);
},
child: Text("Screen 1")),
TextButton(
onPressed: () {
navigateTo("openScreen2", context);
},
child: Text("Screen 2")),
],
),
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:gg_app/home_screen.dart';
import 'package:gg_app/screen1.dart';
import 'package:gg_app/screen2.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomeScreen(),
routes: {
HomeScreen.routeName: (context) => HomeScreen(),
Screen1.routeName: (context) => Screen1(),
Screen2.routeName: (context) => Screen2(),
},
);
}
}
screen1.dart
import 'package:flutter/material.dart';
class Screen1 extends StatefulWidget {
static const routeName = "Screen1";
const Screen1({ Key? key }) : super(key: key);
#override
State<Screen1> createState() => _Screen1State();
}
class _Screen1State extends State<Screen1> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Screen 1")),
);
}
}

How does the "event" parameter contain data? What should I do if I want to create my "onHover"?

I have a simple flutter application. It's ok, but I'm trying to understand how onHover: (event){...} works, why "event" contains data? How can I make my own widget have function parameters like that?
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
double dx = 0, dy = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
home: Scaffold(
body: MouseRegion(
onHover: (event) {
setState(() {
dx = event.localPosition.dx;
dy = event.localPosition.dy;
});
},
child: Center(
child: Text('$dx'),
),
),
),
);
}
}
To create your own onChange, or the like we can use ValueChanged.
For example, taking a look at the code for a TextButton() we see:
const TextButton({
Key? key,
required VoidCallback? onPressed,
VoidCallback? onLongPress,
ValueChanged<bool>? onHover,
the onHover uses a ValueChanged.
You can implement your own valueChanged using this example:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Buttons(
onHover: (value) {
// Do something
print(value);
},
),
),
),
);
}
}
class Buttons extends StatelessWidget {
final ValueChanged<String> onHover;
Buttons({Key? key, required this.onHover}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
TextButton(
onPressed: () {
onHover('Pressed');
},
child: Text("Click me")),
Text('hi')
],
);
}
}
So this how we pass the data from the widget which is at the bottom of the widget tree.
It's more related to passing the value from bottom to top using callback functions.
Below is the simple example to demonstrate this data sharing.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _parentData = 0;
#override
Widget build(BuildContext context) {
return Column(
children: [
Text(
"Parent State Value: " + _parentData.toString(),
),
ChildWidgetExample(
callbackFn: (data) {
setState(() {
_parentData = data;
});
},
)
],
);
}
}
class ChildWidgetExample extends StatefulWidget {
final Function(int) callbackFn;
const ChildWidgetExample({
Key? key,
required this.callbackFn,
}) : super(key: key);
#override
State<ChildWidgetExample> createState() => _ChildWidgetExampleState();
}
class _ChildWidgetExampleState extends State<ChildWidgetExample> {
int data = 0;
#override
Widget build(BuildContext context) {
return Column(
children: [
Text(
data.toString(),
),
const SizedBox(
height: 30,
),
ElevatedButton(
onPressed: () {
setState(() {
data++;
});
widget.callbackFn(data);
},
child: const Text("Press"),
)
],
);
}
}
In Flutter you can declare Functions with parameters.
void Function(String foo) myFunction;
So you declare in as a variable in your widget component.
MyWidget({required this.myFunction});
Then when you have to call this component you can write :
...
child : MyWidget(myFunction: (String foo) {},),

Flutter - Update child state from parent

I would like to update a child's state when a button is clicked in the parent, so for example:
class Parent extends StatelessWidget{
Widget build(context){
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () => //somehow increment the child's counter,
icon: const Icon(Icons.add),
),
],
),
body: const Child(),
);
}
}
class Child extends StatefulWidget {
const Child({Key? key}) : super(key: key);
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
...
int counter = 0; //to be incremented when parent's button is clicked on.
...
}
Is there a common way to implement this? From the other posts I've read, people usually use the child to update the parent's state via callback, so if there is a way to refactor my code to acheive the same effect, that would help too.
You can create the field counter in the parent and pass it down to the child widget and update the child widget from the parent.
You can check the demo that I made here..
DartPad Demo Link
statemanagement Method
You can use provider,bloc,cubit,getx... package to update the child and parent value
setstate callback (here i mention)
Change you widget like this .your parent widget to stateful.
int counter = 0;
class Parent extends StatefulWidget {
#override
State<Parent> createState() => _ParentState();
}
class _ParentState extends State<Parent> {
Widget build(context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () {
setState(() {
counter++;
});
},
icon: const Icon(Icons.add),
),
],
),
body: Child(),
);
}
}
class Child extends StatefulWidget {
Child({Key? key}) : super(key: key);
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
#override
Widget build(BuildContext context) {
return Center(child: Text("$counter",style: TextStyle(fontSize: 30),));
} //to be incremented when parent's button is clicked on.
SampleCod Dartpad live code check here
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Parent(),
);
}
}
class Parent extends StatefulWidget {
#override
State<Parent> createState() => _ParentState();
}
class _ParentState extends State<Parent> {
Widget build(context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
onPressed: () {
setState(() {
counter++;
});
},
icon: const Icon(Icons.add),
),
],
),
body: Child(),
);
}
}
int counter = 0;
class Child extends StatefulWidget {
Child({Key? key}) : super(key: key);
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
#override
Widget build(BuildContext context) {
return Center(child: Text("$counter",style: TextStyle(fontSize: 30),));
} //to be incremented when parent's button is clicked on.
}
Try this:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: Parent(),
);
}
}
class Parent extends StatefulWidget {
const Parent({Key? key}) : super(key: key);
#override
State<Parent> createState() => _ParentState();
}
class _ParentState extends State<Parent> {
int counter = 0;
void incrementCounter() {
setState(() {
counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
tooltip: "Increment counter",
onPressed: incrementCounter,
icon: const Icon(
Icons.add,
),
),
],
),
body: Child(
counter: counter,
),
);
}
}
class Child extends StatefulWidget {
const Child({
Key? key,
required this.counter,
}) : super(key: key);
final int counter;
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child> {
#override
Widget build(BuildContext context) {
return Center(
child: Text(
widget.counter.toString(),
style: const TextStyle(
fontSize: 30,
),
),
);
}
}

Black screen when calling Navigator.popUntil()

I am making a Flutter app where I navigate from the home screen to other pages. I then want to go back to the home screen by popping the Navigator stack. When I do this I get a black screen and I assume I pop until the stack is empty. I do not however understand where my mistake is.
In page2.dart, if I replace the Navigator.popUntil() call with two calls to Navigator.pop(context) after each other, it pops successfully back to the home screen.
To demonstrate the issue I have I made a stand alone application that has this behavior.
main.dart
import 'package:flutter/cupertino.dart';
import 'package:test/router.dart' as router;
import 'package:flutter/widgets.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return const CupertinoApp(
title: 'Test',
initialRoute: router.home,
onGenerateRoute: router.generateRoute);
}
}
router.dart
import 'package:flutter/cupertino.dart';
import 'package:test/home.dart';
import 'package:test/page1.dart';
import 'package:test/page2.dart';
import 'package:flutter/widgets.dart';
const home = '/';
const page1 = '/page1';
const page2 = '/page2';
Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case home:
return CupertinoPageRoute(builder: (context) => const Home());
case page1:
return CupertinoPageRoute(builder: (context) => const Page1());
case page2:
return CupertinoPageRoute(builder: (context) => const Page2());
default:
print('Undefined view');
return CupertinoPageRoute(
builder: (context) => UndefinedView(
name: settings.name ?? 'No Name',
));
}
}
class UndefinedView extends StatelessWidget {
final String name;
const UndefinedView({Key? key, required this.name}) : super(key: key);
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Center(
child: Text('Route for $name is not defined'),
),
);
}
}
home.dart
import 'package:flutter/cupertino.dart';
import 'package:test/router.dart' as router;
import 'package:flutter/widgets.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
CupertinoButton(
child: const Text(
'Go to page 1',
style: TextStyle(color: Color.fromRGBO(0xFF, 0xFF, 0xFF, 1)),
),
onPressed: () => {Navigator.pushNamed(context, router.page1)},
),
Container(
height: 50,
)
],
));
}
}
page1.dart
import 'package:flutter/cupertino.dart';
import 'package:test/router.dart' as router;
import 'package:flutter/widgets.dart';
class Page1 extends StatefulWidget {
const Page1({Key? key}) : super(key: key);
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
CupertinoButton(
child: const Text(
'Go to Page 2',
style: TextStyle(color: Color.fromRGBO(0xFF, 0xFF, 0xFF, 1)),
),
onPressed: () => {Navigator.pushNamed(context, router.page2)},
),
Container(
height: 50,
)
],
));
}
}
page2.dart
import 'package:flutter/cupertino.dart';
import 'package:test/router.dart' as router;
import 'package:flutter/widgets.dart';
class Page2 extends StatefulWidget {
const Page2({Key? key}) : super(key: key);
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
CupertinoButton(
child: const Text(
'Go home',
style: TextStyle(color: Color.fromRGBO(0xFF, 0xFF, 0xFF, 1)),
),
onPressed: () =>
{Navigator.popUntil(context, ModalRoute.withName(router.home))},
),
Container(
height: 50,
)
],
));
}
}
When returning CupertinoPageRoute inside generateRoute, try passing settings too, i.e.
return CupertinoPageRoute(
settings: settings,
builder: (context) => const Home()
);
or
return CupertinoPageRoute(
settings: const RouteSettings(name: home),
builder: (context) => const Home()
);
I believe otherwise the Navigator is not aware of the route names, which causes popUntil to pop until there are no more routes (thus the black screen).

Flutter pageview navigate

How can I use pageController.jumptopage(0) method on button in Page3.dart ? Is it possible? Full example code:
main.dart file
import 'package:flutter/material.dart';
import 'package:test_app/page1.dart';
import 'package:test_app/page2.dart';
import 'package:test_app/page3.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late PageController pageController;
int selectedPage = 0;
final List<Widget> pagesList = [const Page1(), const Page2(), const Page3()];
#override
void initState() {
super.initState();
pageController = PageController();
}
#override
void dispose() {
pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: PageView(
controller: pageController,
children: pagesList,
onPageChanged: (index) {
setState(() => selectedPage = index);
},
),
);
}
}
Page3.dart file
import 'package:flutter/material.dart';
class Page3 extends StatelessWidget {
const Page3({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.red,
),
child: ElevatedButton(
child: const Text('Button'),
onPressed: () {
// pageController.jumptopage(0); <<< use this
}),
);
}
}