Circular slider view in flutter

193 Views Asked by At

I need to create a circular volume slider view as below.Could anybody please suggest me how to do this?

I have checked out many packages on pub.dev but they doesn't seem to provide to make this customized view. enter image description here

I tried to make a widget as follows.it is working well.but I need to move that indicator with respect to the progress.now its moving but the angle is not correct.

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
   runApp(MaterialApp(home: CircularVolumeSlider()));
 }

class CircularVolumeSlider extends StatefulWidget {
  @override
  _CircularVolumeSliderState createState() => _CircularVolumeSliderState();
}

class _CircularVolumeSliderState extends State<CircularVolumeSlider> {
  double _sliderValue = 0.0; // Initial value (0-100)
  Offset _previousOffset = Offset(0, 0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            // Circular Slider
            GestureDetector(
                onPanUpdate: (DragUpdateDetails details) {
                  final currentOffset = details.localPosition;
                  final center = Offset(200, 200) / 2.0; // Use Offset

                  // Calculate the vector from the center to the current and previous points
                  final currentVector = currentOffset - center;
                  final previousVector = _previousOffset - center;

                  final distance = currentVector.distance;
                  if (distance <= 75) {
                    return;
                  }
                  // Calculate the angle between the vectors
                  final angle = atan2(currentVector.dy, currentVector.dx) -
                      atan2(previousVector.dy, previousVector.dx);

                  // Calculate the value based on the angle and adjust to the correct range
                  double newValue =
                      (_sliderValue + angle / (2 * pi) * 100.0) % 100.0;

                  if (newValue < 0) {
                    newValue += 100;
                  }

                  setState(() {
                    _sliderValue = newValue;
                  });

                  // Store the current offset for the next update
                  _previousOffset = currentOffset;
                },
                onPanStart: (details) {
                  _previousOffset = details.localPosition;
                },
                child: Container(
                  width: 230,
                  height: 230,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                  ),
                  child: Stack(
                    alignment: Alignment.center,
                    children: [
                      Container(
                        width: 200, // Set your desired size
                        height: 200,
                        decoration: const BoxDecoration(
                          color: Colors.yellow,
                          shape: BoxShape.circle,
                        ),
                        child: CircularProgressIndicator(
                          value: _sliderValue / 100,
                          strokeWidth: 12, // Customize the appearance
                        ),
                      ),
                      // Vertical Line Indicator
                      Positioned(
                          // Adjust the position
                          top: _previousOffset.dy,
                          left: _previousOffset.dx,
                          child: Transform.rotate(
                            angle: (_sliderValue / 100 * 2 * pi) ,
                            child: Container(
                                width: 10, // Set the line width
                                height: 30, // Set the line height

                                decoration: BoxDecoration(
                                    color: Colors.red,
                                    borderRadius: BorderRadius.circular(
                                        6)) // Customize the color
                                ),
                          )),
                    ],
                  ),
                )),
            const SizedBox(height: 30),
            // Indicator View (you can use GestureDetector for swiping)
            // Percentage Display
            Column(
              children: [
                const Text(
                  'Volume',
                  style: TextStyle(fontSize: 20),
                ),
                Text(
                  '$_sliderValue%',
                  style: TextStyle(fontSize: 24),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
0

There are 0 best solutions below