How do I use a large title Navigation Bar in Flutter? - flutter

This is what I get when I use CupertinoNavigationBar()
Standard title Navigation Bar -
This is what I need to implement -

You can checkout this tutorial for the explanation but the code from the tutorial is:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return CupertinoApp(
title: 'Flutter Demo',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget{
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
child: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled){
return <Widget>[
CupertinoSliverNavigationBar(
largeTitle: Text('Settings'),
)
];
},
body: Center(child: Text('Home Page'),),
),
);
}
}
This code makes a large text an appbar with a large title like the following image:

Related

How to use ViewModelWidget in the onPressed callback of a button in Flutter?

I am trying to use the ViewModelWidget class from the stacked package. I am able to show the TextWidget which extends ViewModelWidget in the body of the page, but cannot show it in the bottom sheet because I am showing the bottom sheet from the onPressed function and that function does not have access to the view model.
Here is the code:
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyView(),
);
}
}
class MyViewModel extends BaseViewModel {
String title = 'Hello';
void updateTitle() {
title = 'Bye';
notifyListeners();
}
}
class MyView extends StatelessWidget {
const MyView({super.key});
#override
Widget build(BuildContext context) {
return ViewModelBuilder<MyViewModel>.reactive(
viewModelBuilder: () => MyViewModel(),
builder: (context, model, child) => Scaffold(
appBar: AppBar(
title: const Text('My View'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const TextWidget(),
ElevatedButton(
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return const SizedBox(child: Center(child: TextWidget(),), height: 200,);
},
);
},
child: const Text('Show Modal'),
),
],
),
),
);
}
}
class TextWidget extends ViewModelWidget<MyViewModel> {
const TextWidget({super.key});
#override
Widget build(BuildContext context, MyViewModel viewModel) {
return Text(viewModel.title);
}
}
And here's the error that happens when I try to open the bottom sheet:
How can I solve this error?
I think i got it
The .nonReactive constructor is best used for providing your ViewModel
to multiple child widgets that will make use of it. It was created to
make it easier to build and provide the same ViewModel to multiple
UI's. It was born out of the Responsive UI architecture where we would
have to provide the same ViewModel to all the different responsive
layouts.
As a result you should give a try to return ViewModelBuilder<HomeViewModel>.nonReactive(
Check the doc #Non Reactive : https://pub.dev/packages/stacked

Why am i getting No MediaQuery widget ancestor found .error

I have checked some threads here on StackOverlow but they dont fix my problem.The suggestions are
Create a new Stateless/Stateful widget and pass it to the home parameter OR
Use the Builder widget and pass it to the home parameter.
which I already did.
This is my main.dart file
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) {
ScreenUtil.init(context,designSize: Size(360,640));
return MaterialApp(
title: 'Flutter Demo',
home: HomeScreen()
);
}
}
And this is home.dart file
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Row(
children: [
buildLeftColumn(),
SizedBox(
width: 20.w,
),
// buildRightColumn(),
],
)),
);
}
buildLeftColumn() {
return Container();
}
So. what am i doing wrong.Could you please help
If you like to use ScreenUtil.init(...) you can solve this issue calling it on HomeScreen widget(context).
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
ScreenUtil.init(context, designSize: Size(360, 640));
To use it before MaterialApp you can use ScreenUtilInit widget.
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: Size(360, 640),
builder: (context, child) => MaterialApp(
title: 'Flutter Demo',
home: HomeScreen(),
),
);
}

Why does the column sitting on top each other?

I am pretty new in Dart and I have tried the following:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter App',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter App'),
),
body: Column(children: [
Card(
child: Text('CHART!!'),
),
Card(child: Text('LIST OF TX'),)
],),
);
}
}
output is:
Why the children of the column does not be placed next to each other?
Change the Column to Row if you want them to be next to each others horizontally.
To place the children next to each other use the Row widget which is very similar to Column. Please see the code below.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter App',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter App'),
),
body: Row(children: [
Card(
child: Text('CHART!!'),
),
Card(child: Text('LIST OF TX'),)
],),
);
}
}

Flutter Web Navigation with persistent drawer and appbar

