Flutter desktop web DraggableScrollableSheet scrolling problem - flutter

There is a strange behavior in Flutter I faced recently that I can not explain. Consider the following code being built for WEB platform:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Hello World',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
const MyHomePage({this.title = "Home Page"});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: const Center(
child: Text(
'Hello, World!',
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) => DraggableScrollableSheet(
expand: false,
builder: (_, ScrollController scrollController) {
return ListView(
controller: scrollController,
children: [for (var i = 0; i < 250; i++) Text("Item: $i")],
);
},
),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
),
tooltip: "Open Sheet!",
child: const Icon(Icons.add),
),
);
}
}
It works perfectly fine and as expected when opened from mobile device: the DraggableScrollableSheet gets opened, takes 50% of the screen height, and then the ListView inside it may be scrolled along with Sheet itself, so it will take from 0% to 100% of the screen.
However, if opened in desktop browser, the DraggableScrollableSheet just refuses to be scrolled together with ListView on mouse wheel rotation. It just sticks to 50% and can only be closed and never expanded!
An I missing something? Is it a flutter bug? How do I make it work in desktop browsers as expected?
P.S. here is a slightly more complex example of the behavior in my app, hosted on GitHub pages; for ModalBottomSheet to get opened, you should touch Flutter icon in the center of St. Petersburg.

This is probably a bug, you can work around this problem using the following parameter (next to "Expand"): "initialChildSize: 1.0"
This will set the initial size to 100% DraggableScrollableSheet parameters

Related

Flutter Navigator and Routing in separate files showing error: Could not find a generator for route RouteSettings("/details", null) in the _Widget

I am working on this Flutter app and trying to make routing works on separate files. Now I have a login page, and in it, there is a login button. When this login button is clicked, the app should navigate to the HomePage. I looked at a few tutorials, but they all put navigators and other widgets on the same page.
In my case, my file structure is:
and in routes.dart:
import 'package:flutter/material.dart';
import 'widgets/login.dart';
import 'widgets/homepage.dart';
void main() {
runApp(Nav2App());
}
class Nav2App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => Login(),
'/homepage': (context) => HomePage(),
},
);
}
}
In login.dart:
child: TextButton(
style: ButtonStyle(
...
))),
child: const Text('Login'),
onPressed: () {
Navigator.pushNamed(
context,
'/homepage',
);
},
),
),
I think I need to do something in main.dart, like:
Widget build(BuildContext context) {
return MaterialApp(
// debugShowCheckedModeBanner: false,
title: 'Flutter Login Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyLoginPage(title: 'login page'),
routes: ***something***
);
}
You will want to replace the login page with the homepage. So use push replacement. That way they won’t get a back button in the top left.
As you said you updated the /details to /homepage in the comments above. But still not working make sure you do a full reload not just a hot reload.
Navigator.pushReplacementNamed(context, "/homepage");
Do not make a second material app in your your code like shows above. When you create another material app you also get a whole new navigator stack.
Use Scaffold instead. 1 material app is all you need.
class Nav2App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => Login(),
'/homepage': (context) => HomePage(),
},
);
}
}
There is no navigator for your /details name.
Change your login code like below:
child: TextButton(
style: ButtonStyle(
...
))),
child: const Text('Login'),
onPressed: () {
Navigator.pushNamed(
context,
'/homepage',
);
},
),
),

How to achieve a smooth transition from exiting and closing Flutter applications with ListViews

I'm simply trying to archive a behaviour like this:
https://streamable.com/vnvxt0
When a scroll is performed, notice how it sort of fades in and out after exiting and returning to the application.
On the other hand, with a flutter application, it doesn't behave in such this way. Rather it forces itself to the correct scroll position:
https://streamable.com/omztmj
A minimal code example would be the Flutter Hello world app with a Listview.builder()
void main() {
runApp(MyApp());
}
// Root class called by the runApp() method.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.light,
),
home: Scaffold(
appBar: AppBar(),
body: ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.ac_unit),
title: Text(
'test',
),
);
},
itemCount: 50,
),
),
);
}
}
Any form of help would be appreciated.

Browser top bar does not scroll with content

When displaying a flutter app from a browser (chrome in this example) on a mobile device, the browser's app bar does not scroll off screen when the content of the page is scrolled. Is there a way to achieve that scroll?
This question regards to Flutter Web only
Demo
Here is a comparison between a flutter demo app and a simple search results page on Google. You can see how the app bar doesn't move in the first example but does move on the search results page.
Code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
final List<ListTile> _list = List.generate(50, (index) {
return ListTile(
title: Text('Hello World $index'),
);
});
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Material(
child: ListView(
children: _list,
),
),
);
}
}

Flutter Transition Animation Issue while pushing new screen on Bottom Navigation Bar

