Total newbie here but I can't get around this.
I want a reusable widget that takes a String title in its constructor and then uses it in the build's widget:
import 'package:flutter/material.dart';
class TemperatureInputDecoration extends StatelessWidget {
const TemperatureInputDecoration({Key? key, required this.title})
: super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return const InputDecorator(
decoration: InputDecoration(
labelText: title,
focusColor: Colors.orangeAccent,
),
);
}
}
I get an error on the line 'labelText: title' saying 'Invalid constant value'. I've tried widget.title, creating a getter for super.widget and using a Stateful widget but no go.
I've seen this page but none of it worked for me. Maybe it has something to do with InputDecoration not being a widget? Any help appreciated.
InputDecoration is not a widget, as defined by the class,
import 'package:flutter/material.dart';
class TemperatureInputDecoration extends StatelessWidget {
const TemperatureInputDecoration({Key? key, required this.title})
: super(key: key);
final String title;
#override
Widget build(BuildContext context) {
return const Text(
title,
style: TextStyle(color: Colors.red)
);
}
}
this will work just fine
Turns out it was simple, just extend InputDecoration rather than StatefulWidget:
import 'package:flutter/material.dart';
class TemperatureInputDecoration extends InputDecoration {
const TemperatureInputDecoration({required this.text, required this.color});
final String text;
final Color color;
#override
String get labelText => text;
#override
Color get focusColor => color;
}
Now I can just instantiate the Decoration where I need it, passing text and color in from above rather than inline.
Try this:
class TemperatureInputDecoration extends StatefulWidget {
TemperatureInputDecoration (this.uid);
final uid;
#override
TemperatureInputDecorationstate createState() => TemperatureInputDecorationstate (this.uid);
}
class TemperatureInputDecorationstate extends State<TemperatureInputDecoration > {
TemperatureInputDecorationstate (this.uid);
var uid;
//you can use uid inside widget.....
}
and to reuse variable:
TemperatureInputDecoration('set here uid value');
Related
I want to bypass an Icon Widget to a custom widget and get the Icons codePoint value make some changes and return the new Icon Widget.
class NewCustomWidget extends StatefulWidget {
const NewCustomWidget({
Key? key,
this.mySize,
this.myIcon,
}) : super(key: key);
final double? mySize;
final Icon? myIcon;
#override
_NewCustomWidgetState createState() => _NewCustomWidgetState();
}
class _NewCustomWidgetState extends State<NewCustomWidget> {
#override
Widget build(BuildContext context) {
return Icon(
???? howto bypass the widget.myIcon's codePoint/IconData to the new Icon ????
color: Colors.black,
size: widget.mySize,
);
}
}
I tried to use the widget.myIcon.toString() but I get only the String "widget"
Icon takes IconData. You can do
return Icon(
widget.myIcon?.icon,
color: Colors.black,
size: widget.mySize,
);
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,
)
]),
);
}
}
I want to change the value of the text field in MyButton, such that, each time the button is clicked, the value is changed. I have set the value as a attribute in MyButton and passed a function from MyButtonRow to MyButton that will be executed everytime it is clicked. In that function, I want to change the attribute "myString" of MyButton, so it will automatically update the text field.
Code:
class MyButtonRow extends StatefulWidget {
const MyButtonRow({Key? key}) : super(key: key);
#override
_MyButtonRowState createState() => _MyButtonRowState();
}
class _MyButtonRowState extends State<MyButtonRow> {
#override
Widget build(BuildContext context) {
return Container(width: MediaQuery.of(context).size.width,
child: Row(children: <Widget>[MyButton(onTap: (){
print("Notify me");
//I want to change the myText attribute of MyButton here
}, myText: "Hello",)],));
}
}
class MyButton extends StatefulWidget {
final Function onTap;
final String myText;
const MyButton({Key? key, required this.onTap, required this.myText}) : super(key: key);
#override
_MyButtonState createState() => _MyButtonState();
}
class _MyButtonState extends State<MyButton> {
var onTap;
var myString;
#override
void initState() {
onTap = widget.onTap;
myString = widget.myText;
super.initState();
}
#override
Widget build(BuildContext context) {
return TextButton(onPressed:onTap,
child: Text(myString));
}
}
**EDIT**
Both the answers, by #Yeasin Sheikh and #Jav T were correct.
But this brought me to another question, "Is there a way i can access that attribute of MyButton in MyButtonRow"
Issue is that you are passing the newValue as a constructor parameter and assigning it to a local variable which is retained in state. Whenever a rebuild is called, the initState function is never called again, just the first time, I would recommend that instead of using:
#override
Widget build(BuildContext context) {
return TextButton(onPressed:onTap,
child: Text(myString));
}
You go ahead and use:
#override
Widget build(BuildContext context) {
return TextButton(onPressed:onTap,
child: Text(widget.myText));
}
In this case, the value will be updated whenever the parent rebuilds your widget. Make sense?
However, you cannot change the attributes of a widget after it is built - How to access/change an attribute of a Widget in Flutter
You can create a method or assign method like inside _MyButtonState's build
onPressed: () {
onTap();
setState(() {
myString = "newValue";
});
},
To use MyButton's myText that is coming though constructor, use widget.myText as #Jav T descried.
It is not necessary to make this StatefulWidget in this case, you can simply use StatelessWidget for MyButton.
class MyButton extends StatelessWidget {
final Function onTap;
final String myText;
const MyButton({
Key? key,
required this.onTap,
required this.myText,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return TextButton(
onPressed: () => onTap(),
child: Text(myText),
);
}
}
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)],
);
}
}
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;
}
}