I am currently trying to figure out how to implement the BLoC pattern in a simple TodoList. I am now facing some issues and am not quite sure why. Seems to come from the "TodoBlocProvider" and shows up when I add a new Todo in "add_task_page". I know its a lot of code and probably not the best you have seen, but if someone can help me it would be really nice and very much appreciated.
Git Repo
I found your issue, let me know if it helped
replace your main.dart by the following
import 'package:flutter/material.dart';
import 'package:todo_v2/TodoBlocProvider.dart';
//import 'package:todo_v2/TodoViewModel.dart';
import 'package:todo_v2/add_task_page.dart';
//import 'package:todo_v2/database.dart';
import 'package:todo_v2/listview.dart';
import 'package:todo_v2/todo_bloc.dart';
//import 'package:uuid/uuid.dart';
//import 'Todo.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TodoBlocProvider(
todoBloc: TodoBloc(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: 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> {
// int _index = 0;
#override
Widget build(BuildContext context) {
final todoBloc = TodoBlocProvider.of(context);
return Scaffold(
backgroundColor: Colors.blueGrey,
appBar: AppBar(
title: Text(widget.title),
),
body: StreamBuilder(
stream: todoBloc.todoList,
builder: (BuildContext context, snapData) {
if (snapData.hasData) {
print("hasdata ${snapData.data.length}");
return CustomListView(todos: snapData.data);
} else {
return Container(
child: Text("nodata"),
);
}
}),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => NewTodoPage()));
}),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
notchMargin: 4.0,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
icon: Icon(Icons.event),
onPressed: (){},
),
IconButton(
icon: Icon(Icons.event_available),
onPressed: (){})
],
),
)
);
}
}
Related
I wrote basic BlocProvider where there is no navigation, but still, I am getting below error
Error: Could not find the correct Provider above this
CounterPage Widget
Here is the link to the reproducible project on GitHub.
In short, you can just wrap the child in Builder as follows or create a new StatelessWidget or StatefulWidget for the child.
Providers injects the objects to the child element. It turns out the BuildContext object from build() is before the CounterBloc is injected.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:japa_counter/counter_widget/counter_widget.dart';
import 'counter_widget/model/counter_model.dart';
import 'counter_widget/bloc/counter_bloc.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: 'Japa Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const CounterPage(),
);
}
}
class CounterPage extends StatelessWidget {
const CounterPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocProvider<CounterBloc>(
create: (_) => CounterBloc(),
// -------------------- Wrapped in Builder ----------------------
child: Builder(
builder: (context) => Scaffold(
appBar: AppBar(
title: const Text("Japa Counter"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: () =>
context.read<CounterBloc>().add(IncrementCounter()),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
const SizedBox(width: 60.0, child: Divider()),
FloatingActionButton(
onPressed: () =>
context.read<CounterBloc>().add(DecrementCounter()),
tooltip: 'Decrement',
child: const Icon(Icons.remove),
),
const CounterWidget(),
],
),
),
)
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
I'm trying to use Markdown (from package flutter_markdown: ^0.6.6) in a dialog box. Following example returns error:
RenderShrinkWrappingViewport does not support returning intrinsic
dimensions.
This is my code:
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
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(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Package flutter_markdown'),
),
body: Center(
child: HelpButtonWithDialog(
title: 'markdown test',
content: '# Help Text\n\n* Text line 1\n*Text Line 2',
),
),
);
}
}
class HelpButtonWithDialog extends StatelessWidget {
final String title;
final String content;
HelpButtonWithDialog({
required this.title,
required this.content,
});
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.help_outline),
onPressed: () => showDialog(
barrierDismissible: true,
context: context,
builder: (BuildContext ctx) => AlertDialog(
title: Text(title),
content: Markdown(
data: content,
shrinkWrap: true,
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
)
],
),
),
);
}
}
I found a workaround by using Dialog and copying parts from AlertDialog. I also filed an enhancement request https://github.com/flutter/flutter/issues/89464 to the Flutter team to get this proper.
Here is the workaround code:
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
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(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Package flutter_markdown'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'flutter_markdown: Please add example how to use in showDialog'),
Text('https://github.com/flutter/flutter/issues/89464'),
HelpButtonWithDialog(
title: 'markdown test',
content: '# Help Text\n\n* Text line 1\n* Text Line 2',
),
],
),
),
);
}
}
class HelpButtonWithDialog extends StatelessWidget {
final String title;
final String content;
HelpButtonWithDialog({
required this.title,
required this.content,
});
#override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final DialogTheme dialogTheme = DialogTheme.of(context);
return IconButton(
icon: Icon(Icons.help_outline),
onPressed: () => showDialog(
barrierDismissible: true,
context: context,
builder: (BuildContext ctx) => Dialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.fromLTRB(24.0, 24.0, 24.0, 24.0),
child: DefaultTextStyle(
style:
dialogTheme.titleTextStyle ?? theme.textTheme.headline6!,
child: Text(title),
),
),
MarkdownBody(
data: content,
shrinkWrap: true,
),
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK'),
),
],
),
),
),
);
}
}
Child has an error, I tried invcache/restart, cache restart, nothing happens!!
enter image description here
Try this,let me know it is work for you
Code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: 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>[
TextButton(
onPressed: () {
_handleClickMe();
},
child: Text(
"CLICK ME!",
),
)
],
),
),
);
}
Future<void> _handleClickMe() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text('Alert'),
content: Text("Are you Sure"),
actions: <Widget>[
CupertinoDialogAction(
child: Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
),
CupertinoDialogAction(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
This should do the trick for you:
showDialog(
context: context,
builder: (BuildContext context){
return CupertinoAlertDialog(
...
)
}
)
you didn't implement builder: (BuildContext, context){ return Widget}
let me know if this works for you :)
I'm trying to get my head around the Providers in Flutters... but after following some tutorials, I'm still facing some issue.
When I try to run this code, it gives me an error
Error: Could not find the correct Provider above this MyHomePage Widget
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_way/MyHomePageViewModel.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 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 ChangeNotifierProvider(
create: (context) => MyHomePageViewModel(),
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Consumer<MyHomePageViewModel>(
builder: (context, viewModel, child) {
return Text(viewModel.text);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () =>
Provider.of<MyHomePageViewModel>(context, listen: false)
.onClicked(),
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
),
);
}
}
import 'package:flutter/foundation.dart';
class MyHomePageViewModel extends ChangeNotifier {
String text = 'Initial text';
void onClicked() {
text = 'Something was clicked';
notifyListeners();
}
}
The website where I found this example use it as
Provider.of<MainViewModel>(context, listen: false).onClicked(),
But that doesn't work either...
Before a widget that needs a provider is presented, it is required you create that particular provider before the page is built.
Checkout the working sample of your code below.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_way/MyHomePageViewModel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => MyHomePageViewModel(),
builder: (_, __) => MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: 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>[
Consumer<MyHomePageViewModel>(
builder: (context, viewModel, child) {
return Text(viewModel.text);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () =>
Provider.of<MyHomePageViewModel>(context, listen: false)
.onClicked(),
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
import 'package:flutter/foundation.dart';
class MyHomePageViewModel extends ChangeNotifier {
String text = 'Initial text';
void onClicked() {
text = 'Something was clicked';
notifyListeners();
}
}
In your provider code, do you have a class defined like:
class MyHomePageViewModel extends ChangeNotifier {
// your stuff here, like getter and setters, methods, etc
}
That class will deal with all the centralisation of your states, essentially acting as you'd hope - the provider.
i want to dial this number as it is, in flutter url launcher but it removes the hashtag sign in the last bit of the String,
onTap: () {
String no = '*477*4*1#';
launch('tel:$no');
},
You can copy paste run full code below
You can use Uri.encodeComponent('*477*4*1#');
code snippet
onPressed: () {
String no = Uri.encodeComponent('*477*4*1#');
launch('tel:$no');
},
working demo
full code
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: 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> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('click'),
onPressed: () {
String no = Uri.encodeComponent('*477*4*1#');
launch('tel:$no');
},
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
You need to use URL Encoding for special character so # is equals to \%23.