Reputation: 1679
I am a Java developer and currently learning about Flutter/Dart. I am an adept of clean code with small functions and some widget examples just scare the s*** out of me.
I am trying to implement a Card widget with some transaction information (price, title and date). Currently the code looks like this:
class TransactionCard extends StatelessWidget {
final Transaction _transaction;
TransactionCard(this._transaction);
@override
Widget build(BuildContext context) {
return Container(
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_PriceContainer(_transaction.amount),
_DetailContainer(_transaction.title, _transaction.date),
],
),
),
);
}
}
// Inner Widgets
class _PriceContainer extends Container {
_PriceContainer(double amount)
: super(
margin: EdgeInsets.symmetric(
vertical: 10,
horizontal: 15,
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.purple,
width: 2,
),
),
padding: EdgeInsets.all(10),
child: Text(
amount.toString(),
style: _amountTextStyle(),
),
);
}
class _DetailContainer extends Container {
_DetailContainer(String title, DateTime date)
: super(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: _titleTextStyle(),
),
Text(
date.toString(),
style: _dateTextStyle(),
),
],
),
);
}
// Text styles
TextStyle _amountTextStyle() {
return TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.purple,
);
}
TextStyle _titleTextStyle() {
return TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
);
}
TextStyle _dateTextStyle() {
return TextStyle(color: Colors.grey);
}
I have used two approaches:
Is there an approach preferable to the other? A third one? Is there a bad practice to create multiple Widgets on the same file?
Upvotes: 4
Views: 1906
Reputation: 127034
As mentioned in the comments and in the Flutter documentation, you should always compose widgets instead of inheriting from e.g. a Container
.
In your case, this would look like this:
class _PriceContainer extends StatelessWidget {
final double amount;
const _PriceContainer({
Key key,
this.amount,
}) : super(key: key);
@override
Widget build(BuildContext context) => Container(
margin: const EdgeInsets.symmetric(
vertical: 10,
horizontal: 15,
),
decoration: BoxDecoration(
border: Border.all(
color: Colors.purple,
width: 2,
),
),
padding: EdgeInsets.all(10),
child: Text(
amount.toString(),
style: _amountTextStyle,
),
);
}
This is analogous for your other widgets.
Declaring top-level functions is generally fine, however, in this case, you should really define a top-level property instead - preferably declare a const
to take advantage of compile-time constants:
const _amountTextStyle = TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.purple,
);
You should be able to apply the same to your other text styles.
Upvotes: 2