Show snack bar to handling missing URL receivers - flutter

I used the url_luncher package and it suggests handle the missing URL receiver in case of target platform can not handle the URL.
So I create a function to handle of onTap of CardTile widget and dial the phone number and if the target platform can not handle the request it shows a snake bar to inform the user in UI.
But I have two problems 1) if using an anonymous function I get a runtime error and my code would be wordly and long
Unhandled Exception: No ScaffoldMessenger widget found.
MyApp widgets require a ScaffoldMessenger widget ancestor.
The specific widget that could not find a ScaffoldMessenger ancestor was:
MyApp
The ancestors of this widget were:
[root]
Typically, the ScaffoldMessenger widget is introduced by the MaterialApp at the top of your application widget tree.
if use function name onTap of CardTile widget for example onTap : _urlLauncherFunction(context) I can not pass BuildContext context argument to the function and get a compile error
This expression has a type of 'void' so its value can't be used.
I could not figure out what did wrong so please guide and help me to solve this.
I paste the anonymous function version here
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
final telLaunchErrorSnackBar = SnackBar(
content:
Text('Your device can not handle this url'));
final String _myPhoneNumber = '+9812345678';
//use xml scheme to trigger error otherwise it should be tel
final Uri _telUri = Uri(scheme: 'xml', path: _myPhoneNumber);
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Column(
children: [
CircleAvatar(
backgroundImage: AssetImage('images/image.jpg'),
),
Card(
child: ListTile(
leading: Icon(
Icons.phone,
),
title: Text(
'00 123 45657',
),
onTap: () async {
String telUri = _telUri.toString();
await canLaunch(telUri)
? await launch(telUri)
: ScaffoldMessenger.of(context)
.showSnackBar(telLaunchErrorSnackBar);
},
),
),
],
),
),
),
);
}
}

When I code as this , flutter throw a error.
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: MyHomePage(title: 'Flutter Demo Home Page'),
home: Scaffold(
body: SafeArea(
child: Container(
alignment: Alignment.center,
child: GestureDetector(
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
onTap: (){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('content')));
},
),
),
),
),
);
}
}
then I change
...
MaterialApp(
home:Scafford(...),
)
...
to
...
MaterialApp(
home:Home(),
)
...
class Home extends StatelessWidget {
#override
Widget build(BuildContext context){
return Scaffold(...);
}
}
It works.

Related

Why do I have to remove const from MaterialApp if I use a theme?

First, here is an example without using a theme. I can put const on MaterialApp.
import 'package:flutter/material.dart';
void main() {
runApp(const _MyApp());
}
class _MyApp extends StatelessWidget {
const _MyApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp( // 👈 const
home: Scaffold(
body: Center(
child: Text(
"Demo",
),
),
),
);
}
}
Next, here is an example of using the theme.
It is no longer possible to put const on MaterialApp.
Instead, only Scaffold has const.
import 'package:flutter/material.dart';
void main() {
runApp(const _MyApp());
}
class _MyApp extends StatelessWidget {
const _MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp( // 👈 remove const
theme: ThemeData(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
),
home: const Scaffold( // 👈 const
body: Center(
child: Text(
"Demo",
),
),
),
);
}
}
Why do I have to remove const from MaterialApp if I use a theme?
Does this simply mean that the theme cannot be determined at compile time?
Since I am only specifying the color, it seems like it could be determined at compile time.
For example, if it is text, I can leave the const attached to MaterialApp as shown below.
import 'package:flutter/material.dart';
void main() {
runApp(const _MyApp());
}
class _MyApp extends StatelessWidget {
const _MyApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text(
"Demo",
style: TextStyle(color: Colors.red),
),
),
),
);
}
}
ThemeData doesn't have a const constructor, this is because the constructor atually has an inner logic to change some internal values, if you want to use const you can use the other constructor ThemeData.raw but you will need to pass all the required values:
import 'package:flutter/material.dart';
void main() {
runApp(const _MyApp());
}
class _MyApp extends StatelessWidget {
const _MyApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
theme: ThemeData.raw(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
/// it will ask you to complete the constructor
),
home: Scaffold(
body: Center(
child: Text(
"Demo",
),
),
),
);
}
}
TLDR: for a const constructor to work you need that all it's parameters are const values but ThemeData is not.

