How to navigate tab from another dart file button tap event? - flutter

How to navigate tab from another dart file button tap event? I am using Tabmanager. It only works with the same dart file.
I am having error in
TabManager._myTabbedPageKey.currentState._tabController
.animateTo(1);
main.dart
void main() {
runApp(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 MaterialApp(
home: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
children: [
new TabA(),
new TabB(),
],
),
),
),
);
}
}
class TabManager extends StatefulWidget {
static final _myTabbedPageKey = new GlobalKey<_MyAppState>();
#override
_TabManagerState createState() => _TabManagerState();
}
class _TabManagerState extends State<TabManager> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: new MyApp(
key: TabManager._myTabbedPageKey,
),
);
}
}
Here tabA.dart is a separate dart file.
An error shows like
The getter '_myTabbedPageKey' isn't defined for the type 'TabManager'.
tabA.dart
class TabA extends StatefulWidget {
#override
_TabAState createState() => _TabAState();
}
class _TabAState extends State<TabA> {
#override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
onTap: () {
TabManager._myTabbedPageKey.currentState._tabController
.animateTo(1);
},
child: Text('taba')),
);
}
}

Try to This Code very similar
working demo
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(text: 'Home'),
Tab(text: 'Messages',),
Tab(text: 'Call'),
],
),
title: Text('MY App'),
),
body: TabBarView(
children: [
new Home(),
new Messages(),
new Call()
],
),
),
),
);
}
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child:
Text('Home',
style: TextStyle(fontSize: 21),)
)
)
);
}
}
class Messages extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child:
Text('Meassage',
style: TextStyle(fontSize: 21),)
)
)
);
}
}
class Call extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child:
Text('Call',
style: TextStyle(fontSize: 21),)
)
)
);
}
}

Related

Cant remove Debug Show Checked Banner

I used the debugShowCheckedModeBanner: false, code to remove the debug banner and it had worked fine with all of my previous apps. But now when I used this code only the shadow under debug banner get removed.
Here's my code
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(
debugShowCheckedModeBanner: false,
home: HomeScreen(),
);
}
}
I have attached the images link of debugShowCheckedModeBanner: false, and debugShowCheckedModeBanner: true,below.
How can I remove this debug banner completely, please help!
Try below code hope its help to you.
Remove MaterialApp Widget from HomeScreen Class
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: HomeScreen(),
),
),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('E Com App'),
),
body: Container(
color: Colors.red,
height: 200,
width: double.infinity,
child: Text(
'Red Container',
style: TextStyle(
fontSize: 30,
color: Colors.white,
),
),
),
);
}
}
Your Result Screen->
If you want MaterialApp Widget in HomeScreen class then add below line inside MaterialApp in HomeScreen Class.
debugShowCheckedModeBanner: false,
Full Widget:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: HomeScreen(),
),
),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('E Com App'),
),
body: Container(
color: Colors.red,
height: 200,
width: double.infinity,
child: Text(
'Red Container',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
);
}
}
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
//this code add it
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: HomeScreen(),
),
),
);
}
}

Flutter - Slidable on whole page?

I'm trying to implement a sliding option that will basically, depending on if I go left or right, direct me to the previous/next message in my app (aka. trigger an action). It should work on the entire page, similar to how tinder slide left/right works. Is there any way to do this in flutter?
I've looked into the flutter_slidable but I'm not sure if I can make the sliding work on the whole page.
Would appreciate some help, thanks in advance!
You can use TabBarView for this:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main()
{
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Learning',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState()
{
return _MyHomePageState();
}
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(text: "Flights", icon: Icon(Icons.flight),),
Tab(text: "Trains", icon: Icon(Icons.train)),
Tab(text: "Hotels",icon: Icon(Icons.restaurant)),
],
),
title: Text('Flutter TabBar'),
),
body: TabBarView(
children: const <Widget>[
Center(
child: Text("Flights"),
),
Center(
child: Text("Trains"),
),
Center(
child: Text("Hotels"),
),
],
),
),
);
}
}
Link
Flutter PageView is used to slide pages either vertically or horizontally.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('PageView ')),
body: const MyStatelessWidget(),
),
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final PageController controller = PageController();
return PageView(
/// [PageView.scrollDirection] defaults to [Axis.horizontal].
/// Use [Axis.vertical] to scroll vertically.
scrollDirection: Axis.horizontal,
controller: controller,
children: const <Widget>[
Center(
child: Text('First Page'),
),
Center(
child: Text('Second Page'),
),
Center(
child: Text('Third Page'),
)
],
);
}
}

flutter: provider dosen't work in statefulwidget

