【问题标题】:Is there a way to make the tab bar indicator line a gradient in flutter?有没有办法让标签栏指示线在颤动中渐变?
【发布时间】:2019-12-29 02:33:02
【问题描述】:

我正在尝试创建一个带有渐变下划线的 TabBar,如下图所示。

我尝试按照之前帖子的建议使用 BoxDecoration,但它并没有完全按照我想要的方式显示。

TabBar(
        labelColor: Theme.of(context).primaryColor,
        indicator: BoxDecoration(
          gradient: LinearGradient(
  colors: const [Color(0xFF10C7E0), Color(0xFF00D5C3)],
),
        ),
        tabs: ...,
      ),

当我尝试这样做时,我得到的是

有人指出此帖与 10 个月前发布的how-to-give-a-gradient-line-in-tab-bar-indicator 重复。但是那里说明的方法不再有效。是的,我试过了。

【问题讨论】:

标签: flutter flutter-layout


【解决方案1】:

这个选项有什么问题? (基于链接中的代码)

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: AppBar(
            title: Text('All', style: TextStyle(color: const Color(0xff596173))),
            backgroundColor: Colors.white,
            centerTitle: true,
            bottom: TabBar(
              labelColor: const Color(0xff525c6e),
              unselectedLabelColor: const Color(0xffacb3bf),
              indicatorPadding: EdgeInsets.all(0.0),
              indicatorWeight: 4.0,
              labelPadding: EdgeInsets.only(left: 0.0, right: 0.0),
              indicator: ShapeDecoration(
                  shape: UnderlineInputBorder(
                      borderSide: BorderSide(color: Colors.transparent, width: 0, style: BorderStyle.solid)),
                  gradient: LinearGradient(colors: [Color(0xff0081ff), Color(0xff01ff80)])),
              tabs: <Widget>[
                Container(
                  height: 40,
                  alignment: Alignment.center,
                  color: Colors.white,
                  child: Text("Visual"),
                ),
                Container(
                  height: 40,
                  alignment: Alignment.center,
                  color: Colors.white,
                  child: Text("Tabular"),
                ),
              ],
            ),
          ),
          body: Container(color: Colors.grey[200]),
        ),
      ),
    );
  }
}

【讨论】:

  • 谢谢。我发现我的错误,我在 tabs 属性中使用 Tab Widgets 而不是 Container。
【解决方案2】:

您可以通过修改默认的UnderlineTabIndicator来创建自己的指标。

import 'package:flutter/material.dart';

class CustomUnderlineTabIndicator extends Decoration {
  /// Create an underline style selected tab indicator.
  ///
  /// The [borderSide] and [insets] arguments must not be null.
  const CustomUnderlineTabIndicator({
    this.gradient,
    this.insets = EdgeInsets.zero,
    this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
  });

  /// The color and weight of the horizontal line drawn below the selected tab.
  final BorderSide borderSide;

  final Gradient? gradient;

  /// Locates the selected tab's underline relative to the tab's boundary.
  ///
  /// The [TabBar.indicatorSize] property can be used to define the tab
  /// indicator's bounds in terms of its (centered) tab widget with
  /// [TabBarIndicatorSize.label], or the entire tab with
  /// [TabBarIndicatorSize.tab].
  final EdgeInsetsGeometry insets;

  @override
  Decoration? lerpFrom(Decoration? a, double t) {
    if (a is CustomUnderlineTabIndicator) {
      return CustomUnderlineTabIndicator(
        gradient: Gradient.lerp(a.gradient, gradient, t),
        borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
        insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!,
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  Decoration? lerpTo(Decoration? b, double t) {
    if (b is CustomUnderlineTabIndicator) {
      return CustomUnderlineTabIndicator(
        gradient: Gradient.lerp(gradient, b.gradient, t),
        borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
        insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!,
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  BoxPainter createBoxPainter([VoidCallback? onChanged]) {
    return _CustomUnderlinePainter(this, onChanged);
  }

  Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
    final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
    return Rect.fromLTWH(
      indicator.left,
      indicator.bottom - borderSide.width,
      indicator.width,
      borderSide.width,
    );
  }

  @override
  Path getClipPath(Rect rect, TextDirection textDirection) {
    return Path()..addRect(_indicatorRectFor(rect, textDirection));
  }
}

class _CustomUnderlinePainter extends BoxPainter {
  _CustomUnderlinePainter(this.decoration, VoidCallback? onChanged)
      : super(onChanged);

  final CustomUnderlineTabIndicator decoration;

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    assert(configuration.size != null);
    final Rect rect = offset & configuration.size!;
    final TextDirection textDirection = configuration.textDirection!;
    final Rect indicator = decoration
        ._indicatorRectFor(rect, textDirection)
        .deflate(decoration.borderSide.width / 2.0);
    final Paint paint = decoration.borderSide.toPaint()
      ..strokeCap = StrokeCap.square;
    paint.shader =
        decoration.gradient?.createShader(rect, textDirection: textDirection);
    canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
  }
}

刚刚复制了UnderlineTabIndicator 并为其添加了渐变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-13
    • 2019-03-27
    • 2021-09-01
    • 2020-03-20
    • 1970-01-01
    • 2017-11-12
    • 1970-01-01
    • 2018-06-05
    相关资源
    最近更新 更多