Dart Flutter display Icons

Im writing my first code and I want to display a Icon, and I try to use the command Icon (Icons.star, color: Colors.red, size: 100, ),. But it doesn't work. Can somebody help me. Thx
Welcome to Stackoverflow.
Try the following code. Your above code is also correct.
Try to check below line in your pubspec.yaml file
flutter:
uses-material-design: true
Refer Flutter Icons
Full Example:
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: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Icon(
Icons.star,
color: Colors.red,
size: 100,
),
);
}
}
Result screen->
You can also test the code on Dartpad.

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"),
),
);
}
}

No able to get the latest state of an object using provider

I am trying get the latest state of the name variable from the Home class, but I am getting a null instead of the value Tenzin Nyidon. I initialize the name variable inside the build method of the MyHomePage as you can see, and set the notifyListeners() method (which notify all listeners) inside the onPress of Navigate button.
main.dart:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<MyHomePage>(builder: (_) => MyHomePage(),)
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget with ChangeNotifier {
String name;
#override
Widget build(BuildContext context) {
//* Here I intialized the name variabel
name = "Tenzin Nyidon";
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(name),
RaisedButton(
child: Text("Navigate"),
onPressed: (){
//* notify all listener
notifyListeners();
Navigator.of(context).push(
MaterialPageRoute(
builder: (_){
return Home();
}
)
);
},
)
],
),
),
);
}
}
home.dart:
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
var provider = Provider.of<MyHomePage>(context);
return Scaffold(
body: Center(
//! I am getting a null value here
child: Text("name from the main.dart: ${provider.name}"),
),
);
}
}
try to not create a provider with a stateless widget because it can't update its state.
and also you have to create a method to handle changes and then call changeNotifier();
such as:
class MyProvider extends ChangeNotifier {
String name;
void changeName(String newValue){
name = newValue;
}
}
and then call in provider:
To change value:
Provider.of<MyProvider>(context).changeName(newValue);
To read it:
Provider.of<MyProvider>(context).name;

Flutter Web persistent header

With the introduction of flutter for web it has me trying to achieve a website style header that is persistent when using routes and across the entire app. Appbar doesn't appear to be the solution since each scaffold has its own appBar. I've created the header widget that's in a Column with the MaterialApp. However, this implementation feels wrong as everything should be a child of MaterialApp or CupertinoApp.
If the searchBar header can be placed within the MaterialApp and I'm able to use Navigator that's would be preferred. I'm really here for guidance and the "right" way to do this.
void main() {
initKiwi();
// BlocSupervisor().delegate = AppBlocDelegate();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Material(
elevation: 2.0,
color: Colors.white,
child: MediaQuery(
data: MediaQueryData.fromWindow(ui.window),
child: Directionality(
textDirection: TextDirection.ltr,
child: Container(
height: 50,
child: SearchBar(),
),
),
),
),
Expanded(
child: MaterialApp(
title: 'Discover Brindle',
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: 'Brdl',
),
home: Text("Pages & Routes Here"),
),
),
]);
}
}
Though it's not using routes I was able to solve this using IndexedStack. This also preserves any scrolling I've done in the ProductsPage() when closing the search page. The AppBar is persistent and was able to keep the code to a minimum.
main.dart
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Discover Brindle',
theme: ThemeData(
primarySwatch: Colors.blue,
fontFamily: 'Brdl'
),
home: MainPage(),
);
}
}
main_page.dart
class MainPage extends StatefulWidget {
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
final _searchBloc = kiwi.Container().resolve<SearchBloc>();
final _productsBloc = kiwi.Container().resolve<ProductsBloc>();
PageController pageController;
int currentPage = 0;
void _onSearchActive({bool isActive}) {
setState(() {
this.currentPage = isActive ? 1 : 0;
});
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: _buildScaffold(),
);
}
Widget _buildScaffold() {
return BlocProviderTree(
blocProviders: [
BlocProvider<SearchBloc>(bloc: _searchBloc),
BlocProvider<ProductsBloc>(bloc: _productsBloc),
],
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: SearchBar(onIsActive: _onSearchActive),
),
body: IndexedStack(
children: [
ProductsPage(),
SearchPage(),
],
index: currentPage,
),
),
);
}
}