Flutter RawMaterialButton won't get transparent - flutter

I'm using this simple CircularButtonWithIcon. The one problem is that it won't respect transparency when no color is setted.
class CircularButtonWithIcon extends StatefulWidget {
CircularButtonWithIcon({
Key key,
#required this.onPress,
this.padding,
this.border,
this.active = false,
this.marginRight,
this.marginLeft,
this.icon,
this.color,
this.activeColor,
this.text,
this.splashColor,
this.image,
this.hasState,
this.borderColor,
}) : super(key: key);
final double padding;
final double border;
final double marginRight;
final double marginLeft;
final Icon icon;
final Image image;
final Color color;
final Color activeColor;
final Color borderColor;
final Widget text;
final Color splashColor;
final Function onPress;
final bool active;
final bool hasState;
#override
_CircularButtonWithIconState createState() => _CircularButtonWithIconState();
}
class _CircularButtonWithIconState extends State<CircularButtonWithIcon> {
bool active;
#override
void initState() {
super.initState();
active = widget.active;
}
#override
Widget build(BuildContext context) {
return FittedBox(
child: Container(
margin: EdgeInsets.only(left: widget.marginLeft ?? 0, right: widget.marginRight ?? 0),
child: RawMaterialButton(
onPressed: () {
setState(() {
active = !active; // don't use widget.active
});
if (widget.onPress != null) widget.onPress();
},
fillColor: active
? widget.activeColor ?? widget.color ?? Colors.transparent
: widget.color ?? Colors.transparent,
splashColor: widget.splashColor ?? Colors.grey,
child: widget.text != null
? Container(
child: widget.text,
)
: widget.image ?? widget.icon,
//padding: EdgeInsets.all(15.0),
padding: widget.padding != null ? EdgeInsets.all(widget.padding) : EdgeInsets.all(15.0),
shape: CircleBorder(
side: BorderSide(
width: widget.border ?? 2.0,
style: BorderStyle.solid,
color: widget.borderColor ?? Colors.grey),
),
),
),
);
}
}
Take a look at:
fillColor: active
? widget.activeColor ?? widget.color ?? Colors.transparent
: widget.color ?? Colors.transparent,
When no color is seted, it should be transparent.
I did this:
CircularButtonWithIcon(
padding: 10,
border: 3,
onPress: () => {},
icon: Icon(Icons.remove,
color: Color.green,
size: 60))
and it's getting a color background instead of merging:
however it looks like it's just the background but darker. Is it possible that the button is adding a shadow on top of the background color? How can I remove it? I looked at https://api.flutter.dev/flutter/material/RawMaterialButton-class.html and couldn't find anything related to shadow effects on the button

Related

Flutter Button Click and Button Color Control

I have six buttons on the screen and they all do the same function. But I want to control the colors of these buttons to be clicked. If the button is clicked, the button color should be green (I'm doing this buttonColorDisable.) Everything is normal so far, but in _buttonFunction() widget.callbackColor(); When I call it, I expect all button colors to change again, but only the last button is affected. Other buttons still remain green. how do i solve this.
class BuildNumButton extends StatefulWidget {
final int number;
final Color color;
final Color buttonColorDisable;
final Function callbackColor;
final Function callbackList;
final Function callbackScore;
final Function callbackTarget;
const BuildNumButton({
Key? key,
required this.number,
required this.callbackScore,
required this.callbackList,
required this.callbackTarget,
required this.callbackColor,
required this.color,
required this.buttonColorDisable,
}) : super(key: key);
#override
State<BuildNumButton> createState() => _BuildNumButtonState();
}
class _BuildNumButtonState extends State<BuildNumButton> {
bool isButtonVisible = false;
void _buttonFunction() {
isButtonVisible = true;
CalculateScore.sumNumbers(widget.number);
CalculateScore.calculateScore();
widget.callbackScore();
if (CalculateScore.answer == true) {
if (!CalculateScore.endGame) {
widget.callbackList();
widget.callbackColor();
isButtonVisible = false;
}
widget.callbackTarget();
}
}
#override
Widget build(BuildContext context) {
return SizedBox(
width: 150,
height: 120,
child: TextButton(
style: ButtonStyle(
backgroundColor: isButtonVisible
? MaterialStateProperty.all(
widget.buttonColorDisable) //button color green
: MaterialStateProperty.all(widget.color),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: const BorderSide(color: Colors.white, width: 3),
),
),
),
onPressed: isButtonVisible ? null : _buttonFunction,
child: Text(
widget.number.toString(),
style: numButtonTextStyle,
),
),
);
}
}
I will prefer creating List<int> to hold tapped index and use BuildNumButton extends StatelessWidget.
Run on dartPad.
class BuildNumButton extends StatelessWidget {
final int number;
final Color color;
final Color buttonColorDisable;
final VoidCallback callback;
final bool isDisable;
const BuildNumButton({
Key? key,
required this.number,
required this.color,
required this.buttonColorDisable,
required this.callback,
required this.isDisable,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return SizedBox(
width: 150,
height: 120,
child: TextButton(
style: ButtonStyle(
backgroundColor: isDisable
? MaterialStateProperty.all(
buttonColorDisable) //button color green
: MaterialStateProperty.all(color),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
side: const BorderSide(color: Colors.white, width: 3),
),
),
),
onPressed: isDisable ? null : callback,
child: Text(
number.toString(),
),
),
);
}
}
and VoidCallback used to get tapEvent and based on condition update the state.
List<int> disableButtons = [];
.....
...List.generate(
6,
(index) => BuildNumButton(
buttonColorDisable: Colors.green,
isDisable: disableButtons.contains(index),
callback: () {
disableButtons.add(index);
if (disableButtons.length == 6) disableButtons.clear();
setState(() {});
},
color: Colors.cyanAccent,
number: index,
),
)