I create a new flutter demo and modify it to use the provider package. But it doesn't work. And here is my code.
class MyState {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Provider<MyState>(
create: (_) => MyState(),
child: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Consumer<MyState>(
builder: (context, state, _) {
return Text(
"${state.cnt}",
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: Provider.of<MyState>(context, listen: false).increase,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
When press the button, the UI is not rebuilt. And as the printed messages show, the cnt field of Mystate had been changed. Why? May provider can not be used in statefulwidget?
Provider: You can use Provider to provide a value anywhere in the widget tree. It will not rebuild the widget tree whenever the value changes. It simply passes the model to its descendant's widget in the widget tree.
ChangeNotifierProvider: ChangeNotifierProvider listens for changes in the model object. It rebuilds the dependents widgets whenever ChangeNotifier.notifyListeners is called.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyState with ChangeNotifier {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
notifyListeners();
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyState>(
create: (context) => MyState(),
child: Scaffold(
appBar: AppBar(
title: Text("Page Title"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'You have pushed the button this many times:',
),
Consumer<MyState>(
builder: (context, counter, child) => Text(
'${counter.cnt}',
style: Theme.of(context).textTheme.display1,
),
),
],
),
),
floatingActionButton: Builder(builder: (context) {
return FloatingActionButton(
onPressed: Provider.of<MyState>(context, listen: false).increase,
tooltip: 'Increment',
child: Icon(Icons.add),
);
}),
),
);
}
}
You can copy paste run full code below
Step 1: MyState extends ChangeNotifier and use notifyListeners()
Step 2: Use ChangeNotifierProvider
code snippet
class MyState extends ChangeNotifier {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
...
home: ChangeNotifierProvider(
create: (_) => MyState(),
child: MyHomePage(title: 'Flutter Demo Home Page'),
working demo
full code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyState extends ChangeNotifier {
MyState();
int cnt = 0;
void increase() {
print("increase. $cnt");
cnt++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: ChangeNotifierProvider(
create: (_) => MyState(),
child: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Consumer<MyState>(
builder: (context, state, _) {
return Text(
"${state.cnt}",
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: Provider.of<MyState>(context, listen: false).increase,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Hero on Tab behavior after flutter version upgrade

After upgrading Flutter from 1.7.8 (I have tested 1.9.1 and 1.10.2), there is some strange behavior of hero for me... I have hero image on the main page. On the second/detail page I have two tabs, first with hero, second empty.
(GoBack)From the first tab hero animation is working as expected, but (GoBack) from the second empty tab, image on the first page disappears. Is this expected behavior in newer versions?
[After some testing this hero tab behavior is from ˆ1.9.0 version, last ok 1.8.4]
Test code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Hero Test'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Hero(
tag: "hero",
child: Image.network("https://dummyimage.com/200x200/ff0329/fff"),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailPage()),
);
},
child: Icon(Icons.add),
),
);
}
}
class DetailPage extends StatefulWidget {
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(vsync: this, length: 2);
super.initState();
}
#override
void dispose() {
// TODO: implement dispose
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
bottom: TabBar(controller: _tabController, tabs: [
Tab(text: "1"),
Tab(text: "2"),
])),
body: TabBarView(controller: _tabController, children: <Widget>[
Column(
children: <Widget>[
Hero(
tag: "hero",
child: Image.network("https://dummyimage.com/200x200/ff0329/fff"),
),
],
),
Text(""),
]),
);
}
}
Bug... fixed in version v1.9.1+hotfix.6
more info https://github.com/flutter/flutter/issues/40239

How to keep the widget's state in Scaffold.drawer in Flutter?

I want to keep the widget's state in Scaffold.drawer. The Scaffold.drawer is a custom widget, which has a RaiseButton in it.
When click the button, the text in the button changed.
But when the drawer is closed, and reopen the drawer, the changed text is reseted.
I have use " with AutomaticKeepAliveClientMixin<> " in my custom Drawer, but it does't work.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter Demo"),
),
drawer: Drawer(child: CustomDrawer(),),
body: Center(
child: Text("Flutter Demo"),
),
);
}
}
class CustomDrawer extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _CustomDrawerState();
}
}
class _CustomDrawerState extends State<CustomDrawer> with AutomaticKeepAliveClientMixin<CustomDrawer> {
String btnText = "Click!";
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return Center(
child: RaisedButton(onPressed: () {
setState(() {
btnText = "Clicked!!";
});
}, child: Text(btnText),),
);
}
}
I expect the widget's state can keep, even if the Drawer is closed.
Create a separate widget for the drawer and just use in anywhere you need to.
Manage the Drawer State with a Provider
class DrawerStateInfo with ChangeNotifier {
int _currentDrawer = 0;
int get getCurrentDrawer => _currentDrawer;
void setCurrentDrawer(int drawer) {
_currentDrawer = drawer;
notifyListeners();
}
void increment() {
notifyListeners();
}
}
Adding State Management to the Widget tree
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
providers: <SingleChildCloneableWidget>[
ChangeNotifierProvider<DrawerStateInfo>(
builder: (_) => DrawerStateInfo()),
],
);
}
}
Creating The Drawer Widget for reuse in application
class MyDrawer extends StatelessWidget {
MyDrawer(this.currentPage);
final String currentPage;
#override
Widget build(BuildContext context) {
var currentDrawer = Provider.of<DrawerStateInfo>(context).getCurrentDrawer;
return Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text(
"Home",
style: currentDrawer == 0
? TextStyle(fontWeight: FontWeight.bold)
: TextStyle(fontWeight: FontWeight.normal),
),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.of(context).pop();
if (this.currentPage == "Home") return;
Provider.of<DrawerStateInfo>(context).setCurrentDrawer(0);
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) =>
MyHomePage(title: "Home")));
},
),
ListTile(
title: Text(
"About",
style: currentDrawer == 1
? TextStyle(fontWeight: FontWeight.bold)
: TextStyle(fontWeight: FontWeight.normal),
),
trailing: Icon(Icons.arrow_forward),
onTap: () {
Navigator.of(context).pop();
if (this.currentPage == "About") return;
Provider.of<DrawerStateInfo>(context).setCurrentDrawer(1);
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => MyAboutPage()));
},
),
],
),
);
}
}
Use of Drawer in one of your pages
class MyAboutPage extends StatefulWidget {
#override
_MyAboutPageState createState() => _MyAboutPageState();
}
class _MyAboutPageState extends State<MyAboutPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('About Page'),
),
drawer: MyDrawer("About"),
);
}
}
In your case, you have 2 choices:
You should keep your state in your Top level widget. in your case _MyHomePageState;
Use state managers like Redux, Bloc, ScopedModel. I think ScopedModel is great for you in this case.
otherwise, you can't control the state of Drawer. cause it re-creates every moment you call the Drawer by the action button in Appbar;