是否可以创建一个轮廓(透明)按钮与渐变边界在Flutter?我试图使用线性渐变在BorderSide风格,但它是不允许的。
7vhp5slm1#
我在上面花了大约两个小时:)
使用方法:
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; }
ccrfmcuu2#
你可以通过一个简单的技巧
你必须定义两个容器。第一个外部容器有渐变背景,第二个内部容器有白色背景。作为内部容器的子容器,你可以放置任何东西,例如TextField,Text,另一个按钮等。
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, ),
完成
ef1yzkbh3#
OutlinedButton
创建此类(null安全代码)
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'), )
nhaq1z214#
要更改大小,您可以插入容器:
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), ),
ddrv8njm5#
你可以使用如下的结构。你也可以通过删除BorderRadius将它用作一个平面按钮。
InkWell( onTap: () { print("TAP"); }, child: Container( height: 85, width: 85, padding: EdgeInsets.all(6), decoration: BoxDecoration( borderRadius: BorderRadius.circular(100), gradient: LinearGradient( colors: [Colors.blue, Colors.black], begin: Alignment(-1, -1), end: Alignment(2, 2), ), ), child: Center( child: ClipRRect( borderRadius: BorderRadius.circular(100), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(100), image: DecorationImage( image: Image.network("https://images.unsplash.com/photo-1612151855475-877969f4a6cc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8aGQlMjBpbWFnZXxlbnwwfHwwfHw%3D&w=400&q=80").image, fit: BoxFit.fitHeight, ), //By deleting the image here, you can only use it text. color: Colors.white, border: Border.all( color: Colors.white, width: 4, ), ), child: Center(child: Text("sssss")), //By deleting the text here, you can only use it visually. width: 75, height: 75, ), ), ), ), )
ippsafx76#
Package 您的构件宽度CustomPaint构件,并使用此扩展CustomPainter的**_CustomGradientBorder**。
CustomPaint(painter: const _CustomGradientBorder(thickness: 1, colors: [Colors.red, Colors.green, Colors.blue, Colors.tealAccent], radius: 8), child: //widget here) class _CustomGradientBorder extends CustomPainter{ final double thickness; final List<Color> colors; final double radius; const _CustomGradientBorder({required this.thickness, required this.colors, required this.radius}); @override void paint(Canvas canvas, Size size) { final Path path = Path(); path.moveTo(0, size.height/2); path.lineTo(0, radius); path.quadraticBezierTo(0, 0, radius, 0); path.lineTo(size.width-radius, 0); path.quadraticBezierTo(size.width, 0, size.width, radius); path.lineTo(size.width, size.height-radius); path.quadraticBezierTo(size.width, size.height, size.width-radius, size.height); path.lineTo(radius, size.height); path.quadraticBezierTo(0, size.height, 0, size.height-radius); path.close(); final Paint paint = Paint() ..style = PaintingStyle.stroke ..shader = LinearGradient(colors: colors).createShader(Rect.fromCenter(center: Offset(size.width/2, size.height/2), width: size.width, height: size.height)) ..strokeWidth = thickness; canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return true; }
}
hm2xizp97#
class GradientBorderWidget extends StatelessWidget { final Widget child; const GradientBorderWidget({super.key, required this.child}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 1.5, vertical: 1.5), width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), gradient: const LinearGradient( colors: [color1, color2, color3], begin: Alignment.centerLeft, end: Alignment.centerRight)), alignment: Alignment.center, child: ClipRRect(borderRadius: BorderRadius.circular(15), child: child), ); } }
byqmnocz8#
现在有一个更简单的方法提供。Flutter现在有一个包,可以完美地完成这项工作。我留下了一个链接到文档,以供进一步使用https://pub.dev/packages/gradient_borders。
qrjkbowd9#
我尝试了许多方法来做到这一点,但所有这些方法都有其局限性,然后我发现了一个包,工作如何我期望:https://pub.dev/packages/outline_gradient_button
9条答案
按热度按时间7vhp5slm1#
我在上面花了大约两个小时:)
使用方法:
以及类本身:
ccrfmcuu2#
你可以通过一个简单的技巧
你必须定义两个容器。第一个外部容器有渐变背景,第二个内部容器有白色背景。作为内部容器的子容器,你可以放置任何东西,例如
TextField
,Text
,另一个按钮等。现在这是您的视图
完成
ef1yzkbh3#
使用
OutlinedButton
(推荐)创建此类(null安全代码)
用法:
nhaq1z214#
要更改大小,您可以插入容器:
ddrv8njm5#
你可以使用如下的结构。你也可以通过删除BorderRadius将它用作一个平面按钮。
ippsafx76#
Package 您的构件宽度CustomPaint构件,并使用此扩展CustomPainter的**_CustomGradientBorder**。
}
hm2xizp97#
byqmnocz8#
现在有一个更简单的方法提供。Flutter现在有一个包,可以完美地完成这项工作。我留下了一个链接到文档,以供进一步使用https://pub.dev/packages/gradient_borders。
qrjkbowd9#
我尝试了许多方法来做到这一点,但所有这些方法都有其局限性,然后我发现了一个包,工作如何我期望:https://pub.dev/packages/outline_gradient_button