Is it possible to trigger a CupertinoContextMenu from a single click on an icon in flutter?

I have the CupertinoContextMenu setup and it works well. However, I have an Icon in a separate widget which when tapped (single tap) would also trigger the opening of the Context Menu.
Is anything like this possible?
I hacked something a little remotly iosy together from the material PopupMenuButton. Maybe it can help you as a basis for styling.
import 'package:flutter/material.dart';
class IosLikePopupMenuButton extends StatelessWidget {
final double borderRadius;
final Color _backgroundColor = const Color.fromARGB(209, 235, 235, 235);
final List<IosLikePopupMenuItem> Function(BuildContext) itemBuilder;
const IosLikePopupMenuButton({
Key? key,
this.borderRadius = 24.0,
required this.itemBuilder,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return PopupMenuButton<String>(
icon: const Icon(Icons.more_horiz),
itemBuilder: (context1) {
/// give the current context and map the IosLikePopupMenuItem dtos to PopupMenuEntry while splicing in dividers
return itemBuilder(context1)
.map((e) => e.popupMenuItems())
.toList()
.fold(
List<PopupMenuEntry<String>>.empty(growable: true),
(p, e) => [
...p,
...[e, const PopupMenuDivider()]
])
/// delete the last divider
..removeLast();
},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(borderRadius),
),
),
color: _backgroundColor,
);
}
}
class IosLikePopupMenuItem {
final double menuItemHeight, minSpaceBtwnTxtAndIcon;
final String lableText;
final IconData icon;
final void Function() onTap;
final TextStyle _textStyle =
const TextStyle(color: Colors.black, fontSize: 22.0);
IosLikePopupMenuItem({
this.menuItemHeight = 24.0,
this.minSpaceBtwnTxtAndIcon = 48.0,
required this.lableText,
required this.icon,
required this.onTap,
});
PopupMenuItem<String> popupMenuItems() => PopupMenuItem<String>(
height: menuItemHeight,
textStyle: _textStyle,
onTap: onTap,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
lableText,
),
SizedBox(width: minSpaceBtwnTxtAndIcon),
Icon(icon),
],
),
);
}

Reusable Switch Widget using the flutter_switch package

