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,
)
]),
);
}
}
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?
I would create a custom container and add properties like id to it
I tried doing it like this.
what I would like is to create a container which has a unique id assigned to it.
class Tile extends Container
{
late int id;
late int position;
Tile({Key? key}) : super(key: key);
}
You can create custom class like:
class Tile extends StatelessWidget {
late int id;
late int position;
Tile({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container();
}
}
You can choose one of the following two codes:
class Tile extends Container {
Tile({Key? key, required int id, required int position})
: super(
key: key,
child: ......,
);
}
or
class Tile extends StatelessWidget {
const Tile({Key? key, required this.id, required this.position})
: super(key: key);
final int id;
final int position;
#override
Widget build(BuildContext context) {
return Container(
child: ......,
);
}
}
I try do some like fabric for my default view.
/// Providing create access to create default snapshot state view.
abstract class DefaultSnapshotView extends StatelessWidget {
/// Constructor.
const DefaultSnapshotView({Key? key}) : super(key: key)
/// Default loading view.
const factory DefaultSnapshotView.loading({
Key? key,
}) = _Loading;
// ... other factories like above.
}
class _Loading extends DefaultSnapshotView {
const _Loading({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const CircularProgressIndicator();
}
}
but I have error
what I do wrong? and how I can fix it for const factory ... =
A bit of a late answer:
I think you're only missing a ; after
const DefaultSnapshotView({Key? key}) : super(key: key);
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');
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;
}
}