[Flutter]Sliderのつまみに枠線をつけるには?

Flutter

どうも、ちょげ(@chogetarou)です。

Sliderの操作する部分であるつまみに枠線をつける方法を紹介します。

スポンサーリンク

方法

インターフェース, インターネット, プログラム, ブラウザ, Www

Sliderのつまみに枠線をつけるには、SliderComponentShapeのカスタムクラスを使います。

まず、SliderComponentShapeのクラスを作ります。(テンプレみたいなものです)

class CircleThumbShape extends SliderComponentShape {
  final double thumbRadius;

  const CircleThumbShape({
    this.thumbRadius = 10.0, //サイズ
  });

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(thumbRadius);
  }

  @override
  void paint(PaintingContext context, Offset center,
      {required Animation<double> activationAnimation,
      required Animation<double> enableAnimation,
      required bool isDiscrete,
      required TextPainter labelPainter,
      required RenderBox parentBox,
      required SliderThemeData sliderTheme,
      required TextDirection textDirection,
      required double value,
      required double textScaleFactor,
      required Size sizeWithOverflow}) {
    //つまみの描画
  }
}

次に、通常のつまみ用と枠線用のPaintクラスを用意します。

class CircleThumbShape extends SliderComponentShape {
  final double thumbRadius;

  const CircleThumbShape({
    this.thumbRadius = 10.0,
  });

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(thumbRadius);
  }

  @override
  void paint(PaintingContext context, Offset center,
      {required Animation<double> activationAnimation,
      required Animation<double> enableAnimation,
      required bool isDiscrete,
      required TextPainter labelPainter,
      required RenderBox parentBox,
      required SliderThemeData sliderTheme,
      required TextDirection textDirection,
      required double value,
      required double textScaleFactor,
      required Size sizeWithOverflow}) {

    final Canvas canvas = context.canvas;
   
    //通常のつまみ用
    final fillPaint = Paint()
      ..color = sliderTheme.thumbColor! //つまみの色
      ..style = PaintingStyle.fill;
     
    //枠線用
    final borderPaint = Paint()
      ..color = Colors.pink //枠線の色
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2; //枠線の太さ
  }
}

そして、用意したPaintクラスを描画します。

class CircleThumbShape extends SliderComponentShape {
  final double thumbRadius;

  const CircleThumbShape({
    this.thumbRadius = 10.0,
  });

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(thumbRadius);
  }

  @override
  void paint(PaintingContext context, Offset center,
      {required Animation<double> activationAnimation,
      required Animation<double> enableAnimation,
      required bool isDiscrete,
      required TextPainter labelPainter,
      required RenderBox parentBox,
      required SliderThemeData sliderTheme,
      required TextDirection textDirection,
      required double value,
      required double textScaleFactor,
      required Size sizeWithOverflow}) {

    final Canvas canvas = context.canvas;

    final fillPaint = Paint()
      ..color = sliderTheme.thumbColor!
      ..style = PaintingStyle.fill;
    final borderPaint = Paint()
      ..color = Colors.pink
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;

    canvas.drawCircle(center, thumbRadius, fillPaint); //通常のつまみの描画
    canvas.drawCircle(center, thumbRadius, borderPaint); //枠線の描画
  }
}

最後に、SliderThemeDataの引数「thumbShape」に用意したクラスを指定します。

SliderTheme(
  data: SliderThemeData(
    thumbShape: CircleThumbShape(),
  ),
  child: Slider(
    value: _value,
    onChanged: (newValue) {
      setState(() {
        _value = newValue;
      });
    },
  ),
),

SliderComponentShapeを使うことで、Sliderのつまみに枠線をつけることが出来ます。

使用例

以下は、使用例です。

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  double _value = 0.5;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Center(
          child: SliderTheme(
            data: SliderThemeData(
              thumbShape: CircleThumbShape(),
            ),
            child: Slider(
              value: _value,
              onChanged: (newValue) {
                setState(() {
                  _value = newValue;
                });
              },
            ),
          ),
        ),
      ),
    );
  }
}

class CircleThumbShape extends SliderComponentShape {
  final double thumbRadius;

  const CircleThumbShape({
    this.thumbRadius = 10.0,
  });

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(thumbRadius);
  }

  @override
  void paint(PaintingContext context, Offset center,
      {required Animation<double> activationAnimation,
      required Animation<double> enableAnimation,
      required bool isDiscrete,
      required TextPainter labelPainter,
      required RenderBox parentBox,
      required SliderThemeData sliderTheme,
      required TextDirection textDirection,
      required double value,
      required double textScaleFactor,
      required Size sizeWithOverflow}) {

    final Canvas canvas = context.canvas;

    final fillPaint = Paint()
      ..color = sliderTheme.thumbColor!
      ..style = PaintingStyle.fill;

    final borderPaint = Paint()
      ..color = Colors.pink
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;

    canvas.drawCircle(center, thumbRadius, fillPaint);
    canvas.drawCircle(center, thumbRadius, borderPaint);
  }
}

コメント

タイトルとURLをコピーしました