【发布时间】:2019-08-19 02:36:17
【问题描述】:
是否可以在颤动中创建一个带有渐变边框的轮廓(透明)按钮?我尝试在 BorderSide 样式中使用 LinearGradient,但不允许这样做。
【问题讨论】:
是否可以在颤动中创建一个带有渐变边框的轮廓(透明)按钮?我尝试在 BorderSide 样式中使用 LinearGradient,但不允许这样做。
【问题讨论】:
我尝试了很多方法来做到这一点,但它们都有其局限性,然后我找到了一个符合我预期的包:https://pub.dev/packages/outline_gradient_button
【讨论】:
OutlinedButton(推荐)创建这个类(空安全代码)
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,
),
),
);
}
}
用法:
MyOutlinedButton(
onPressed: () {},
gradient: LinearGradient(colors: [Colors.indigo, Colors.pink]),
child: Text('OutlinedButton'),
)
【讨论】:
你可以通过一个简单的技巧来实现这一点
你必须定义两个容器。
第一个带有渐变背景的外部容器和第二个带有白色背景的内部容器。作为内部容器的子容器,您可以放置任何东西,例如TextField、Text、另一个按钮等
final kInnerDecoration = BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.circular(32),
);
final kGradientBoxDecoration = BoxDecoration(
gradient: LinearGradient(colors: [Colors.black, Colors.redAccent]),
border: Border.all(
color: kHintColor,
),
borderRadius: BorderRadius.circular(32),
);
现在这是你的视图
Container(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: Container(
child:Text("Button Title with your style"),
decoration: kInnerDecoration,
),
),
height: 66.0,
decoration: kGradientBoxDecoration,
),
【讨论】:
要改变大小,你可以插入一个Container:
OutlineGradientButton(
child: Container(
constraints: BoxConstraints(maxWidth: 300, maxHeight: 50),
height: 50,
alignment: Alignment.center,
child: Text(
'Text',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white, fontSize: 20, fontWeight: FontWeight.w500),
),
),
gradient: LinearGradient(
colors: [Color(0xfff3628b), Color(0xffec3470)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
strokeWidth: 3,
radius: Radius.circular(25),
),
【讨论】:
我花了大约两个小时:)
使用方法:
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
UnicornOutlineButton(
strokeWidth: 2,
radius: 24,
gradient: LinearGradient(colors: [Colors.black, Colors.redAccent]),
child: Text('OMG', style: TextStyle(fontSize: 16)),
onPressed: () {},
),
SizedBox(width: 0, height: 24),
UnicornOutlineButton(
strokeWidth: 4,
radius: 16,
gradient: LinearGradient(
colors: [Colors.blue, Colors.yellow],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
child: Text('Wow', style: TextStyle(fontSize: 16)),
onPressed: () {},
),
],
),
),
),
),
);
}
}
以及课程本身:
class UnicornOutlineButton extends StatelessWidget {
final _GradientPainter _painter;
final Widget _child;
final VoidCallback _callback;
final double _radius;
UnicornOutlineButton({
@required double strokeWidth,
@required double radius,
@required Gradient gradient,
@required Widget child,
@required VoidCallback onPressed,
}) : this._painter = _GradientPainter(strokeWidth: strokeWidth, radius: radius, gradient: gradient),
this._child = child,
this._callback = onPressed,
this._radius = radius;
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _painter,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: _callback,
child: InkWell(
borderRadius: BorderRadius.circular(_radius),
onTap: _callback,
child: Container(
constraints: BoxConstraints(minWidth: 88, minHeight: 48),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_child,
],
),
),
),
),
);
}
}
class _GradientPainter extends CustomPainter {
final Paint _paint = Paint();
final double radius;
final double strokeWidth;
final Gradient gradient;
_GradientPainter({@required double strokeWidth, @required double radius, @required Gradient gradient})
: this.strokeWidth = strokeWidth,
this.radius = radius,
this.gradient = gradient;
@override
void paint(Canvas canvas, Size size) {
// create outer rectangle equals size
Rect outerRect = Offset.zero & size;
var outerRRect = RRect.fromRectAndRadius(outerRect, Radius.circular(radius));
// create inner rectangle smaller by strokeWidth
Rect innerRect = Rect.fromLTWH(strokeWidth, strokeWidth, size.width - strokeWidth * 2, size.height - strokeWidth * 2);
var innerRRect = RRect.fromRectAndRadius(innerRect, Radius.circular(radius - strokeWidth));
// apply gradient shader
_paint.shader = gradient.createShader(outerRect);
// create difference between outer and inner paths and draw it
Path path1 = Path()..addRRect(outerRRect);
Path path2 = Path()..addRRect(innerRRect);
var path = Path.combine(PathOperation.difference, path1, path2);
canvas.drawPath(path, _paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => oldDelegate != this;
}
【讨论】: