Missing concrete implementation of StatefulWidget - flutter

Missing concrete implementation of 'StatefulWidget.createState'.
Try implementing the missing method, or make the class abstract.
//code
import 'package: flutter/material dart';
void main() {
run App(my App())
}
class my App extends State less Widget {
#override
Widget build(Build Context context) {
return Material App(
home: Test(),
);
}
}
class Test extends State full Widget {
State <State full Widget> create state() {
return Test state ();
}
}
class Test state extends State<Test> {
Widget build(Build Context context) {
return Scaffold(
app Bar: App Bar(),
drawer: Drawer(),
body: Text("how are you"),
)
}
}
the text in body run

Do it this way, you are having space and brackets issue on question.
import 'package:flutter/material.dart';
void main() {
runApp(myApp());
}
class myApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Test(),
);
}
}
class Test extends StatefulWidget {
const Test({super.key});
#override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
drawer: Drawer(),
body: Text("how are you"),
);
}
}

Related

How to define variable inside of a text widget located in a separate dart file in Flutter

I have a messages.dart file that holds all the initial texts for different messages as Widgets.
Widget rest = Text('You should rest $restTime or $restTimeOr');
In the main.dart file, I'm defining the $restTime string value and in the column children, I want to call the rest widget from the messages.dart file.
class _HomePageState extends State<HomePage> {
String restTime = 'now';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
rest,
],
),
);
}
}
But it gives me the error in the messages.dart file that restTime is undefined. What am I missing here?
The complete main.dart file is:
import 'package:flutter/material.dart';
import 'example/messages.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String restTime = 'now';
String restTimeOr = '2 hours later';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
rest,
],
),
);
}
}
And the messages.dart file is:
import 'package:flutter/material.dart';
Widget rest = Text('You should rest $restTime or $restTimeOr');
You can create a RestMessageWidget in your messages.dart like this:
class RestMessageWidget extends StatelessWidget {
final String? restTime;
final String? restTimeOr;
RestMessageWidget({#required this.restTime, #required this.restTimeOr});
#override
Widget build(BuildContext context) {
return Text('You should rest $restTime or $restTimeOr');
}
}
You can then use the RestMessageWidget in main.dart like this:
class _HomePageState extends State<HomePage> {
String myRestTime = 'now';
String myRestTimeOr = '2 hours later';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
RestMessageWidget(restTime: myRestTime, restTimeOr: myRestTimeOr),
],
),
);
}
}
Define the rest message as a statelessWidget rather than a runtime instance. like this;
class RestMessage extends StatelessWidget {
final String text;
RestMessage(this.text);
#override
Widget build(BuildContext context) {
return Text(text)
}
}
and then use it in the main.dart like
Column...
children: [
RestMessage(restMessageWithTime),
],

How to implement Gesture detection - On Tap method in child class?

