Outlined transparent button with gradient border in flutter

后端 未结 3 1651
情歌与酒
情歌与酒 2021-02-02 00:11

Is it possible to create an outlined(transparent) button with gradient border in flutter? I tried to use LinearGradient in BorderSide style but it\'s not allowed.

相关标签:
3条回答
  • 2021-02-02 00:58

    To change the size, you can insert a 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),
    ),
    
    0 讨论(0)
  • 2021-02-02 01:02

    I spent about two hours on it :)

    how to use:

    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: () {},
                    ),
                  ],
                ),
              ),
            ),
          ),
        );
      }
    }
    

    and the class itself:

    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;
    }
    
    0 讨论(0)
  • 2021-02-02 01:10

    You can achieve this by doing just a simple trick

    You have to define two Containers. First outer container with a gradient background and the second inner container with white background. and as a child of the inner container, you can place anything e.g. TextField, Text, another button, etc.

    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),
    );
    

    Now this is your View

      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,
      ),
    

    Done

    0 讨论(0)
提交回复
热议问题