如何为 Flutter 中分区之间的滑块轨道段着色?

问题描述 投票:0回答:1

我对 Flutter 还很陌生,所以目前我无法理解如何自定义滑块轨道以通过分区之间的单独颜色为每个段着色,请帮助实现与下面的屏幕截图相同的设计。 custom slider

带有颜色的代码片段:

final List<Color> _divisionColors = [
  Color(0xff8DF5DE),
  Color(0xffA8F58C),
  Color(0xffFCEC74),
  Color(0xffFCD376),
  Color(0xffFDB272),
  Color(0xffE27E5A),
];
flutter colors slider division
1个回答
0
投票

我知道这个答案已经很晚了。我希望这对其他人有帮助。

import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gradient_slider/src/image_thumb_shape.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: ColoredSlider(),
        ),
      ),
    );
  }
}

class ColoredSlider extends StatefulWidget {
  @override
  _ColoredSliderState createState() => _ColoredSliderState();
}

class _ColoredSliderState extends State<ColoredSlider> {
  double _value = 3;
  ImageThumbShape? myShape;

  @override
  void initState() {
    super.initState();
    _loadImage();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 55,
      width: 340,
      child: SliderTheme(
        data: SliderThemeData(
          thumbShape: myShape,
          overlayShape: const RoundSliderOverlayShape(overlayRadius: 10),
          trackHeight: 16, // Adjust the track height
          trackShape: CustomTrackShape(), // Set the custom track shape
        ),
        child: Slider(
          value: _value,
          min: 1,
          max: 5,
          onChanged: (newValue) {
            setState(() {
              _value = newValue;
            });
          },
        ),
      ),
    );
  }

  _loadImage() async {
    ByteData byData = await rootBundle.load('assets/Triangle.png');
    final Uint8List bytes = Uint8List.view(byData.buffer);
    final ui.Codec codec = await ui.instantiateImageCodec(bytes, targetWidth: 30, targetHeight: 30);
    ui.Image image = (await codec.getNextFrame()).image;
    myShape = ImageThumbShape(image: image);
    setState(() {});
  }
}

class CustomTrackShape extends SliderTrackShape {
  @override
  Rect getPreferredRect({
    required RenderBox parentBox,
    Offset? offset = Offset.zero,
    required SliderThemeData sliderTheme,
    bool? isEnabled,
    bool? isDiscrete,
  }) {
    return Rect.fromLTWH(
      offset!.dx,
      offset.dy + (parentBox.size.height - sliderTheme.trackHeight!) / 2,
      parentBox.size.width,
      sliderTheme.trackHeight!,
    );
  }

  @override
  void paint(
    PaintingContext context,
    Offset offset, {
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    Animation<double>? enableAnimation,
    Offset? thumbCenter,
    bool? isEnabled,
    bool? isDiscrete,
    TextDirection? textDirection,
    Offset? secondaryOffset,
  }) {
    if (sliderTheme.trackHeight == null || sliderTheme.trackHeight! <= 0) {
      return;
    }

    final Rect trackRect = getPreferredRect(
      parentBox: parentBox,
      offset: offset,
      sliderTheme: sliderTheme,
      isEnabled: isEnabled,
      isDiscrete: isDiscrete,
    );

    final Paint paint = Paint();
    final sliderDivisions = 5; // Your slider division

    // Calculate the segment width
    final double segmentWidth = trackRect.width / sliderDivisions;

    // Paint colored segments between divisions
    for (int index = 0; index < sliderDivisions; index++) {
      final double startX = trackRect.left + (index * segmentWidth);
      final double endX = trackRect.left + ((index + 1) * segmentWidth);

      final Rect segmentRect = Rect.fromLTRB(startX, trackRect.top, endX, trackRect.bottom);

      // Set different colors for segments
      if (index == 0) {
        paint.color = Color(0xffF4D11D);
      } else if (index == 1) {
        paint.color = Color(0xffD1D231);
      } else if (index == 2) {
        paint.color = Color(0xffB3D342);
      } else if (index == 3) {
        paint.color = Color(0xff9CD450);
      } else if (index == 4) {
        paint.color = Color(0xff83D55E);
      } else if (index == 5) {
        paint.color = Color(0xffF4D11D);
      } else if (index == 6) {
        paint.color = Colors.green;
      }
      // Draw rounded rectangle
      context.canvas.drawRRect(
        RRect.fromRectAndCorners(
          segmentRect,
          topLeft: index == 0 ? Radius.circular(sliderTheme.trackHeight! / 2) : Radius.zero,
          topRight: (index == 5 - 1) ? Radius.circular(sliderTheme.trackHeight! / 2) : Radius.zero,
          bottomLeft: index == 0 ? Radius.circular(sliderTheme.trackHeight! / 2) : Radius.zero,
          bottomRight: (index == 5 - 1) ? Radius.circular(sliderTheme.trackHeight! / 2) : Radius.zero,
        ),
        paint,
      );

      // Draw vertical white line
      if (index < sliderDivisions - 1) {
        final double lineX = startX + segmentWidth;
        context.canvas.drawLine(
          Offset(lineX, trackRect.top),
          Offset(lineX, trackRect.bottom),
          Paint()
            ..color = Colors.white
            ..strokeWidth = 2.0, // Line Width
        );
      }
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.