可容纳一个孩子,为后代的Slider指定默认样式。常用于Slider的样式统一,避免一一设置,也可以对Slider进行样式定制。

相关组件

Slider

SliderTheme使用

  1. <br />可通过SliderTheme.of获取Slider主题数据对象,其中包含大量属性用于对Slider的设定。"<br />可以为ButtonTheme【后代】的按钮组件设置默认样式,包括颜色、形状、尺寸等。<br />![215.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589512250988-3e231e99-733c-450f-82fe-9acb683cdd6f.gif#align=left&display=inline&height=102&margin=%5Bobject%20Object%5D&name=215.gif&originHeight=102&originWidth=384&size=216590&status=done&style=none&width=384)
  1. import 'dart:math';
  2. import 'package:flutter/material.dart';
  3. class SliderThemeDemo extends StatefulWidget {
  4. @override
  5. _SliderThemeDemoState createState() => _SliderThemeDemoState();
  6. }
  7. class _SliderThemeDemoState extends State<SliderThemeDemo> {
  8. var _bliss = 0.5;
  9. @override
  10. Widget build(BuildContext context) {
  11. return SliderTheme(
  12. data: SliderTheme.of(context).copyWith(activeTrackColor: Colors.orange),
  13. child: Slider(
  14. min: 0.0,
  15. max: 200.0,
  16. divisions: 10,
  17. label: "${_bliss.toStringAsFixed(1)}",
  18. onChanged: (double value) {
  19. setState(() {
  20. _bliss = value;
  21. });
  22. },
  23. value: _bliss,
  24. ),
  25. );
  26. }
  27. }

SliderTheme对Slider的样式定制

   <br />通过thumbShape和valueIndicatorShape可以对Slider进行样式定制。"<br />注: 本例参考flutter-gallery中的SlideDemo<br />![216.gif](https://cdn.nlark.com/yuque/0/2020/gif/326147/1589512285260-0976e7ce-6633-4a84-8974-e781055cbc0b.gif#align=left&display=inline&height=102&margin=%5Bobject%20Object%5D&name=216.gif&originHeight=102&originWidth=384&size=101385&status=done&style=none&width=384)
import 'dart:math';
import 'package:flutter/material.dart';
class DIYSliderTheme extends StatefulWidget {
  @override
  _DIYSliderThemeState createState() => _DIYSliderThemeState();
}

class _DIYSliderThemeState extends State<DIYSliderTheme> {
  var _bliss = 0.5;

  @override
  Widget build(BuildContext context) {
    final ThemeData theme = Theme.of(context);

    return SliderTheme(
      data: theme.sliderTheme.copyWith(
        activeTrackColor: Colors.deepPurple,
        inactiveTrackColor: Colors.blue.withAlpha(55),
        activeTickMarkColor: theme.colorScheme.onSurface.withOpacity(0.7),
        inactiveTickMarkColor: theme.colorScheme.surface.withOpacity(0.7),
        overlayColor: theme.colorScheme.onSurface.withOpacity(0.12),
        thumbColor: Colors.deepPurple,
        valueIndicatorColor: Colors.deepPurpleAccent,
        thumbShape: _CustomThumbShape(),
        valueIndicatorShape: _CustomValueIndicatorShape(),
        valueIndicatorTextStyle: theme.accentTextTheme.body2
            .copyWith(color: theme.colorScheme.onSurface),
      ),
      child: Slider(
        min: 0.0,
        max: 200.0,
        divisions: 10,
        label: "${_bliss.toStringAsFixed(1)}",
        onChanged: (double value) {
          setState(() {
            _bliss = value;
          });
        },
        value: _bliss,
      ),
    );
  }
}