I want to implement the GestureDetector method onTapin child class. Is there a way to do it in Flutter ?
ParentClass.dart
Class ParentClass extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GestureDetector {
onTap: methodA,
child: ChildClass(),
}
}
ChildClass.dart
Class ChildClass extends StatefulWidget {
methodA() // need to access methodA which is being passed to gesture detector
// How do I access methodA of parent class method here
// so whenever GestureDetector's onTap method is called, i want to handle that in ChildClass is there a way to do it ?
}
You can access the Child State methods using a unique key. Here is a minimal example:
Inside the ParentWidget, we define _childKey, a GlobalKey<_ChildWidgetState> that we then can use to access the State's method updateValue as follows:
_childKey.currentState.updateValue('Goodbye, Thierry!'),
Full source code
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: ParentWidget()),
);
}
}
class ParentWidget extends StatefulWidget {
#override
_ParentWidgetState createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
final _childKey = GlobalKey<_ChildWidgetState>();
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _childKey.currentState.updateValue('Goodbye, Thierry!'),
child: ChildWidget(key: _childKey),
);
}
}
class ChildWidget extends StatefulWidget {
const ChildWidget({Key key}) : super(key: key);
#override
_ChildWidgetState createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
String value = 'Hello, Thierry!';
void updateValue(String newValue) {
setState(() => value = newValue);
}
#override
Widget build(BuildContext context) {
return Text(value);
}
}
In your ChildClass, return a GestureDetector. Set the child property to the rest of your widgets, and then set the onTap to call methodA. That should look something like this:
class ChildClass extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GestureDetector {
onTap: methodA,
child: SomeWidget(),
}
}
You are asking how to detect child class onTap and pass it to Parent right?
class YourChild extends StatelessWidget {
final Function parentCallback;
const YourChild({this.parentCallback});
#override
Widget build(BuildContext context) {
return GestureDetector(
// 1st option
onTap: () {
print("do something");
parentCallback();
},
)
}
}
Then for using It.
class YourParent extends StatelessWidget {
#override
Widget build(BuildContext context) {
return YourChild( parentCallback(){
//do your stuff}
)
}
}

How to set data in an inherited widget from a another widget?

So inherited widget is useful for passing data down the tree, but how do I set that data in the first place if inherited widgets are immutable?
I'm trying to set a phone number for OTP auth and then display that number on another screen. Provider is kind of advanced for me at the moment, how do I approach this?
thank you
You have to rebuild somewhere your InheritedWidget.
You can use any stage management for it, for example you can use StatefulWidget:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class MyInheritedWidget extends InheritedWidget {
final int counter;
MyInheritedWidget({Key key, this.counter, Widget child})
: super(key: key, child: child);
#override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return oldWidget.counter != counter;
}
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _counter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: MyInheritedWidget(counter: _counter, child: CounterWidget()),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_counter++;
});
},
),
);
}
}
class CounterWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text("${MyInheritedWidget.of(context).counter}",
style: TextStyle(fontSize: 100));
}
}
Firstly you would use a StreamProvider for your stream of data (The same as you would using a StreamBuilder):
class Widget1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: Wrapper(),
);
}
}
Next widget has no required data
class Widget2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Widget3(),
);
}
}
Access your data via Provider.of
class Widget3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
if (user == null) {
return Login();
} else {
return Dashboard();
}
}
}
With this method, you still need to access the data somewhere down the widget tree. You can't go up, if you want to have the ability to have a widget up the tree listen to something that happens down the tree, you will want to look at ChangeNotifier

MediaQuery.of() called with a context that does not contain a media query. visual studio Code [duplicate]

