Let say I want a container with this style -> rounded shape and with border.
Should I create a theme for Container?
Or should I create my custom widget/component?
My main concern here is not to repeat everything so I'm thinking about this 2 possibilities.
Which one more recommended?
Kind Regards
And why people down voted my question. I really don't know :(
You have to create your widget, which extend Widget
It can be StatelessWidget
class MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
//... return your container here
}
or StatefulWidget
class MyWidget extends StatefulWidget {
MyWidget(this.child);
final Widget child;
#override
State<StatefulWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
#override
Widget build(BuildContext context) {
return Container(child: widget.child, ...)
//... return your container here
}
Related
Here is property as a part of the StatefulWidget class
class MyWidget extends StatefulWidget {
String property = "";
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
#override
Widget build(BuildContext context) {
return Container();
}
}
Here is how I would accessproperty from the State's build method:
widget.property
Here is property as a part of the StatefulWidget's State class
class MyWidget extends StatefulWidget {
#override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String property = "";
#override
Widget build(BuildContext context) {
return Container();
}
}
Here is how I would access it from the State's build method:
property
Looks to me like I can achieve the exact same things regardless of whether property is part of the StatefulWidget class or part of the State class.
Am I right or wrong, and if I am wrong, why?
I have created a custom StatefulWidget that takes a Widget as an argument.
import 'package:flutter/material.dart';
class CustomWidget extends StatefulWidget {
final Widget myWidget;
CustomWidget({this.myWidget});
#override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: widget.myWidget(name: 'ASAD'), //I want to achieve this
);
}
}
I'm passing another StatefulWidget named Profile as that argument widget. Now I want to access that passed widget's constructor.
import 'package:flutter/material.dart';
class Profile extends StatefulWidget {
final String name;
Profile({this.name});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
#override
Widget build(BuildContext context) {
return Center(child: Text('${widget.name}'),);
}
}
I'm using the CustomWidget which takes a widget as argument here
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomWidget(myWidget: Profile(),) //I don't want to pass the argument here
);
}
}
I was able to accomplish something like this using typedef but it started throwing an error.
typedef CustomCallBack = Widget Function({String name});
class CustomWidget extends StatefulWidget {
final CustomCallBack myWidget;
CustomWidget({this.myWidget});
#override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: widget.widget(name: 'ASAD'), //I'm able to access the constructor here but now I get an error.
);
}
}
Error
error: The argument type 'Profile' can't be assigned to the parameter type 'Widget Function({String name})'. (argument_type_not_assignable
Note: Based on the app that I'm working on but cannot share code, I have recreated this scenario and is same as far as the issue is concerned.
Try the change this line in the CustomWidget widget,child: widget.widget(name: 'ASAD'), for the widget that you are passing only, without putting the (name: 'ASAD').
So when you pass the Profile Widget, that's when you must specify the value of the name parameter!
body: CustomWidget(myWidget: Profile(name: 'ASAD'),)
please try to use this :
import 'package:flutter/material.dart';
typedef CustomCallBack = Widget Function(String name);
class CustomWidget extends StatefulWidget {
final CustomCallBack myWidget;
CustomWidget({this.myWidget});
#override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: widget.myWidget(
'ASAD'), //I'm able to access the constructor here but now I get an error.
);
}
}
class Profile extends StatefulWidget {
final String name;
Profile({this.name});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('${widget.name}'),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomWidget(
myWidget: (name) => Profile(
name: name,
),
) //I don't want to pass the argument here
);
}
}
How can I pass generic type to the State of a StatefulWidget, Here I want to use my generics in myMethod<T>
class MyWidget<T> extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
#override
Widget build(BuildContext context) {
return Container();
}
myMethod<T>(){
}
}
You just provide the type in your state full widget and then pass it way down to its state:
class MyWidget<T> extends StatefulWidget {
#override
_MyWidgetState<T> createState() => _MyWidgetState<T>();
}
class _MyWidgetState<T> extends State<MyWidget<T>> {
#override
Widget build(BuildContext context) {
return Container();
}
myMethod<T>() {
}
}
Usage:
MyWidget<String>()
_MyWidgetState need to extends State<MyWidget<T>> not just State<MyWidget> and then you can use T within _MyWidgetState
Here's how the Flutter team solves this issue inside the FutureBuilder widget. Instead of having a return type of _MyWidgetState<T> for the createState(), you would need State<MyWidget<T>>.
State<MyWidget<T>> createState() => _MyWidgetState<T>();
Below is the minimal version of what i'm attempting to do with my app that maintains the issue. The slider still responds to being interacted with by showing it's animation, however it does not change the value or actually move. This only seems to occur because the Scaffold has been separated out to it's own widget.
I know that changing it to a stateless widget would fix it in this case, however the version in my app requires state changes.
I've tried adding UniqueKeys up and down the widget tree with no luck, though i'll admit I don't fully understand their use in this case.
Any advice, or a point in the right direction? Should I keep playing around with keys, or am I going about this in the wrong way?
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scaffold Test',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double _value = 20.0;
#override
Widget build(BuildContext context) {
return MyScaffold(
child: Center(
child: Slider(
min: 0,
max: 100,
value: _value,
onChanged: (double value) {
setState(() {
_value = value;
});
},
),
),
);
}
}
class MyScaffold extends StatefulWidget {
final Widget child;
MyScaffold({this.child});
#override
State<StatefulWidget> createState() => new MyScaffoldState(child);
}
class MyScaffoldState extends State<MyScaffold> {
Widget child;
MyScaffoldState(this.child);
#override
Widget build(BuildContext context) {
return Scaffold(
body: child,
);
}
}
As commented by user #pskink, removing the state constructor fixes the issue.
class MyScaffold extends StatefulWidget {
final Widget child;
MyScaffold({this.child});
#override
State<StatefulWidget> createState() => MyScaffoldState();
}
class MyScaffoldState extends State<MyScaffold> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: widget.child,
);
}
}
In flutter, you should never have constructors for states.
if you need to initialize state properties, use initState.
I have an app that looks like this
class MainScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => MainScreenState();
}
class MainScreenState extends State<MainScreen> {
#override
Widget build(BuildContext context) {
return new Container(
child: FlatButton(
onPressed:() {
// Want pop up to launch
},
),
)
}
}
class PopUp extends StatefulWidget {
PopUp({
this.postId
})
#override
State<StatefulWidget> createState() => PopUpState();
}
class PopUpState extends State<PopUp> {
// api logic
#override
Widget build(BuildContext context) {
return new Dialog()
}
}
Is it possible for me to overlay the PopUp widget on top of the MainScreen Widget without using showDialog ? Since i'm trying to make the PopUp stateful in that it processes and rerenders itself depending on the processed data ?