The method 'selectTime' isn't defined for the class '_createWeckerPage' - flutter

I used a casual showTimePicker in our first dart file (main.dart)
import 'package:flutter/material.dart';
import 'dart:async';
//import 'package:android_alarm_manager/android_alarm_manager.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: CreateWeckerPage('Wecker erstellen'),
);
}
}
class CreateWeckerPage extends StatefulWidget{
CreateWeckerPage(this.name):super();
final String name;
#override
_CreateWeckerPage createState() => _CreateWeckerPage();
}
class _CreateWeckerPage extends State<CreateWeckerPage>{
TimeOfDay _time = new TimeOfDay.now();
//Zeit Picker Funktion
Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: _time,
builder: (BuildContext context, Widget child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
child: child,
);
}
);
if(picked != null && picked != _time){
print('Timeselected: ${_time.toString()}');
setState((){
_time = picked;
});
}
}
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text('${widget.name}')
),
body: Container(
child: Column(
children: <Widget>[
Text('Time Selected: ${_time.toString()}'),
RaisedButton(
onPressed: (){
_selectTime(context);
},
child: Text(
"Zeit eingeben",
),
),
],
),
),
);
}
}
I wanted to refector the code and started to outsource the page in another dart file and the function _selectTime into another dart file for the functions. So i created a file which is called createWeckerPage.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:wecker/Funktions/timePicker.dart';
class CreateWeckerPage extends StatefulWidget{
CreateWeckerPage(this.name):super();
final String name;
#override
_CreateWeckerPage createState() => _CreateWeckerPage();
}
class _CreateWeckerPage extends State<CreateWeckerPage>{
TimeOfDay _time;
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text('${widget.name}')
),
body: Container(
child: Column(
children: <Widget>[
Text('Time Selected: ${_time.toString()}'),
RaisedButton(
onPressed: (){
testClass.testFunktion();
_time = _selectTime(context):
);
},
child: Text(
"Zeit eingeben",
),
),
],
),
),
);
}
}
and a timePicker.dart
import 'package:flutter/material.dart';
import 'dart:async';
Future<Null> _selectTime(BuildContext context) async {
TimeOfDay _time = TimeOfDay.now();
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: _time,
builder: (BuildContext context, Widget child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
child: child,
);
}
);
if(picked != null && picked != _time){
print('Timeselected: ${_time.toString()}');
return picked;
}
return _time;
}
The problem is, as written in the title that the method _selectTime is not defined in the createWeckerPage Class. How can I implement my Future _selectTime function to work inside my createWeckerPage.dart to display in the app?
Thank you in advance.

underline means private, you can remove _ underline
please change from
_selectTime(BuildContext context)
to
selectTime(BuildContext context)

Related

Flutter build not behaving as expected

