-
First of all I know this has nothing to do with Lets say we create a Container(
decoration: ShapeDecoration(
shape: CardTheme.of(context).shape ??
const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(
4))) // on null take the default Card borderShape
)); With this it is impossible (from my understanding to edit the used P.S. I am really happy for you that the rest of the community saw the benefit of your packages and the like count now reflects that. 👍 |
Beta Was this translation helpful? Give feedback.
Replies: 8 comments
-
I think I have the answer to this and will reply when GitHub is working better again :) |
Beta Was this translation helpful? Give feedback.
-
This is actually a very good question, and yes we can do it. It is a bit tricky and maybe not so obvious. I faced what I think is a similar challenge in the repo examples, in the widgets that display the colors, when I wanted them to use the theme dependent shape of the card theme, but I wanted to also add a border side with a color, to the themed card with whatever radius it has in the theme. The solution I came up with involves checking if we have a theme that includes a none null shape in I'm sure some variation of this could work with your decoration scenario too, you would not even really need the theme wrapper, just the logic to copy in the desired border side and its color or themed radius. The Was it something along this line that you were looking for? |
Beta Was this translation helpful? Give feedback.
-
yes, thanks as always. This is what I was looking for. Edit: |
Beta Was this translation helpful? Give feedback.
-
Not at keyboard anymore, but I will check in tomorrow and see if I can't make an example using your Container example and use case. And yes I on purpose in my use case wanted to leave it untouched if the parent had been themed to have another not anticipateed Shape type or custom shape. I did not really need it for my use case, but I justed wanted a widget that would not override the card theme, if the theme was not the cases it intended to handle, ie null no theme at all, so replicate default behavior of card, and if themed with expected sub theme only then add the colored border. |
Beta Was this translation helpful? Give feedback.
-
Hi again @jlnrrg, so to return as promised to your BoxDecoration example and question. This should work: @override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
// Get the card theme's ShapeBorder.
ShapeBorder? border = theme.cardTheme.shape;
// Make a BorderRadius that defaults to default un-themed Card's border radius behavior of 4.
BorderRadius radius = const BorderRadius.all(Radius.circular(4));
// If we have ShapeBorder in card theme of type RoundedRectangleBorder, grab its
// border radius, if it is a BorderRadius.
if (border is RoundedRectangleBorder) {
if (border.borderRadius is BorderRadius) {
radius = border.borderRadius as BorderRadius;
}
}
// We can now use this card theme dependent border radius when it was a
// RoundedRectangleBorder, border radius to make a BoxDecoration
// e.g. for a Container that has the same theme dependent border radius.
final Container myContainer = Container(
decoration: BoxDecoration(
borderRadius: radius,
),
);
... It is a bit tedious as you see, but you can always inspect the type of the used implementations of the abstract classes used in the property interfaces, to extract the property's used implementation dependent values by accessing it with "as", to do so safely you should of course first examine that it is of the type you expect it to be. Otherwise you will have a run time exception if it is not, you can of course let it throw and catch it, but making sure it is of the type where you expect to find the property you need, and only do the as cast to get the prop values, is imo cleaner. Hope this is what you looked for and that it works for your use case. I did not actually buidl the code, only checked with IDE that it passes the analyser so it should build 😃 This is a good question tough and I think I will add it to docs FAQ in the next improvement phase of the docs. I plan to move the docs to its own doc site and have only minimal content in the pub readme. Maintaining a big single readme file in pub.dev is a pain and it is also not so nice to read. |
Beta Was this translation helpful? Give feedback.
-
Yes, this helped a lot. As a thanks youFor the theme selection in my app I created a theme_card, to display the diefferences better to the user. Codeclass ThemeCard extends StatefulWidget {
const ThemeCard({
Key? key,
required this.appTheme,
this.brightness = Brightness.light,
required this.onTap,
this.wonColor = Constants.wonColorDefault,
this.lostColor = Constants.lostColorDefault,
this.notPlayedColor = Constants.notPlayedColorDefault,
}) : super(key: key);
final AppTheme appTheme;
final Brightness brightness;
final Color wonColor;
final Color lostColor;
final Color notPlayedColor;
final void Function(AppTheme appTheme, Brightness brightness) onTap;
@override
State<ThemeCard> createState() => _ThemeCardState();
}
class _ThemeCardState extends State<ThemeCard> {
BorderRadius get borderRadius => BorderRadius.circular(10);
late ThemeData themeData;
@override
void initState() {
super.initState();
themeData = widget.appTheme.toTheme(widget.brightness);
}
@override
void didUpdateWidget(ThemeCard oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.appTheme != oldWidget.appTheme) {
themeData = widget.appTheme.toTheme(widget.brightness);
}
if (widget.wonColor != oldWidget.wonColor ||
widget.lostColor != oldWidget.lostColor ||
widget.notPlayedColor != oldWidget.notPlayedColor) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
final bool themeIsActive =
Theme.of(context).colorScheme == themeData.colorScheme;
return InkWell(
borderRadius: BorderRadius.circular(20),
onTap: () => widget.onTap(widget.appTheme, widget.brightness),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
IgnorePointer(
child: Padding(
padding: const EdgeInsets.all(5),
child: Theme(
data: themeData,
child: Container(
height: 150,
width: 100,
decoration: BoxDecoration(
color: themeData.scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(15),
border: Border.all(
color: themeIsActive
? themeData.primaryColor
: Colors.grey,
width: 5)),
child: ClipRRect(
borderRadius: borderRadius,
child: Stack(
children: [
Column(
children: [
// AppBar
Container(
height: 25,
color: themeData.appBarTheme.backgroundColor,
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: [
Icon(
const AppIcons.drawer().toIcon(context),
size: 12,
color:
themeData.appBarTheme.foregroundColor,
),
const SizedBox(width: 8),
Expanded(
child: Text(LocaleKeys.title.tr(),
style: themeData.textTheme.headline1
?.copyWith(
fontSize: 10,
color: themeData.appBarTheme
.foregroundColor)),
),
Icon(
const AppIcons.moreVertical()
.toIcon(context),
size: 12,
color:
themeData.appBarTheme.foregroundColor,
)
],
),
),
),
// Body
Padding(
padding: const EdgeInsets.fromLTRB(8, 5, 8, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(LocaleKeys.text.tr(),
style: themeData.textTheme.bodyText1
?.copyWith(fontSize: 8)),
const Expanded(
child: Divider(height: 1))
],
),
FlatCard(
margin: const EdgeInsets.symmetric(
vertical: 3),
child: Container(
height: 20,
width: double.infinity,
child: Stack(
children: [
Transform.scale(
alignment:
Alignment.centerLeft,
scale: 0.4,
child: Checkbox(
value: true,
onChanged: (_) {},
)),
Container(
padding:
const EdgeInsets.only(
left: 20),
alignment:
Alignment.centerLeft,
child: Text(
LocaleKeys.text.tr(),
style: themeData
.textTheme.bodyText1
?.copyWith(
fontSize: 8))),
],
)),
),
// FlatCard(
// margin: const EdgeInsets.symmetric(vertical: 3),
// child:
// Container(height: 20, width: double.infinity),
// ),
Row(
children: [
Text(LocaleKeys.winner.tr(),
style: themeData.textTheme.bodyText1
?.copyWith(fontSize: 8)),
const Expanded(
child: Divider(height: 1))
],
),
// Selector Pill
Padding(
padding: const EdgeInsets.symmetric(
vertical: 3),
child: Container(
height: 15,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(15)),
child: Row(
children: [
Flexible(
child: Container(
width: double.infinity,
color: themeData
.colorScheme
.primary)),
Flexible(
child: Container(
width: double.infinity,
color: themeData
.colorScheme.secondary,
))
],
),
)),
Row(
children: [
Text(LocaleKeys.game_default.tr(),
style: themeData.textTheme.bodyText1
?.copyWith(fontSize: 8)),
const Expanded(
child: Divider(height: 1))
],
),
Padding(
padding: const EdgeInsets.only(top: 2),
child: Wrap(
spacing: 2,
children: [
Container(
height: 10,
width: 10,
decoration: BoxDecoration(
color: widget.wonColor,
borderRadius:
BorderRadius.circular(3)),
child: const Center(
child: Text(
'5',
style: TextStyle(
fontSize: 5,
color: Colors.white),
)),
),
Container(
height: 10,
width: 10,
decoration: BoxDecoration(
color: widget.lostColor,
borderRadius:
BorderRadius.circular(3)),
child: const Center(
child: Text(
'2',
style: TextStyle(
fontSize: 5,
color: Colors.white),
)),
),
Container(
height: 10,
width: 10,
decoration: BoxDecoration(
color: widget.notPlayedColor,
borderRadius:
BorderRadius.circular(3)),
child: const Center(
child: Text(
'2',
style: TextStyle(
fontSize: 5,
color: Colors.white),
)),
),
],
)),
],
)),
],
),
Container(
padding: const EdgeInsets.only(bottom: 5, right: 5),
alignment: Alignment.bottomRight,
child: SizedBox(
height: 20,
width: 20,
child: FloatingActionButton(
elevation: 0,
child: Icon(
themeIsActive
? const AppIcons.check()
.toIcon(context)
: const AppIcons.close()
.toIcon(context),
size: 13),
onPressed: () {},
)))
],
)),
),
),
)),
Text(widget.appTheme.toString())
],
),
);
}
} |
Beta Was this translation helpful? Give feedback.
-
That looks really cool. Thx, I could definitely enhance some of the examples with it or something similar in future versions. Nice work! 👍 |
Beta Was this translation helpful? Give feedback.
-
I took inspiration from TachiyomiJ2K, which looks like this. |
Beta Was this translation helpful? Give feedback.
Hi again @jlnrrg, so to return as promised to your BoxDecoration example and question. This should work: