Reputation: 2271
I have been trying to create a raised button with a rounded corner, and gradient background but to no success. I can only implement one or the other. It's been 2 hours and I haven't found a solution myself, on how I can implement both a rounded corner, and a gradient background together.
Below are my codes of my latest attempt to implement a raised button with rounded corner, and gradient background.
Custom class of GradientButton
class RaisedGradientButton extends StatelessWidget {
final Widget child;
final Gradient gradient;
final double width;
final double height;
final Function onPressed;
const RaisedGradientButton({
Key key,
@required this.child,
this.gradient,
this.width = double.infinity,
this.height = 50.0,
this.onPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: 50.0,
decoration: BoxDecoration(
gradient: new LinearGradient(
colors: [
Colors.blue,
Colors.red,
],
begin: FractionalOffset.centerLeft,
end: FractionalOffset.centerRight,
),
),
child: Material(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(128.0)),
// color: Colors.transparent,
child: InkWell(
onTap: onPressed,
child: Center(
child: child,
)),
),
);
}
}
How I use the above code:
RaisedGradientButton(
onPressed: navigateToNextPage,
child: Text("Select Community"),
)
How it looks like:
As you can see, the gradient is there, but when I attempt to create a rounded corner, it overlaps, and the gradient is behind.
Upvotes: 3
Views: 7158
Reputation: 267584
Use ElevatedButton
(Recommended as of Flutter 2.0)
@override
Widget build(BuildContext context) {
final radius = BorderRadius.circular(20);
return Scaffold(
body: Center(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [Colors.cyanAccent, Colors.red]),
borderRadius: radius,
),
child: ElevatedButton(
onPressed: () {},
child: Text('Elevated Button'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: radius),
),
),
),
),
);
}
Upvotes: 1
Reputation: 2836
There is a simple solution. Add the same border radius to both the button and the container inside the button. Here is a simple example.
RaisedButton(
onPressed: () {},
textColor: Colors.white,
color: Colors.transparent,
padding: EdgeInsets.all(0),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(18.0),
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
gradient: LinearGradient(
colors: <Color>[
Colors.black38,
Colors.black26,
Colors.white38,
],
),
),
padding: const EdgeInsets.fromLTRB(24, 12, 24, 12),
child: const Text('Sign In', style: TextStyle(fontSize: 20)),
),
),
Upvotes: 3
Reputation: 2271
If anyone ever encounters the same issue. Here is my code on how I got it solved.
class GradientButton extends StatelessWidget {
final Widget child;
// final Gradient gradient;
final double width;
final double height;
final bool isEnabled;
final Function onPressed;
const GradientButton({
Key key,
@required this.child,
// this.gradient,
this.isEnabled,
this.width,
this.height,
this.onPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Color _statusColor;
if (isEnabled != null) {
// Show gradient color by making material widget transparent
if (isEnabled == true) {
_statusColor = Colors.transparent;
} else {
// Show grey color if isEnabled is false
_statusColor = Colors.grey;
}
} else {
// Show grey color if isEnabled is null
_statusColor = Colors.transparent;
}
return Container(
width: width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
gradient: LinearGradient(
colors: [
Color(0xFF3186E3),
Color(0xFF1D36C4),
],
begin: FractionalOffset.centerLeft,
end: FractionalOffset.centerRight,
),
),
child: Material(
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(4)),
color: _statusColor,
child: InkWell(
borderRadius: BorderRadius.circular(32),
onTap: onPressed,
child: Padding(
padding: EdgeInsets.fromLTRB(24, 16, 24, 16),
child: Center(
child: child,
),
))),
);
}
}
Upvotes: 0
Reputation: 1570
I suggest you put a Container
with a gradient below the button in a Stack
and cut its corners with ClipRRect
while leaving the button's color transparent. This way you keep touch feedback and pressed button shadow, as well as accessibility support.
class RaisedGradientButton extends StatelessWidget {
final Widget child;
final Gradient gradient;
final double width;
final double height;
final Function onPressed;
final borderRadius = BorderRadius.circular(128.0);
RaisedGradientButton({
Key key,
@required this.child,
Gradient gradient,
this.width = double.infinity,
this.height = 50.0,
this.onPressed,
}) : this.gradient = gradient ??
LinearGradient(
colors: [
Colors.blue,
Colors.red,
],
begin: FractionalOffset.centerLeft,
end: FractionalOffset.centerRight,
),
super(key: key);
@override
Widget build(BuildContext context) => Stack(
children: [
Positioned.fill(
child: ClipRRect(
borderRadius: borderRadius,
child: Container(
width: width,
height: height,
decoration: BoxDecoration(
gradient: gradient,
),
),
),
),
Container(
width: width,
height: height,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: borderRadius,
),
padding: EdgeInsets.zero,
child: Center(child: child),
onPressed: onPressed,
color: Colors.transparent,
),
),
],
);
}
Upvotes: 2