How to do operations on state constructor variables in Flutter? - flutter

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;
}
}

Related

Flutter: Superclass variable to upper case without touching subclass

Here i have some pseudo code with this scenario.
The UpperCaseElement superclass has the text variable. If upperCase is true, the text variable should be turned into upperCase.
I have tried setting it in the constructor, but it is only the default value if it isn't defined.
import "package:flutter/material.dart";
abstract class UpperCaseElement extends StatelessWidget {
// Should be uppercase if upperCase = true
final String text;
final bool upperCase;
// My attempt to set this.text to upperCase, but it doesn't work.
const UpperCaseElement({Key? key, this.text = text.toUpperCase(), this.upperCase = false})
: super(key: key);
}
class TestWidget extends UpperCaseElement {
const TestWidget({
Key? key,
super.text,
super.upperCase,
}) : super(key: key);
#override
Widget build(context) {
// Yes, the checking and converting to upper case can be done here. But doing that on all subclasses would be a pain. That's why I want to do it on the superclass.
return Text(text);
}
}
class TestPage extends StatelessWidget {
const TestPage({
Key? key,
}) : super(key: key);
#override
Widget build(context) {
return Scaffold(
body: Column(children: const [
// Should be TEST
TestWidget(
text: "test",
upperCase: true,
)
]),
);
}
}
Update: force on abstract class, you can't use const constructor.
#immutable
abstract class UpperCaseElement extends StatelessWidget {
String text;
final bool upperCase;
UpperCaseElement({Key? key, required this.text, this.upperCase = false})
: super(key: key) {
text = upperCase ? text.toUpperCase() : text;
}
}
For the UpperCaseElement is an abstract class, we can handle conditional inside TestWidget.
class TestWidget extends UpperCaseElement {
const TestWidget({
Key? key,
required super.text,
super.upperCase,
}) : super(key: key);
#override
Widget build(context) {
return Text(upperCase ? text.toUpperCase() : text);
}
}
abstract class UpperCaseElement extends StatelessWidget {
final String text;
final bool upperCase;
const UpperCaseElement({
Key? key,
required this.text,
this.upperCase = false,
}) : super(key: key);
}
My solution will be defining a getter function which will return text base on bool value
abstract class UpperCaseElement extends StatelessWidget {
// Should be uppercase if upperCase = true
final String text;
final bool upperCase;
get getText => upperCase ? text.toUpperCase() : text;
// My attempt to set this.text to upperCase, but it doesn't work.
const UpperCaseElement({Key? key, required this.text, this.upperCase = false})
: super(key: key);
}
class TestWidget extends UpperCaseElement {
const TestWidget({
Key? key,
required String text,
required bool upperCase,
}) : super(key: key, text: text, upperCase: upperCase);
#override
Widget build(context) {
// calling getText function from superClass.
return Text(getText);
}
}
class TestPage extends StatelessWidget {
const TestPage({
Key? key,
}) : super(key: key);
#override
Widget build(context) {
return Scaffold(
body: Column(children: const [
// Should be TEST
TestWidget(
text: "test",
upperCase: true,
)
]),
);
}
}

flutter:: Can a variable be used in another file?

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.

Flutter: Random a list of colors

My goal is to generate multiple Stickynote with different color,
I already build a list of six different colors.
I want to put them shuffle on the card.
ERROR
"message": "The instance member 'color' can't be accessed in an initializer.\nTry replacing the reference to the instance member with a different expression",
Here is the code:
import 'dart:math';
import 'package:flutter/cupertino.dart';
class Sticky {
final String note;
List color = [
const Color(0xffB85252),
const Color(0xffB4C6A6),
const Color(0xffF4ABC4),
const Color(0xff346751),
const Color(0xffFFC947),
const Color(0xff3282B8),
];
var colorItem = (color.toList()..shuffle()).first;
Sticky({required this.note, required this.color});
}
class StickyNote extends StatefulWidget {
final color;
final String note;
const StickyNote({Key? key, this.color, required this.note})
: super(key: key);
#override
_StickyNoteState createState() => _StickyNoteState();
}
class _StickyNoteState extends State<StickyNote> {
#override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: Sticky.colorItem,
);
}
}
This looks like a very bad dart code, without any sense to me but I think it is only part of your code.
There is a couple of errors here, that I will summarize below, and also I'm assuming that this code is partial and there is no sense in the usage that you are doing in your example:
final color is not null, and it required
class StickyNote extends StatefulWidget {
final Color color;
final String note;
const StickyNote({Key? key, required this.color, required this.note})
: super(key: key);
You are using the class Sticky as a static class, but any of the propriety is static.
A workable solution is the following one
import 'dart:math';
import 'package:flutter/cupertino.dart';
class Sticky {
final String note;
static List color = [
const Color(0xffB85252),
const Color(0xffB4C6A6),
const Color(0xffF4ABC4),
const Color(0xff346751),
const Color(0xffFFC947),
const Color(0xff3282B8),
];
Sticky({required this.note});
static Color getColorItem() => (color.toList()..shuffle()).first;
}
class StickyNote extends StatefulWidget {
final Color color;
final String note;
const StickyNote({Key? key, required this.color, required this.note})
: super(key: key);
#override
_StickyNoteState createState() => _StickyNoteState();
}
class _StickyNoteState extends State<StickyNote> {
#override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: Sticky.colorItem(),
);
}
}
In addition, with this code there is a little bit more sense if your colors didn't change, otherwise, you need to use the object and not the class
You might want to try this:
import 'dart:math';
import 'package:flutter/cupertino.dart';
class StickyColors {
static final List colors = [
const Color(0xffB85252),
const Color(0xffB4C6A6),
const Color(0xffF4ABC4),
const Color(0xff346751),
const Color(0xffFFC947),
const Color(0xff3282B8),
];
}
class StickyNote extends StatefulWidget {
final String note;
const StickyNote({Key? key, required this.note})
: super(key: key);
#override
_StickyNoteState createState() => _StickyNoteState();
}
class _StickyNoteState extends State<StickyNote> {
final _random = Random();
#override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: StickyColors.colors[_random.nextInt(6)],
);
}
}
I did not actually test it, but I have something similar in my app.
If you just want a random sticky note color without any state logic. You can also convert it to one statelesswidget which can be reused easily:
class StickNote extends StatelessWidget {
final List colors = [
const Color(0xffB85252),
const Color(0xffB4C6A6),
const Color(0xffF4ABC4),
const Color(0xff346751),
const Color(0xffFFC947),
const Color(0xff3282B8),
];
final _random = Random();
#override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: colors[_random.nextInt(6)],
);
}
}