I'm trying to make a note app but there is a yellow square showing on the screen.
I've included the main.dart code and also allnotesscreens.dart. I think there is something wrong with allnotesscreens code, but I don't know what.
Maybe _loadViewMode() part.
Why this problem is happening?!!!
Main.dart:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'providers/label_provider.dart';
import 'providers/note_provider.dart';
import 'package:provider/provider.dart';
import 'constants/app_constants.dart';
import 'screens/all_labels_screen.dart';
import 'screens/all_notes_screen.dart';
import 'screens/drawer_screen.dart';
main() {
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarColor: ColorsConstant.grayColor,
),
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => NoteProvider()),
ChangeNotifierProvider(create: (_) => LabelProvider()),
],
builder: (context, child) => MaterialApp(
title: 'Note-App',
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.dark,
theme: customThemeData(context),
initialRoute: '/',
routes: {
'/': (context) => const AllNotesScreen(),
DrawerScreen.routeName: (context) => const DrawerScreen(),
AllLabelsScreen.routeName: (context) => const AllLabelsScreen(),
},
),
);
}
}
allnotesscreens.dart:
class AllNotesScreen extends StatefulWidget {
const AllNotesScreen({Key? key}) : super(key: key);
#override
State<AllNotesScreen> createState() => _AllNotesScreenState();
}
class _AllNotesScreenState extends State<AllNotesScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Container(
height: 200,
width: 100,
color: Colors.yellow,
),
),
);
}
String _viewMode = ViewMode.staggeredGrid.name;
bool _isLoading = false;
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
setState(() {
_isLoading = true;
});
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
Future _loadViewMode() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('view-mode')) return;
setState(() {
_viewMode = prefs.getString('view-mode') ?? ViewMode.staggeredGrid.name;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: const Text(
"all notes",
style: TextStyleConstants.titleAppBarStyle,
),
actions: [
if (context
.watch<NoteProvider>()
.items
.isNotEmpty)
IconButton(
onPressed: () {
showSearch(
context: context,
delegate: NoteSearch(isNoteByLabel: false),
);
},
icon: const Icon(Icons.search),
),
IconButton(
onPressed: () async {
final result = await changeViewMode(_viewMode);
setState(() {
_viewMode = result;
});
},
icon: _viewMode == ViewMode.staggeredGrid.name
? const Icon(Icons.view_stream)
: const Icon(Icons.grid_view),
),
const SizedBox(
width: 6,
)
],
),
drawer: const DrawerScreen(),
body: _isLoading
? const Center(
child: CircularProgressIndicator(),
)
: RefreshIndicator(
onRefresh: () => refreshOrGetData(context),
child: Consumer<NoteProvider>(
builder: (context, noteProvider, child) =>
noteProvider.items.isNotEmpty
? NoteListViewWidget(
notes: noteProvider.items,
viewMode: _viewMode,
scaffoldContext: _scaffoldKey.currentContext!,
)
: child!,
child: const NoNoteUIWidget(
title: "your notes after adding will appear here",
),
),
),
floatingActionButton: FloatingActionButton(
child: linearGradientIconAdd,
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const EditNoteScreen(),
));
},
),
);
}
}
}
The first few lines of your _AllNotesScreenState class are why there's a yellow square; that's what you're telling it to build.
class _AllNotesScreenState extends State<AllNotesScreen> {
// this build function here is what is drawing to the screen
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child:
Container(
height: 200,
width: 100,
color: Colors.yellow,
),
),
);
}
Maybe it's just how you've pasted it in, but it appears as though you have a build function defined within the didChangeDependencies function. If you took it out of there, it would then make it apparent that you have two build functions defined for the class.
I'm assuming it's the second one that you actually want building.
#override
void didChangeDependencies() {
super.didChangeDependencies();
Future _loadViewMode() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('view-mode')) return;
setState(() {
_viewMode = prefs.getString('view-mode') ?? ViewMode.staggeredGrid.name;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
...

How to Passing Data from Navigator Pop to Previous Page Where The Data is Used in The Widget Inside the ListView.builder

As stated in the title. How to return data to the previous page where the data is used to list widgets.
I have read this article Flutter Back button with return data or other similar articles. The code works perfectly. But there is a problem if I want to use the data returned to the widget that is in the list.\
Note that I only want to update one ListWidget, I don't want to refresh the state of the entire HomePage like the solution in this article Flutter: Refresh on Navigator pop or go back.
Here is a simple code sample to represent the problem I'm facing.
(check on ListWidget Class and SecondPage Class below)
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: HomePage(),
);
}
}
HomePage class
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: ListView.builder(
itemCount: 4,
itemBuilder: (_, index){
return ListWidget(number: index+1);
},
)
),
);
}
}
ListWidget Class
class ListWidget extends StatelessWidget{
ListWidget({#required this.number});
final int? number;
String? statusOpen;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () async {
statusOpen = await Navigator.of(context, rootNavigator: true)
.push(
MaterialPageRoute(
builder: (BuildContext context) => SecondPage(),
),
);
},
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(20),
color: Colors.amber,
child: Text(statusOpen != null ? '$number $statusOpen' : '$number Unopened'),
//
// I want to change the text here to 'has Opened' when the user returns from SecondPage
//
),
);
}
}
SecondPage Class
class SecondPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Page'),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context, 'has Opened');
// return 'has Opened' to await statusOpen variable
},
child: Text('Go Back'),
),
),
);
}
}
is there any solution to handle this?
If you make your listWidget a stateful widget, then you can get the solution where you just need to call setState when you return to your previous screen. And in this way you will be only changing your single list element and not the full screen.
sample code:
changing this line- class ListWidget extends StatefulWidget
and adding these lines -
onTap: () async {
statusOpen = await Navigator.of(context, rootNavigator: true)
.push(
MaterialPageRoute(
builder: (BuildContext context) => SecondPage(),
),
);
setState(() {
});
},
If you used the data in your listview just call setstate after Navigator.pop like below code
onTap: () async {
statusOpen = await Navigator.of(context, rootNavigator: true)
.push(
MaterialPageRoute(
builder: (BuildContext context) => SecondPage(),
),
).then((value) async {
setState(() {});
});
},

