I want to make Page Widget with string "mytitle","Anime"
It might be too simple question but it is very confusing for me the relationship of StatefulWidget and State
return Navigator.pushReplacement(context,
NoAnimationMaterialPageRoute(
builder: (context,"mytitle","Anime") => AnimePage()));
class AnimePage extends StatefulWidget {
AnimePage({Key key, this.title, this.video}) : super(key: key);
final String title;
final String video;
#override
_AnimePageState createState() => _AnimePageState();
}
class _AnimePageState extends State<AnimePage> {
#override
void initState() {
super.initState();
print(widget.video) //want to show `Anime` here
};
This works:
return Navigator.pushReplacement(
context,
NoAnimationMaterialPageRoute(
builder: (context) => AnimePage(
// pass your parameter values
title: 'My Anime',
video: YOUR_VIDEO_PARAM,
),
),
);
You also have to add the constructor on the State, like this...
class AnimePage extends StatefulWidget {
AnimePage({Key key, this.title, this.video}) : super(key: key);
final String title;
final String video;
#override
_AnimePageState createState() => _AnimePageState(title,video);
}
class _AnimePageState extends State<AnimePage> {
final String title;
final String video;
_AnimePageState(this.title,this.video);
#override
void initState() {
super.initState();
print(widget.video) //want to show `Anime` here
};
I hope that was what you're looking for
Related
I'm a beginner and I cannot understand one thing. So, I have these classes:
class Book {
int? id;
Author author = Author();
}
class Author {
String? firstName;
String? lastName;
}
Creating the book object in the widget
class MainWidget extends StatefulWidget {
const MainWidget({Key? key}) : super(key: key);
#override
State<MainWidget> createState() => _MainWidgetState();
}
class _MainWidgetState extends State<MainWidget> {
final Book myBook = Book();
#override
Widget build(BuildContext context) {
return ChangeBookAuthor(bookAuthor: myBook.author);
}
}
And changing the value of the author
First example
class ChangeBookAuthor extends StatefulWidget {
final Author bookAuthor;
const ChangeBookAuthor({Key? key, required this.bookAuthor})
: super(key: key);
#override
State<ChangeBookAuthor> createState() => _ChangeBookAuthorState();
}
class _ChangeBookAuthorState extends State<ChangeBookAuthor> {
late Author _bookAuthor;
#override
void initState() {
_bookAuthor = widget.bookAuthor;
super.initState();
}
#override
Widget build(BuildContext context) {
return TextFormField(
onChanged: (value) => _bookAuthor.firstName = value,
);
}
}
Second example
class ChangeBookAuthor extends StatefulWidget {
final Book book;
const ChangeBookAuthor({Key? key, required this.book})
: super(key: key);
#override
State<ChangeBookAuthor> createState() => _ChangeBookAuthorState();
}
class _ChangeBookAuthorState extends State<ChangeBookAuthor> {
late Book _book;
#override
void initState() {
_book = widget.book;
super.initState();
}
#override
Widget build(BuildContext context) {
return TextFormField(
onChanged: (value) => _book.author.firstName = value,
);
}
}
In my application, I would like to have a ChangeBookAuthor widget that only gets the Author object and changes its value in the Book object in MainWidget. How can this be achieved? Why does the first example work and the second doesn't?
home.dart
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late Directory? appDir;
late List<String>? records;
record.dart
class Records extends StatefulWidget {
final List<String> records;
const Records({
Key? key,
required this.records,
}) : super(key: key);
#override
_RecordsState createState() => _RecordsState();
}
app.dart
class App extends GetView<AppController>{
const App({Key? key}) : super(key: key);
static const PrimaryColor1 = const Color(0xFF708FF8);
#override
Widget build(BuildContext context){
return Scaffold(
body: Obx(() {
switch(RouteName.values[controller.currentIndex.value]) {
case RouteName.Home:
return Home();
break;
case RouteName.Record:
return Record(records: records);
I need to return Record(records: records) in app.dart. The variable records is in home.dart. Is there a way to use the variable records in app.dart?
+) I tried changing it as follows, but 'recordnull' was printed.
home.dart
class video_Body extends StatefulWidget {
video_Body({Key? key, required this.index}) : super(key: key);
#override
_video_Body createState() => _video_Body();
int index;
static List<String>? records;
}
class _video_Body extends State<video_Body> {
List<String>? get record => video_Body.records;
app.dart
if(video_Body.records == null) print('recordnull');
return Record(records: video_Body.records);
There are several ways to do what you want to do, here are the two simplest ones I could think of:
1. Store the variable somewhere else.
It is hard to explain how to do this because I have very little information about what the home page is doing to the list of records, but the general idea is declare the list of records on the app.dart file and pass the value of the list into the Home class.
To do this, you will probably have to declare some sort of callback for when the Home class wants to edit the list, I will give you an example:
In this example, we have a button widget that displays a number, and when you press the button it increases the value of the number, and we want to access the current value of the number.
First I will show you the equivalent of your problem:
Button:
class MyButton extends StatefulWidget {
...
}
class _MyButtonState extends State<MyButton> {
int value = 0;
#override
Widget build(BuildContext) {
return ElevatedButton(
child: Text(value.toString()),
onPressed: () => setState(() => value++),
);
}
}
Home:
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: [
MyButton(),
Text(buttonText), // how do we access the button text?????
]
);
}
}
And now, with the solution:
Button:
class MyButton extends StatelessWidget {
MyButton({required this.value, required this.onChange});
final void Function(int) onChange;
final int value;
#override
Widget build(BuildContext) {
return ElevatedButton(
child: Text(value.toString()),
onPressed: () => onChange(value +1),
);
}
}
Home:
class Home extends StatefulWidget {
...
}
class _HomeState extends State<Home> {
int value = 0;
#override
Widget build(BuildContext context) {
return Column(
children: [
MyButton(onChange: (v) => setState(() => value=v), value: value),
Text(value.toString()),
]
);
}
}
Of course, this solution may not work for you depending on the situation.
2. Use a static class
The idea here is to move the variable you want to access into a static class, first you need to make a class with a static variable you want to access:
class RecordsService {
static List<String>? records;
}
Because it is static, you can access it from anywhere, so on home, make the following changes:
Before:
late List<String>? records;
After:
List<String>? get records => RecordService.records;
and to access the value on app:
return Record(records: RecordService.records);
Hopefully one of these solutions solves your use case.
I'd like to show change of wordCount in homeWidget
return Scaffold(
body: Column(
children: [
...
Expanded(
flex: 1,
child: RecorderView(
onSaved: _onRecordComplete,
wordCount:wordCount,
),
),
],
),
);
the variablewordCount relies on RecordView method:
I write this to get state variable here
class RecorderView extends StatefulWidget {
final Function onSaved;
final int wordCount;
const RecorderView({Key key, #required this.onSaved,#required this.wordCount}) : super(key: key);
#override
_RecorderViewState createState() => _RecorderViewState();
}
class _RecorderViewState extends State<RecorderView> {
//in one method
widget.wordCount++;
}
I want to add wordCount here,but it says it's a final one.How could I inherit wordCount from homeWidget without final? I just want to change the word show in wordCount automatically,thanks!!
You cant inherit the variable, you can however initialize it to a value from the widget.
class RecorderView extends StatefulWidget {
final Function onSaved;
final int wordCount;
const RecorderView({Key key, #required this.onSaved,#required this.wordCount}) : super(key: key);
#override
_RecorderViewState createState() => _RecorderViewState();
}
class _RecorderViewState extends State<RecorderView> {
int _wordCount;
#override
void initState() {
super.initState();
_wordCount = widget.wordCount;
}
}
I want to push param value(index and user_name) from User_Management_Page to User_Detail_page via Navigator.pushNamed. But I can't know a way to do this.
In User_Management_Page:
Navigator.pushNamed(context,'/user-management/detail',
arguments: {index, user.name},
);
Set up RouterModule:
#override
// TODO: implement routers
List<Router> get routers => [
Router("/usermagement", child: (_, args) => UsersPage()),
Router("/detail", child: (_, args) => UserDetailPage()),
];
And the contractor class User_detail:
class UserDetailPage extends StatelessWidget {
final int index;
final String name;
UserDetailPage({Key key, this.index, this.name}) : super(key: key);
}
This solution is very easy by passing variables in constructor:
first page:
Navigator.of(context).push(MaterialPageRoute(builder:(context)=>SecondPage('something')));
second page:
class SecondPage extends StatefulWidget {
String something;
SecondPage(this.something);
#override
State<StatefulWidget> createState() {
return SecondPageState(this.something);
}
}
class SecondPageState extends State<SecondPage> {
String something;
SecondPageState(this.something);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
//now you have passing variable
title: Text(something),
),
...
}
After Flutter version 1.12.1 ancestorInheritedElementForWidgetOfExactType is deprecated.
We should use getElementForInheritedWidgetOfExactType now.
How do I edit this BlocProvider to work with this new method?
import 'package:flutter/material.dart';
Type _typeOf<T>() => T;
abstract class BlocBase {
void dispose();
}
class BlocProvider<T extends BlocBase> extends StatefulWidget {
BlocProvider({
Key key,
#required this.child,
#required this.bloc,
}) : super(key: key);
final Widget child;
final T bloc;
#override
_BlocProviderState<T> createState() => _BlocProviderState<T>();
static T of<T extends BlocBase>(BuildContext context) {
final type = _typeOf<_BlocProviderInherited<T>>();
_BlocProviderInherited<T> provider =
context.ancestorInheritedElementForWidgetOfExactType(type)?.widget; //deprecated
return provider?.bloc;
}
}
class _BlocProviderState<T extends BlocBase> extends State<BlocProvider<T>> {
#override
void dispose() {
widget.bloc?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new _BlocProviderInherited<T>(
bloc: widget.bloc,
child: widget.child,
);
}
}
class _BlocProviderInherited<T> extends InheritedWidget {
_BlocProviderInherited({
Key key,
#required Widget child,
#required this.bloc,
}) : super(key: key, child: child);
final T bloc;
#override
bool updateShouldNotify(_BlocProviderInherited oldWidget) => false;
}
Do I get rid of the _typeOf variable now?
What are the benefits of this change?
Use context.getElementForInheritedWidgetOfExactType<_BlocProviderInherited<T>>().widget and it should work.
As far as benefits go, the documentation basically states the same though someone can correct me but I don't see any difference. You should be able to get rid of the _typeOf variable.