有没有可能在Flutter 中创建一个带有渐变边框的轮廓(透明)按钮?我试着在BorderSide样式中使用LinearGradent,但这是不允许的.

推荐答案

我在上面花了大约两个小时:)

flat outlined button with gradient

使用方法:

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;
}

Flutter相关问答推荐

创建多个具有适当填充和对齐的按钮的最佳方法

如何使一个悬浮的appbar在flutter?

在Riverpod ConsumerWidget中使用文本编辑控制器

创建后检索FiRestore文档ID

为什么Flutter InAppWebView中的DatePicker看起来很旧?

功能不起作用的Flutter 块复制

在选项卡栏视图中搜索和筛选不起作用

如何使文本表格域在抖动中变圆?

带有命名参数的回调函数不起作用

使用 Flutter 和 Dio 将图像上传到 API

如何获取flutter中gridview项目占用的高度和宽度?

Riverpod 注册多少个 providers

在允许屏幕 Select 和点击的同时保持通用对话框显示

如何与 PostgreSQL 和外部网站交互 flutter apk?

Flutter Dart 功能弹出错误的小部件?

如何根据应用程序主题(深色和浅色)更改谷歌 map 的主题?

如何将 List 转换为 String []?

Flutter Desktop,如何获取windows用户配置文件名称?

在Flutter 中将数字转换为印度文字样式

RangeError(索引):无效值:有效值范围为空:点击文章时为0