I am trying to make a reusable Switch Widget using the flutter_switch package https://pub.dev/packages/flutter_switch.
Unfortnaly how i maked it, it does not change the look, the size etc. of the widget when i use it.
If i make a reusable Swich without using the package it works fine.
Somebody have a idea what is wrong here?
Thanks for any help
import 'package:flutter/material.dart';
import 'package:flutter_switch/flutter_switch.dart';
class MyFlutterSwitch extends StatelessWidget {
const MyFlutterSwitch(
{required this.onToggle,
required this.value,
required this.activeColor,
required this.inactiveColor,
required this.activeTextColor,
required this.inactiveTextColor,
required this.toggleColor,
required this.activeToggleColor,
required this.inactiveToggleColor,
this.padding,
this.borderRadius,
this.toogleSize,
Key? key})
: super(key: key);
final void Function(bool) onToggle;
final bool value;
final Color activeColor;
final Color inactiveColor;
final Color activeTextColor;
final Color inactiveTextColor;
final Color toggleColor;
final Color? activeToggleColor;
final Color? inactiveToggleColor;
final double? padding;
final double? borderRadius;
final double? toogleSize;
#override
Widget build(BuildContext context) {
return SizedBox(
height: 20.0,
width: 40.0,
child: FlutterSwitch(
toggleSize: 15.0,
borderRadius: 60.0,
padding: 3.0,
activeTextColor: const Color.fromARGB(255, 198, 40, 40),
inactiveTextColor: const Color.fromARGB(255, 46, 125, 50),
activeToggleColor: Colors.red[800],
inactiveToggleColor: Colors.green[800],
inactiveColor: const Color(0xFF55DDCA),
activeColor: const Color(0xFFF87A54),
onToggle: onToggle,
value: value,
),
);
}
}
You need to pass your functions values if you want to pass custom values in every instance of this widget if you want :
class MyFlutterSwitch extends StatelessWidget {
const MyFlutterSwitch(
{
this.toggleSize: 15.0,
this.borderRadius: 60.0,
this.padding: 3.0,
this.activeTextColor: const Color.fromARGB(255, 198, 40, 40),
this.inactiveTextColor: const Color.fromARGB(255, 46, 125, 50),
this.activeToggleColor: Colors.red[800],
this.inactiveToggleColor: Colors.green[800],
this.inactiveColor: const Color(0xFF55DDCA),
this.activeColor: const Color(0xFFF87A54),
required this.onToggle,
required this.value,
Key? key})
: super(key: key);
final void Function(bool) onToggle;
final bool value;
final Color activeColor;
final Color inactiveColor;
final Color activeTextColor;
final Color inactiveTextColor;
final Color toggleColor;
final Color? activeToggleColor;
final Color? inactiveToggleColor;
final double? padding;
final double? borderRadius;
final double? toogleSize;
#override
Widget build(BuildContext context) {
return SizedBox(
height: 20.0,
width: 40.0,
child: FlutterSwitch(
toggleSize: toggleSize,
borderRadius: borderRadius,
padding: padding,
activeTextColor: activeTextColor,
inactiveTextColor: inactiveTextColor,
activeToggleColor: activeToggleColor,
inactiveToggleColor: inactiveToggleColor,
inactiveColor: inactiveColor,
activeColor: activeColor,
onToggle: onToggle,
value: value,
),
);
}
}
It looks like you're not passing in the values from your parameter list. Your build method should look something like this.
#override
Widget build(BuildContext context) {
return SizedBox(
height: 20.0,
width: 40.0,
child: FlutterSwitch(
toggleSize: toogleSize ?? 15.0,
borderRadius: borderRadius ?? 60.0,
padding: padding ?? 3.0,
activeTextColor: activeColor,
inactiveTextColor: inactiveColor,
activeToggleColor: activeToggleColor ?? Colors.red[800],
inactiveToggleColor: inactiveToggleColor ?? Colors.green[800],
inactiveColor: inactiveColor,
activeColor: activeColor,
onToggle: onToggle,
value: value,
),
);
}

4 positional argument(s) expected, but 0 found

Not able to print clicked after clicking and all area from CustomBtn bracket is red underlined till the bracket closed
CustomBtn(
text: "Create New Account",
onPressed: () {
print("Clicked");
},
),
Here is CustomBtn class it is another file
import 'package:flutter/material.dart';
class CustomBtn extends StatelessWidget {
final String write;
final void Function() onPressed;
final bool outlineBtn;
final bool isLoading;
CustomBtn(this.write, this.onPressed, this.outlineBtn, this.isLoading, {Key? key} : super(key: key));
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onPressed,
child: Container(
height: 70.0,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
width: 2.0,
),
borderRadius: BorderRadius.circular(
12.0,
),
),
margin: const EdgeInsets.symmetric(
horizontal: 24.0,
vertical: 24.0,
),
child: Text(
write ?? "text",
style: const TextStyle(
fontSize: 16.0,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
),
);
}
}
I am Trying and seeing from this youtube video
https://youtu.be/YPqYnM6KjZI
and here is the time where i am facing problem
at 12:50 https://youtu.be/YPqYnM6KjZI?t=770[][2]
your constructor has positional parameters and therefore are required and you have to pass values to it otherwise the compiler complains :). Either change them to named parameters and make the type nullable like so:
final String? write;
CustomBtn({
this.write,
etc...
})
or simply pass some values
This is because your constructor has
final String write;
final void Function() onPressed;
final bool outlineBtn;
final bool isLoading;
so it requires to send the parameters to works.
Here you Flutter is waiting a call of your customBtn like this :
CustomBtn(
write: "Create New Account",
onPressed: () {
print("Clicked");
},
outlineBtn: false,
isLoading: false,
),
If you don't need to require this parameters, you can put a ? after the type in the declaration, like below.
final String? write;
final void? Function() onPressed;
final bool? outlineBtn;
final bool? isLoading;
Just convert this line:
CustomBtn(this.write, this.onPressed, this.outlineBtn, this.isLoading, {Key? key} : super(key: key));
to:
CustomBtn({this.write, this.onPressed, this.outlineBtn, this.isLoading, Key? key} : super(key: key));