I'm having still no success with my Flutter Web App, doing an URL based routing and keeping things like the appbar and the drawer persistent.
The goal I'm trying to achieve is, that I can only modify the content of my App. So i.e. if the user enters the url $baseurl/#/ it should navigate to the content of page one. $baseurl/#/two to the content of page two, and so on...
My main file is something like this. As you can see it's done with Fluro Router and I tried so simplify everything to see my main goal.
import 'package:flutter/material.dart';
import 'package:newnavigationtest/routes.dart';
void main() {
FluroRouter.setupRouter();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final navigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MainLayout(),
);
}
}
class MainLayout extends StatelessWidget {
final navigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: <Widget>[
Column(
children: [
Expanded(
child: Container(
color: Colors.green,
width: 100,
child: Text("Static sidebar"),
),
),
],
),
Expanded(
child: Navigator(
key: navigatorKey,
initialRoute: '/',
onGenerateRoute: FluroRouter.router.generator,
),
)
],
),
);
}
}
The FluroRouter file looks like this
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
class FluroRouter {
static Router router = Router();
static Handler _routeOneHandler = Handler(
handlerFunc: (BuildContext context, Map<String, dynamic> params) =>
Container(child: Center(child: Text("Later content for page 1"))));
static Handler _routeTwoHandler = Handler(
handlerFunc: (BuildContext context, Map<String, dynamic> params) =>
Container(child: Center(child: Text("Later content for page 2"))));
static void setupRouter() {
router.define(
'/',
handler: _routeOneHandler,
);
router.define(
'/two',
handler: _routeTwoHandler,
);
}
}
Clearly, if the user enters a URL nothing happens at the moment. I think this is because the main navigator in the MaterialApp is consuming the input from the user and not passing it through to my Navigator in the Scaffold. But I'm absolutely not sure.
Can anybody point me the right way to achieve the wanted behavior?
Thanks!
Update 1:
I also tried something like using the builder to build the child and keep the rest persistent.
(This leads me to the behavior I'm looking for, except for the OverLay Error)
import 'package:flutter/material.dart';
import 'package:newnavigationtest/routes.dart';
void main() {
FluroRouter.setupRouter();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final navigatorKey = GlobalKey<NavigatorState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
key: navigatorKey,
initialRoute: '/',
onGenerateRoute: FluroRouter.router.generator,
builder: (context, child) {
return MainLayout(child: child);
},
);
}
}
class MainLayout extends StatelessWidget {
final Widget child;
MainLayout({#required this.child});
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: <Widget>[
Column(
children: [
Expanded(
child: Container(
color: Colors.green,
width: 100,
child:
Tooltip(message: "Hello", child: Text("Static sidebar")),
),
),
],
),
Expanded(
child: child,
)
],
),
);
}
}
But this leads to a missing Overlay at the tooltip.
════════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building Tooltip("Hello", dirty, state: _TooltipState#93c0f(ticker inactive)):
No Overlay widget found.
Tooltip widgets require an Overlay widget ancestor for correct operation.
Because Fluro redirects without persistence, you may have to have each page have a Scaffold with an AppBar and Drawer, most efficient way would to have a custom scaffold you could re-use.
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';
void main() {
FluroRouter.setupRouter();
runApp(
MaterialApp(
title: 'Your website',
onGenerateRoute: FluroRouter.router.generator
),
);
}
class CustomScaffold extends StatelessWidget {
final Widget body;
CustomScaffold({this.body});
#override
Widget build(BuildContext context) {
return Scaffold(
//your appbar here
appBar: AppBar(),
//your drawer here
drawer: Drawer(),
body: body,
);
}
}
class FluroRouter {
static Router router = Router();
static Handler _routeOneHandler = Handler(
handlerFunc: (BuildContext context, Map<String, dynamic> params) => PageOne());
static Handler _routeTwoHandler = Handler(
handlerFunc: (BuildContext context, Map<String, dynamic> params) => PageTwo());
static void setupRouter() {
router.define(
'/',
handler: _routeOneHandler,
);
router.define(
'/two',
handler: _routeTwoHandler,
);
}
}
class PageOne extends StatelessWidget {
Widget build(BuildContext context) {
return CustomScaffold(
body: Container(child: Text('Page 1')),
);
}
}
class PageTwo extends StatelessWidget {
Widget build(BuildContext context) {
return CustomScaffold(
body: Container(child: Text('Page 2')),
);
}
}

Flutter Provider: Why does this error happens when calling Provider.of<Widget>(context) like tihis:

I'm new to flutter and I'm testing Provider and can't figure out why doing this works (by work i mean it shows a list in the appbar):
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
builder: (context)=> Data(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: CustomText(),
),
),
),
);
}
}
With a CustomText class that does practically nothing:
class CustomText extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Text(Provider.of<Data>(context).texts.tostring());
}
}
But this other thing throws a - Could not find the correct Provider above this MyApp Widget - Error:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
builder: (context)=> Data(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(Provider.of<Data>(context).texts.toString()),
),
),
),
);
}
}
The Data class is :
class Data with ChangeNotifier{
List<String> _texts = ['Text 1', 'Text 2', 'Text 3', 'Text 4',];
get texts {
return _texts;
}
void deleteText(int index){
this._texts.removeAt(index);
notifyListeners();
}
void addText(String text){
this._texts.add(text);
notifyListeners();
}
}
I just can not see what is the difference or why that matters. Shouldn't that code be equivalent? Any insight will be much appreciated.
The difference is that in the CustomText case, context is from its parent widget which is MyApp, whereas in the second case, context is from MyApp's parent. Since your Provider is implemented inside MyApp, it cannot find the provider if you use MyApp's parent's context (the second case)