android 如何在syncfusion滑块Flutter中实现这一点?

kr98yfug  于 2023-04-28  发布在  Android
关注(0)|答案(2)|浏览(177)

这是我从Syncfusion的文档中得到的图片。
同步滑块

这是我想要实现的,一个滑块轨道,其中有活动的颜色,非活动的颜色,和一个禁用的颜色。禁用的颜色将应用于用户的值之间的最大值。
比如说,我输入值80,因此红色将在80 - 100之间应用。
我已经尝试限制onChanged属性不超过用户的给定值。即80。我只需要颜色是不同的用户之间的价值-最大值。

lmvvr0a8

lmvvr0a81#

你可以这样试试

double _values = 80;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SfSlider(
        min: 0.0,
        max: 100.0,
    stepSize: 1,
    value: _values,
    inactiveColor: Colors.red.shade200,
    activeColor: Colors.green,
    interval: 20,
    showTicks: true,
    showLabels: true,
    enableTooltip: true,
    minorTicksPerInterval: 1,
    onChanged: (value) {
      setState(() {
        _values = value;
      });
    },
  ),
);
}
yzuktlbb

yzuktlbb2#

我们使用Slider中的trackShapethumShape属性实现了您的要求。我们扩展了SfTrackShapeSfThumbShape类,并根据paint方法中的滑块值自定义了轨迹和拇指颜色。然后我们将这些类分配给trackShapethumShape属性。我们在下面分享了完整的代码片段供您参考。
代码片段:

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_sliders/sliders.dart';
import 'package:syncfusion_flutter_core/theme.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ShapeCustomizedSliderPage(Key('slider')),
    );
  }
}

///Renders slider with customized shapes
class ShapeCustomizedSliderPage extends StatefulWidget {
  ///Renders slider with customized shapes
  const ShapeCustomizedSliderPage(Key key) : super(key: key);

  @override
  ShapeCustomizedSliderPageState createState() =>
      ShapeCustomizedSliderPageState();
}

class ShapeCustomizedSliderPageState extends State<ShapeCustomizedSliderPage> {
  ShapeCustomizedSliderPageState();
  final double _min = 0.0;
  final double _max = 100.0;
  double _value = 60.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) {
        final double padding = MediaQuery.of(context).size.width / 20.0;
        return Container(
          padding: EdgeInsets.fromLTRB(padding, 0, padding, 0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              SfSliderTheme(
                data: SfSliderThemeData(
                  brightness: Brightness.light,
                ),
                child: SfSlider(
                  min: _min,
                  max: _max,
                  value: _value,
                  interval: 20.0,
                  showLabels: true,
                  showTicks: true,
                  trackShape: _SfTrackShape(_min, _max),
                  thumbShape: _SfThumbShape(_min, _max),
                  onChanged: (dynamic value) {
                    setState(() {
                      _value = value as double;
                    });
                  },
                ),
              ),
            ],
          ),
        );
      }),
    );
  }
}

class _SfTrackShape extends SfTrackShape {
  _SfTrackShape(dynamic min, dynamic max) {
    this.min = (min.runtimeType == DateTime
        ? min.millisecondsSinceEpoch.toDouble()
        : min) as double;
    this.max = (max.runtimeType == DateTime
        ? max.millisecondsSinceEpoch.toDouble()
        : max) as double;
  }

  late double min;
  late double max;
  double? trackIntermediatePos;

  @override
  void paint(PaintingContext context, Offset offset, Offset? thumbCenter,
      Offset? startThumbCenter, Offset? endThumbCenter,
      {required RenderBox parentBox,
      required SfSliderThemeData themeData,
      SfRangeValues? currentValues,
      dynamic currentValue,
      required Animation<double> enableAnimation,
      required Paint? inactivePaint,
      required Paint? activePaint,
      required TextDirection textDirection}) {
    final Rect trackRect = getPreferredRect(parentBox, themeData, offset);
    final double actualValue = (currentValue.runtimeType == DateTime
        ? currentValue.millisecondsSinceEpoch.toDouble()
        : currentValue) as double;
    final double actualValueInPercent =
        ((actualValue - min) * 100) / (max - min);
    trackIntermediatePos = _getTrackIntermediatePosition(trackRect);

    // low volume track.
    final Paint trackPaint = Paint();
    trackPaint.color = actualValueInPercent <= 80.0 ? Colors.green : Colors.red;
    final Rect lowVolumeRect = Rect.fromLTRB(
        trackRect.left, trackRect.top, thumbCenter!.dx, trackRect.bottom);
    context.canvas.drawRect(lowVolumeRect, trackPaint);

    if (actualValueInPercent <= 80.0) {
      trackPaint.color = Colors.green.withOpacity(0.40);
      final Rect lowVolumeRectWithLessOpacity = Rect.fromLTRB(thumbCenter.dx,
          trackRect.top, trackIntermediatePos!, trackRect.bottom);
      context.canvas.drawRect(lowVolumeRectWithLessOpacity, trackPaint);
    }

    trackPaint.color = Colors.red.withOpacity(0.40);
    final double highTrackLeft =
        actualValueInPercent >= 80.0 ? thumbCenter.dx : trackIntermediatePos!;
    final Rect highVolumeRectWithLessOpacity = Rect.fromLTRB(highTrackLeft,
        trackRect.top, trackRect.width + trackRect.left, trackRect.bottom);
    context.canvas.drawRect(highVolumeRectWithLessOpacity, trackPaint);
  }

  double _getTrackIntermediatePosition(Rect trackRect) {
    final double actualValue = ((80 * (max - min)) + min) / 100;
    return (((actualValue - min) / (max - min)) * trackRect.width) +
        trackRect.left;
  }
}

class _SfThumbShape extends SfThumbShape {
  _SfThumbShape(dynamic min, dynamic max) {
    this.min = (min.runtimeType == DateTime
        ? min.millisecondsSinceEpoch.toDouble()
        : min) as double;
    this.max = (max.runtimeType == DateTime
        ? max.millisecondsSinceEpoch.toDouble()
        : max) as double;
  }

  late double min;
  late double max;

  @override
  void paint(PaintingContext context, Offset center,
      {required RenderBox parentBox,
      required RenderBox? child,
      required SfSliderThemeData themeData,
      SfRangeValues? currentValues,
      dynamic currentValue,
      required Paint? paint,
      required Animation<double> enableAnimation,
      required TextDirection textDirection,
      required SfThumb? thumb}) {
    final double actualValue = (currentValue.runtimeType == DateTime
        ? currentValue.millisecondsSinceEpoch.toDouble()
        : currentValue) as double;

    final double actualValueInPercent =
        ((actualValue - min) * 100) / (max - min);

    paint = Paint();
    paint.color = actualValueInPercent <= 80 ? Colors.green : Colors.red;

    super.paint(context, center,
        parentBox: parentBox,
        themeData: themeData,
        currentValue: currentValue,
        paint: paint,
        enableAnimation: enableAnimation,
        textDirection: textDirection,
        thumb: thumb,
        child: child);
  }
}

截图:

实时示例,https://flutter.syncfusion.com/#/slider/customization/shape-customization

相关问题