Problem with Datepicker, it disappears if you try to change month or year

When I try to change year or month in date picker modal it disappears. as you can see below:
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.value(
value: Register(),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('some title'),
),
body: Consumer<Register>(
builder: (context, register, child) {
return InkWell(
onTap: () {
_selectDate(context, register);
},
child: Container(
child: Text('Click me'),
),
);
},
),
);
}
Future<void> _selectDate(BuildContext context, Register register) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: register.birthdate,
firstDate: DateTime(1920),
lastDate: DateTime.now(),
);
print(picked);
if (picked != null && picked != register.birthdate) {
register.birthdate = picked;
}
}
}
class Register extends ChangeNotifier {
DateTime birthdate = DateTime.now();
String get birthDateDate {
return birthdate.toLocal().toIso8601String();
}
}
I've rechecked in android emulator and it worked, after I restarted iOS emulator and worked like a charm.

Flutter: Shared Preferences, Change Notifier

This is the code of the count up app with change notifier and shared preferences.
I want it to save the counter in the model and show the last counter when it is opened, but it does not work.
When it is opened, it shows 0. Once I tap the add button, it shows the last counter plus 1.
Please tell me why it does not work and how can I fix it.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(
ChangeNotifierProvider<MyHomePageModel>(
create: (_) => MyHomePageModel(),
child: 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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<MyHomePageModel>(builder: (context, model, child) {
int _counter = model.getCounter();
return Scaffold(
appBar: AppBar(
title: Text('FlutteR Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: Button());
});
}
}
class Button extends StatelessWidget {
#override
Widget build(BuildContext context) {
final model = Provider.of<MyHomePageModel>(context, listen: false);
return FloatingActionButton(
onPressed: () => model.addCounter(),
tooltip: 'Increment',
child: Icon(Icons.add),
);
}
}
class MyHomePageModel extends ChangeNotifier {
int _counter = 0;
void _setPrefItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('counter', _counter);
}
void _getPrefItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_counter = prefs.getInt('counter') ?? 0;
}
void addCounter() {
_counter++;
_setPrefItems();
notifyListeners();
}
int getCounter() {
_getPrefItems();
return _counter;
}
}
2 things I see missing here.
There is no getter for your counter in your HomePageModel. You're calling the getCounter() method in your widget, but the method returns void and not the counter value.
You have a ChangeNotifier, but notifyListeners is never called.
I would recommend setting a getter for your counter and calling notifyListeners in your method.
void _getPrefItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_counter = prefs.getInt('counter') ?? 0;
notifyListeners();
}
int get counter => _counter
void _getPrefItems() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
_counter = prefs.getInt('counter') ?? 0;
}
int getCounter() {
_getPrefItems();
return _counter;
}
_getPrefItems is async function, and when you call getCounter the _counter hasn't been reassigned yet, so it return the default value of _counter which is 0.
So all you have to do is change the getCounter function to async function
Future<int> getCounter() async {
await _getPrefItems();
return _counter;
}
I recommend you to put SharePreferences out of your model, then using FutureProvider, look at the full code, I didn't test it, but you get the idea.
import 'package:animations/animations.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return FutureProvider(
create: (_) => SharedPreferences.getInstance(),
lazy: false,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Provider(
create: (_) => MyHomePageModel(prefs: Provider.of(context)),
child: Scaffold(
appBar: AppBar(
title: Text('FlutteR Demo Home Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Consumer<MyHomePageModel>(
builder: (context, model, child) => Text(
'${model.getCounter()}',
style: Theme.of(context).textTheme.headline4,
),
),
],
),
),
floatingActionButton: Button(),
),
);
}
}
class Button extends StatelessWidget {
#override
Widget build(BuildContext context) {
final model = Provider.of<MyHomePageModel>(context, listen: false);
return FloatingActionButton(
onPressed: () => model.addCounter(),
tooltip: 'Increment',
child: Icon(Icons.add),
);
}
}
class MyHomePageModel extends ChangeNotifier {
final SharedPreferences prefs;
int _counter = 0;
MyHomePageModel({#required this.prefs});
void _setPrefItems() {
prefs.setInt('counter', _counter);
}
void _getPrefItems() {
_counter = prefs.getInt('counter') ?? 0;
}
void addCounter() {
_counter++;
_setPrefItems();
notifyListeners();
}
int getCounter() {
_getPrefItems();
return _counter;
}
}

Switch toggle between time format (am/pm and 24H) from settings page

i want to have switch widget in settings page. i can figured switching theme using switch widget, but this is too complicated
my main_page:
import 'package:intl/intl.dart';
Column(
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Text("Summary"),
),
SizedBox(height: 45),
_time24(snapshot), //show this if switch is off
_time12(snapshot), //show this if switch is on
],
)
Widget _time12(AsyncSnapshot snapshot){
return Column(
children: <Widget>[
_time(Icons.home, Text(DateFormat("hh:mma").format(DateFormat("HH:mm").parse(snapshot.data.home)))),
_time(Icons.work, Text(DateFormat("hh:mma").format(DateFormat("HH:mm").parse(snapshot.data.work)))),
_time(Icons.restaurant, Text(DateFormat("hh:mma").format(DateFormat("HH:mm").parse(snapshot.data.restaurant)))),
]);
}
Widget _time24(AsyncSnapshot snapshot){
return Column(
children: <Widget>[
_time(Icons.home, Text(snapshot.data.home)),
_time(Icons.work, Text(snapshot.data.work)),
_time(Icons.restaurant, Text(snapshot.data.restaurant)),
]);
}
Thank you for your time :)
You can copy paste run full code below
You can await Navigator.push then call setState()
code snippet
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => Setting()),
);
setState(() {});
}
...
else if (snapshot.hasData) {
if (is24) {
return _time24(snapshot);
} else {
return _time12(snapshot);
}
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:intl/intl.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 Payload {
String home;
String work;
String restaurant;
Payload({this.home, this.work, this.restaurant});
}
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;
Future _future;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget _time12(AsyncSnapshot snapshot) {
var a = DateFormat("HH:mm").parse(snapshot.data.home);
print("a ${a}");
return Column(children: <Widget>[
_time(
Icons.home,
Text(DateFormat("hh:mma")
.format(DateFormat("HH:mm").parse(snapshot.data.home)))),
_time(
Icons.work,
Text(DateFormat("hh:mma")
.format(DateFormat("HH:mm").parse(snapshot.data.work)))),
_time(
Icons.restaurant,
Text(DateFormat("hh:mma")
.format(DateFormat("HH:mm").parse(snapshot.data.restaurant)))),
]);
}
Widget _time24(AsyncSnapshot snapshot) {
return Column(children: <Widget>[
_time(Icons.home, Text(snapshot.data.home)),
_time(Icons.work, Text(snapshot.data.work)),
_time(Icons.restaurant, Text(snapshot.data.restaurant)),
]);
}
Widget _time(IconData iconData, Text _text) {
return ListTile(
leading: Icon(iconData),
title: _text,
);
}
Future<Payload> getData() {
print("getData");
return Future.value(
Payload(home: "18:00", restaurant: "13:00", work: "08:00"));
}
#override
void initState() {
// TODO: implement initState
_future = getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FutureBuilder<Payload>(
future: _future,
builder: (BuildContext context, AsyncSnapshot<Payload> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return Text('Awaiting result...');
case ConnectionState.done:
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
else if (snapshot.hasData) {
if (is24) {
return _time24(snapshot);
} else {
return _time12(snapshot);
}
}
}
return null; // unreachable
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context) => Setting()),
);
setState(() {});
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
bool is24 = true;
class Setting extends StatefulWidget {
#override
_SettingState createState() => _SettingState();
}
class _SettingState extends State<Setting> {
void _changed(value) {
setState(() {
is24 = value;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Container(
child: Switch(
value: is24,
onChanged: _changed,
)));
}
}