class _CustomThumbShape extends SliderComponentShape {
  static const double _thumbSize = 4.0;
  static const double _disabledThumbSize = 3.0;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return isEnabled
        ? const Size.fromRadius(_thumbSize)
        : const Size.fromRadius(_disabledThumbSize);
  }

  static final Animatable<double> sizeTween = Tween<double>(
    begin: _disabledThumbSize,
    end: _thumbSize,
  );

  @override
  void paint(PaintingContext context, Offset center,
      {Animation<double> activationAnimation,
      Animation<double> enableAnimation,
      bool isDiscrete,
      TextPainter labelPainter,
      RenderBox parentBox,
      SliderThemeData sliderTheme,
      TextDirection textDirection,
      double value,
      double textScaleFactor,
      Size sizeWithOverflow}) {
    final Canvas canvas = context.canvas;
    final ColorTween colorTween = ColorTween(
      begin: sliderTheme.disabledThumbColor,
      end: sliderTheme.thumbColor,
    );
    final double size = _thumbSize * sizeTween.evaluate(enableAnimation);
    final Path thumbPath = _downTriangle(size, center);
    canvas.drawPath(
        thumbPath, Paint()..color = colorTween.evaluate(enableAnimation));
  }
}

Path _upTriangle(double size, Offset thumbCenter) =>
    _downTriangle(size, thumbCenter, invert: true);

Path _downTriangle(double size, Offset thumbCenter, {bool invert = false}) {
  final Path thumbPath = Path();
  final double height = sqrt(3.0) / 2.0;
  final double centerHeight = size * height / 3.0;
  final double halfSize = size / 2.0;
  final double sign = invert ? -1.0 : 1.0;
  thumbPath.moveTo(
      thumbCenter.dx - halfSize, thumbCenter.dy + sign * centerHeight);
  thumbPath.lineTo(thumbCenter.dx, thumbCenter.dy - 2.0 * sign * centerHeight);
  thumbPath.lineTo(
      thumbCenter.dx + halfSize, thumbCenter.dy + sign * centerHeight);
  thumbPath.close();
  return thumbPath;
}

class _CustomValueIndicatorShape extends SliderComponentShape {
  static const double _indicatorSize = 4.0;
  static const double _disabledIndicatorSize = 3.0;
  static const double _slideUpHeight = 30.0;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(isEnabled ? _indicatorSize : _disabledIndicatorSize);
  }

  static final Animatable<double> sizeTween = Tween<double>(
    begin: _disabledIndicatorSize,
    end: _indicatorSize,
  );

  @override
  void paint(PaintingContext context, Offset center,
      {Animation<double> activationAnimation,
      Animation<double> enableAnimation,
      bool isDiscrete,
      TextPainter labelPainter,
      RenderBox parentBox,
      SliderThemeData sliderTheme,
      TextDirection textDirection,
      double value,
      double textScaleFactor,
      Size sizeWithOverflow}) {
    final Canvas canvas = context.canvas;
    final ColorTween enableColor = ColorTween(
      begin: sliderTheme.disabledThumbColor,
      end: sliderTheme.valueIndicatorColor,
    );
    final Tween<double> slideUpTween = Tween<double>(
      begin: 0.0,
      end: _slideUpHeight,
    );
    final double size = _indicatorSize * sizeTween.evaluate(enableAnimation);
    final Offset slideUpOffset =
        Offset(0.0, -slideUpTween.evaluate(activationAnimation));
    final Path thumbPath = _upTriangle(size, center + slideUpOffset);
    final Color paintColor = enableColor
        .evaluate(enableAnimation)
        .withAlpha((255.0 * activationAnimation.value).round());
    canvas.drawPath(
      thumbPath,
      Paint()..color = paintColor,
    );
    canvas.drawLine(
        center,
        center + slideUpOffset,
        Paint()
          ..color = paintColor
          ..style = PaintingStyle.stroke
          ..strokeWidth = 2.0);
    labelPainter.paint(
        canvas,
        center +
            slideUpOffset +
            Offset(-labelPainter.width / 2.0, -labelPainter.height - 4.0));
  }
}