ElevatedButton, TextButton and OutlinedButton gradient

Before it was easy to make a gradient button with the default ButtonThemeData... But now I can't figure out how to properly make a custom gradient button using the new MaterialButtons.
I am trying to make a three custom gradient button which must use the ButtonStyle defined in the AppTheme (splashColor, elevation, ...).
ElevatedButton
GradientElevatedButton that uses the ElevatedButtonThemeData with a gradient background
TextButton
GradientTextButton that uses the TextButtonThemeData with a gradient text
OutlinedButton
GradientOutlinedButton that uses the OutlinedButtonThemeData with a gradient border and a gradient text
Already tried
I have tried to wrap an ElevatedButton with a ShaderMask but it covers the ink animations so it doesn't accomplish my goals.
ElevatedButton
DecoratedBox(
decoration: BoxDecoration(gradient: LinearGradient(colors: [Colors.red, Colors.blue])),
child: ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(primary: Colors.transparent),
child: Text('Elevated Button'),
),
)
OutlinedButton
For OutlinedButton, you need to do some extra steps. Create a class (null-safe):
class MyOutlinedButton extends StatelessWidget {
final VoidCallback onPressed;
final Widget child;
final ButtonStyle? style;
final Gradient? gradient;
final double thickness;
const MyOutlinedButton({
Key? key,
required this.onPressed,
required this.child,
this.style,
this.gradient,
this.thickness = 2,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(gradient: gradient),
child: Container(
color: Colors.white,
margin: EdgeInsets.all(thickness),
child: OutlinedButton(
onPressed: onPressed,
style: style,
child: child,
),
),
);
}
}
Usage:
MyOutlinedButton(
onPressed: () {},
gradient: LinearGradient(colors: [Colors.indigo, Colors.pink]),
child: Text('OutlinedButton'),
)
I don't know if it helps, but I just did it by myself this way. Still don't get why they have to make things more complicated.
import 'package:flutter/material.dart';
import 'package:my_app/src/utils/style_helper.dart';
import 'package:my_app/src/utils/themes.dart';
class SecondaryButtonState extends State<SecondaryButton> {
setPressed(bool value) {
setState(() {
widget.pressed = value;
});
}
getDecoration() {
if (widget.disabled) {
return BoxDecoration(
borderRadius: BorderRadius.circular(SH.BORDER_RADIUS),
color: ThemeColors.secondaryLight,
);
}
if (!widget.pressed) {
return BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: LinearGradient(
begin: FractionalOffset.topCenter,
end: FractionalOffset.bottomCenter,
colors: [ThemeColors.gradient, ThemeColors.secondary]),
);
} else {
return BoxDecoration(
borderRadius: BorderRadius.circular(SH.BORDER_RADIUS),
color: ThemeColors.secondary);
}
}
void onTapDown(TapDownDetails details) {
if (!widget.disabled) {
setPressed(true);
}
}
void onTapUp(TapUpDetails details) {
if (!widget.disabled) {
setPressed(false);
widget.onPressed();
}
}
TextStyle getTextStyle(context, Set<MaterialState> states) {
return Theme.of(context)
.textButtonTheme
.style
.textStyle
.resolve(states)
.copyWith();
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: onTapDown,
onTapUp: onTapUp,
child: Container(
width: 400,
decoration: getDecoration(),
padding: EdgeInsets.symmetric(vertical: SH.PC, horizontal: SH.P3),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
widget.icon != null ? widget.icon : Container(),
Text(
widget.label,
style: Theme.of(context)
.elevatedButtonTheme
.style
.textStyle
.resolve(null)
.copyWith(),
),
])),
);
}
}
class SecondaryButton extends StatefulWidget {
SecondaryButton(
{#required this.onPressed,
#required this.label,
this.icon,
this.disabled = false});
final GestureTapCallback onPressed;
final String label;
bool disabled;
final Icon icon;
bool pressed = false;
#override
State<StatefulWidget> createState() {
return SecondaryButtonState();
}
}