I have been trying to get the size of the whole context view in Flutter. But every time I try I'm getting the above mentioned error.
Here's my code:
import 'package:flutter/material.dart';
void main => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return new MaterialApp(
home: new Scaffold(),
);
}
}
Note: I also tried with a StatefulWidget.
Please, help me find what I'm doing wrong here.
You need a MaterialApp or a WidgetsApp around your widget. They provide the MediaQuery. When you call .of(context) flutter will always look up the widget tree to find the widget.
You usually have this in your main.dart:
void main() => runApp(App());
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
theme: kThemeData,
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Container(
child: ...,
);
}
}
What works for us is using WidgetsBinding.instance.window instead of MediaQuery - also when setting the theme of the MaterialApp:
_pixelRatio = WidgetsBinding.instance.window.devicePixelRatio;
_screenWidth = WidgetsBinding.instance.window.physicalSize.width;
_screenHeight = WidgetsBinding.instance.window.physicalSize.height;
_statusBarHeight = WidgetsBinding.instance.window.padding.top;
_bottomBarHeight = WidgetsBinding.instance.window.padding.bottom;
_textScaleFactor = WidgetsBinding.instance.window.textScaleFactor;
You can access MediaQuery when you are inside MaterialApp. The place where you are accessing the media query is not correct.
Please refer below code:
import 'package:flutter/material.dart';
class CommonThings {
static Size size;
}
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'MediaQuery Demo',
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
CommonThings.size = MediaQuery.of(context).size;
print('Width of the screen: ${CommonThings.size.width}');
return new Container();
}
}
I've purposely created a class CommonThings which has static Size so that you can use it throughout the app.
I fixed it by using the following method. First I created a new class named MyWidget and returned it in MyApp within a MaterialApp's home:. Refer code below:
import 'package:flutter/material.dart';
void main => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyWidget(),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return new MaterialApp(
home: new Scaffold(),
);
}
}
Also, declaring size as final doesn't matter. Orientation/Rotation is handled.
Solved by re-run the app(click on stop button in android studio then run again)
There is better way. Above solutions would require you to have only one screen widget or inherit all screens from parent class. But there is solution, place the media query initialization into onGenerateRoute callback function
main.dart
import 'package:flutter/material.dart';
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => new MyAppState();
}
class MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Awesome App',
routes: NavigationUtils.routeList(),
onGenerateRoute: (routeSettings) =>
NavigationUtils.onGenerateRoute(routeSettings),
);
}
}
NavigationUtils.dart
import 'package:flutter/material.dart';
class NavigationUtils {
static onGenerateRoute(RouteSettings routeSettings) {
return new MaterialPageRoute(
builder: (context) {
WidgetUtils.me.init(context);
return StorageUtils.me.isLogged() ? HomeScreen() : ForkScreen();
},
settings: routeSettings,
);
}
}
WidgetUtils.dart
import 'package:flutter/material.dart';
class WidgetUtils {
MediaQueryData _mediaQueryData;
double _screenWidth;
double _screenHeight;
double _blockSizeHorizontal;
double _blockSizeVertical;
init(BuildContext context) {
_mediaQueryData = MediaQuery.of(context);
screenWidth = _mediaQueryData.size.width;
screenHeight = _mediaQueryData.size.height;
blockSizeHorizontal = screenWidth / 100;
blockSizeVertical = screenHeight / 100;
}
}
Warning: It is not copy & paste code, there are some singletons etc. but you should get the point ;)
Had the same error in
import 'screens/tasks_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TasksScreen();
}
}
I solved it by:-
import 'package:flutter/material.dart';
import 'screens/tasks_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: TasksScreen(),
);
}
}
Wrap your code in a Material App widget. I also had the same issue as I forgot to use it and directly returned the scaffold.
In other words, your MediaQuery.of(context) should be inside the Material Widget.
Material app -> scaffold -> MediaQuery.of(context)
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyAppOne(),
);
}
}
class MyAppOne extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyAppOne>{
#override
Widget build(BuildContext context){
return Scaffold(
);
}
}
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body:HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size.height;
return Container(
height:size/2,
color:Colors.lightBlueAccent,
);
}
}
YOU SHOULD TRY THIS I HAVE DONE IT.
I was trying to change the package then this error arise,
so make sure you complete each of the following steps
https://stackoverflow.com/a/51550358/4993045
Add MaterialApp ...
void main() {
runApp(MaterialApp(
home: HomePage(),
));
}

Why is my "Data"."data" not updated in ChangeNotifier class using ChangeNotifierProvider?

I am new to flutter.
I want to ask why when my text field's onChange did not trigger: "Provider.ofContext).updateData(newString);".
The value of my Provider.of(context).data is not updated and with the 2 print statements, only 'called1' is always printed out.
Here is the code:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
create: (_) => Data(),
lazy: false,
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text(Provider.of<Data>(context).data),
),
body: Level2(),
),
),
);
}
}
class Level2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
MyTextField(),
],
);
}
}
class MyTextField extends StatelessWidget {
#override
Widget build(BuildContext context) {
return TextField(onChanged: (newString) {
print('called1');
Provider.of<Data>(context).updateData(newString);
print('called2');
});
}
}
class Data extends ChangeNotifier {
String data = '1234567890';
void updateData(newString) {
data = newString;
notifyListeners();
}
}
You are trying to access provider in same widget where you are declaring, which is not right way to do, provider must declare in above widget where you are accessing.
Moreover always use provider data by variable(as used in MyTextField widget) other wise it will not work.
Following code may help you to understand more.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<Data>(
create: (_) => Data(),
child: MaterialApp(home: Level1()),
);
}
}
class Level1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(Provider.of<Data>(context).data),
),
body: Level2(),
);
}
}
class Level2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
MyTextField(),
],
);
}
}
class MyTextField extends StatelessWidget {
var dataprovider;
#override
Widget build(BuildContext context) {
dataprovider = Provider.of<Data>(context);
return TextField(
onChanged: (newString) {
print(dataprovider.data);
dataprovider.updateData(newString);
print('called2');
},
);
}
}
class Data extends ChangeNotifier {
String data = '1234567890';
void updateData(newString) {
print("cds");
data = newString;
notifyListeners();
}
}