How to pass a value parameter in ChildModule of Flutter?

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),
),
...
}

Passing data from one widget to another

I have a list of choice widget and want to pass the selected choice to another widget.
Here is the list of choice widget
class ChoiceChipWidget extends StatefulWidget {
final List<String> reportList;
final Function(String item) onChoiceSelected;
ChoiceChipWidget(this.reportList, this.onChoiceSelected);
#override
_ChoiceChipWidgetState createState() => new _ChoiceChipWidgetState();
}
class _ChoiceChipWidgetState extends State<ChoiceChipWidget> {
String selectedChoice = "";
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
child: ChoiceChip(
label: Text(item),
selected: selectedChoice == item,
onSelected: (selected) {
setState(() {
selectedChoice = item;
widget.onChoiceSelected(item);
print(selectedChoice); //DATA THAT NEEDS TO BE PASSED
});
},
),
));
});
return choices;
}
#override
Widget build(BuildContext context) {
return Wrap(
children: _buildChoiceList(),
);
}
}
I need to pass it to this widget
class AddCashPage extends StatefulWidget {
#override
_AddCashPageState createState() => _AddCashPageState();
}
class _AddCashPageState extends State<AddCashPage> {
void createTodo() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
String repetition = //DATA NEEDS TO GO HERE;
final addCash = AddCash(repetition);
setState(() {
id = addCash.id;
});
}
}
#override
Widget build(BuildContext context) {
return Container(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
ChoiceChipWidget(chipList, (item) {
selectedItem = item;
}),
],
),
RaisedButton(
child: Text("Update Cash Flow"),
onPressed: createTodo,
),
],
),
),
);
}
}
I tried making a constructor inside AddCashPage
like this
class AddCashPage extends StatefulWidget {
final ChoiceChipWidget choiceChipWidget;
AddCashPage({Key key, #required this.choiceChipWidget}) : super(key: key);
#override
_AddCashPageState createState() => _AddCashPageState();
}
I think you just missed to call setState() in here:
ChoiceChipWidget(chipList, (item) {
selectedItem = item;
}),
Like this:
ChoiceChipWidget(chipList, (item) {
setState(() => selectedItem = item);
}),
Then you could do this:
AddCash(selectedItem)
Make sure to declare the selectedItem variable inside _AddCashPageState, I don't see it on your code.
Your choice widget passes the data to the AddCashPage via the constructor you created, but you're missing something. You need to pass the data that AddCashPage has to its state (_AddCashState) so that you can use it there. Basically, you need to create one more constructor.
class AddCashPage extends StatefulWidget {
final ChoiceChipWidget choiceChipWidget;
AddCashPage({Key key, #required this.choiceChipWidget}) : super(key: key);
#override
_AddCashPageState createState() => _AddCashPageState(choiceChipWidget: choiceChipWidget);
}
And in _AddCashPageState:
class _AddCashPageState extends State<AddCashPage> {
final choiceChipWidget;
_AddCashPageState({Key key, #required this.choiceChipWidget});
}
To use your passed data inside _AddCashPageState class you can use widget property of the corresponding state of the related Stateful class.
For Ex : To use choice chip widget in your class you can use it like widget.ChoiceChipWidget
Any properties/methods provided in AddCashPage class can be accessed in its State class _AddCashPageState() using widget.ChoiceChipWidget property;
You can use this widget property inside methods only like, initState(), build(), dispose() etc.