I have a MaterialApp in which it has an IndexedStack as its homePage, to use it for BottomBarNavigation. Now, in one of the "Tab"s, I want page transitions to be done like it is done in iOS.
Part of the trick can be done using CupertinoPageRoute in Navigator.push as follows:
Navigator.of(context, rootNavigator: true).push(CupertinoPageRoute<bool>(
//fullscreenDialog: true,
builder: (BuildContext context) => new DescriptionPage(),
));
this results the new page to slide from right as an iOS app. But, I also want the first page to be shifted to right with parallax, as it says in the CupertinoPageRoute's documentation:
The page also shifts to the left in parallax when another page enters to cover it.
this will be done if the first page itself is created via "Navigator.push(CupertinoPageRoute ...", but as I mentioned, my first page is one of the main pages of the application's home.
current transition style:
the new page slides in from right, but the current page does not shift to left
as you can see, the current page does not shift to left. There might be a way to make the current page's widget to act as a widget built by a CupertinoPageRoute, so that the current page itself slides to left as the new page comes in.
In the theme: parameter of MaterialApp, try this:
MaterialApp(
theme: ThemeData( //or replace with your custom ThemeData.copywith()
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder()
}
),
),
)
If you run the code below, you will see that First Tab is doing what you are seeing and second Tab is what you are expecting.
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CupertinoStoreHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class CupertinoStoreHomePage extends StatelessWidget {
const CupertinoStoreHomePage({title});
#override
Widget build(BuildContext context) {
return CupertinoTabScaffold(
tabBar: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.bell),
title: Text('TAB1'),
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.bell_solid),
title: Text('TAB2'),
),
],
),
tabBuilder: (context, index) {
switch (index) {
case 0:
return CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: TAB1(),
);
});
case 1:
return CupertinoTabView(
builder: (context) {
return CupertinoPageScaffold(
child: TAB2(),
);
},
routes: {
'/screen': (ctx) => NextScreen(),
},
);
default:
return Container();
}
},
);
}
}
class TAB1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("TAB1"),
),
body: Container(
child: FlatButton(
child: Text("Go To Next Screen"),
onPressed: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => NextScreen())),
),
),
);
}
}
class TAB2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("TAB2"),
),
body: Container(
child: FlatButton(
child: Text("Go To Next Screen"),
onPressed: () => Navigator.of(context).pushNamed("/screen"),
)),
);
}
}
class NextScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: Scaffold(
appBar: AppBar(
title: Text("NextScreen"),
),
body: Container(
child: Text("NextScreen"),
),
),
);
}
}
When using Navigator.of(ctx).push the app tries to push new screen on root navigator, which in your case is tab bar but it fails to replace the tab bar, hence you see incomplete animation. But with second approach where you have defined route in relevant tab and use Push Named, the app uses navigator assigned to that tab and hence expected result.
Happy Coding!

Flutter not navigating to next page context error?

This is my code what i am doing it that on tap i need to go to another page ,but i am getting an error Navigator operation requested with a context that does not include a Navigator.
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final title = 'SHA-WAY';
var FirstPage = ['SURGERIES','OPERTAION THEATER TECHNICIAN','DRESSINGS OR BANDAGES','PHYSIOTHERAPY','NURSE MALE|FEMALE',
'HOSPITAL LINEN OR STAFF UNIFORM','MEDICENS(ONLY RARE INJECTIONS)','OPERATION THEATRE INSTRUMENTS|EQUIPEMENTS'];
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
child: GridView.count(
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this produces 2 rows.
crossAxisCount: 2,
children: [
Card(
child: InkWell(
onTap: (){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => surgeries()),
);
},
splashColor: Colors.blue,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.content_cut,size: 60.0,),
Text(FirstPage[0]),
],
)
),
),
),
This is the class where i want to navigate,
import 'package:flutter/material.dart';
class surgeries extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SURGERIES"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
don't know what i am doing wrong just started FLUTTER and i am stuck
You can use the approach shown in the official doc,
You have to define the routes in the main.dart
MaterialApp(
// Start the app with the "/" named route. In this case, the app starts
// on the FirstScreen widget.
initialRoute: '/',
routes: {
// When navigating to the "/" route, build the FirstScreen widget.
'/': (context) => FirstScreen(),
// When navigating to the "/second" route, build the SecondScreen widget.
'/second': (context) => SecondScreen(),
},
);
Then you can navigate to the First screen to another on onTap or onPressed event like this,
Navigator.pushNamed(context, '/second');
Note: You should only have one MaterialApp in your whole app.
For more head over to official Page
Your all classes should be descendant of MaterialApp widget, to achieve that, wrap your class that placed on runApp method with MaterialApp widget, then remove all of other MaterialApp widgets from your widget tree.
void main() {
runApp(MaterialApp(home:MyApp));
}
Just tried this and work!
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'example',
debugShowCheckedModeBanner: false,
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
buttonTheme: ButtonThemeData(
buttonColor: Colors.blue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
textTheme: ButtonTextTheme.primary
)
),
home: Esempio1()
);
}
}
class Esempio1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("WAKAWAKA"),
),
body: Container(
child: Column(
children: <Widget>[
RaisedButton(
child: Text("aasdasd"),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (_)=> Esempio2()));
},
)
],
),
),
);
}
}
class Esempio2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("eheh"),
),
body: Container(
child: Text("AAAAA"),
),
);
}
}