process_bar_with_sine 1.2.1 copy "process_bar_with_sine: ^1.2.1" to clipboard
process_bar_with_sine: ^1.2.1 copied to clipboard

An enhanced Flutter progress bar, featuring dynamic sine-wave animations.

example/lib/main.dart

import 'dart:async';

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

void main() => runApp(const DemoApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ProgressBar 增强功能演示',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: Colors.blue,
        brightness: Brightness.dark,
        useMaterial3: true,
      ),
      home: const DemoPage(),
    );
  }
}

class DemoPage extends StatefulWidget {
  const DemoPage({super.key});

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  static const _totalDuration = Duration(seconds: 30);

  Timer? _timer;
  Duration _progress = Duration.zero;
  bool _isPlaying = false;

  ThumbShape _thumbShape = ThumbShape.circle;
  double _barBorderRadius = 0;
  double _thumbGap = 0;
  double _thumbBarGap = 0;
  bool _enableSineWave = false;
  double _amplitude = 3.0;
  double _cycleCount = 2.0;
  double _speed = 1.0;
  int _waveCount = 1;
  bool _clampToBarBounds = false;
  double _lineThumbWidth = 4.0;
  double _lineThumbHeight = 14.0;
  double _lineThumbBorderRadius = 2.0;
  TimeLabelLocation _timeLabelLocation = TimeLabelLocation.below;

  @override
  void dispose() {
    _timer?.cancel();
    super.dispose();
  }

  void _togglePlay() {
    if (_isPlaying) {
      _timer?.cancel();
    } else {
      _timer = Timer.periodic(const Duration(milliseconds: 200), (_) {
        setState(() {
          _progress += const Duration(milliseconds: 200);
          if (_progress >= _totalDuration) {
            _progress = Duration.zero;
          }
        });
      });
    }
    setState(() => _isPlaying = !_isPlaying);
  }

  void _seek(Duration position) {
    setState(() => _progress = position);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar:
          AppBar(title: const Text('ProgressBar 增强功能演示'), centerTitle: true),
      body: ListView(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
        children: [
          // ---- 进度条展示区 ----
          Card(
            child: Padding(
              padding:
                  const EdgeInsets.symmetric(horizontal: 20, vertical: 24),
              child: Column(
                children: [
                  ProgressBar(
                    progress: _progress,
                    total: _totalDuration,
                    buffered: _isPlaying
                        ? _progress + const Duration(seconds: 8)
                        : null,
                    thumbShape: _thumbShape,
                    lineThumbWidth: _lineThumbWidth,
                    lineThumbHeight: _lineThumbHeight,
                    lineThumbBorderRadius: _lineThumbBorderRadius,
                    barBorderRadius:
                        _barBorderRadius > 0 ? _barBorderRadius : null,
                    thumbGap: _thumbGap,
                    thumbBarGap: _thumbBarGap,
                    sineWaveConfig:
                        _enableSineWave ? _buildSineConfig() : null,
                    timeLabelLocation: _timeLabelLocation,
                    onSeek: _seek,
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      IconButton(
                        icon: Icon(
                            _isPlaying ? Icons.pause : Icons.play_arrow),
                        onPressed: _togglePlay,
                      ),
                      IconButton(
                        icon: const Icon(Icons.replay),
                        onPressed: () =>
                            setState(() => _progress = Duration.zero),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),

          const SizedBox(height: 8),

          // ---- 滑块形状 ----
          _buildSection('滑块形状 (thumbShape)'),
          SegmentedButton<ThumbShape>(
            segments: const [
              ButtonSegment(value: ThumbShape.circle, label: Text('circle')),
              ButtonSegment(value: ThumbShape.line, label: Text('line')),
            ],
            selected: {_thumbShape},
            onSelectionChanged: (v) => setState(() => _thumbShape = v.first),
          ),

          if (_thumbShape == ThumbShape.line) ...[
            _buildSection('线宽 (lineThumbWidth): ${_lineThumbWidth.toStringAsFixed(1)}'),
            Slider(
              value: _lineThumbWidth,
              min: 2,
              max: 12,
              onChanged: (v) => setState(() => _lineThumbWidth = v),
            ),
            _buildSection('线高 (lineThumbHeight): ${_lineThumbHeight.toStringAsFixed(1)}'),
            Slider(
              value: _lineThumbHeight,
              min: 6,
              max: 32,
              onChanged: (v) => setState(() => _lineThumbHeight = v),
            ),
            _buildSection('圆角 (lineThumbBorderRadius): ${_lineThumbBorderRadius.toStringAsFixed(1)}'),
            Slider(
              value: _lineThumbBorderRadius,
              min: 0,
              max: 6,
              onChanged: (v) => setState(() => _lineThumbBorderRadius = v),
            ),
          ],

          // ---- 时间标签位置 ----
          _buildSection('时间标签位置 (timeLabelLocation)'),
          SegmentedButton<TimeLabelLocation>(
            segments: const [
              ButtonSegment(
                  value: TimeLabelLocation.below, label: Text('below')),
              ButtonSegment(
                  value: TimeLabelLocation.above, label: Text('above')),
              ButtonSegment(
                  value: TimeLabelLocation.sides, label: Text('sides')),
              ButtonSegment(
                  value: TimeLabelLocation.none, label: Text('none')),
            ],
            selected: {_timeLabelLocation},
            onSelectionChanged: (v) =>
                setState(() => _timeLabelLocation = v.first),
          ),

          // ---- 圆角半径 ----
          _buildSection(
              '进度条圆角 (barBorderRadius): ${_barBorderRadius.toStringAsFixed(1)}'),
          Slider(
            value: _barBorderRadius,
            min: 0,
            max: 16,
            onChanged: (v) => setState(() => _barBorderRadius = v),
          ),

          // ---- 滑块间隙 ----
          _buildSection('滑块分段间隙 (thumbGap): ${_thumbGap.toStringAsFixed(1)}'),
          Slider(
            value: _thumbGap,
            min: 0,
            max: 16,
            onChanged: (v) => setState(() => _thumbGap = v),
          ),

          _buildSection(
              '滑块端点间隙 (thumbBarGap): ${_thumbBarGap.toStringAsFixed(1)}'),
          Slider(
            value: _thumbBarGap,
            min: -4,
            max: 12,
            onChanged: (v) => setState(() => _thumbBarGap = v),
          ),

          // ---- 正弦波浪 ----
          SwitchListTile(
            title: const Text('启用正弦波浪 (sineWaveConfig)'),
            value: _enableSineWave,
            onChanged: (v) => setState(() => _enableSineWave = v),
          ),

          if (_enableSineWave) ...[
            _buildSection('振幅 (amplitude): ${_amplitude.toStringAsFixed(1)}'),
            Slider(
              value: _amplitude,
              min: 1,
              max: 8,
              onChanged: (v) => setState(() => _amplitude = v),
            ),
            _buildSection('周期数 (cycleCount): ${_cycleCount.toStringAsFixed(1)}'),
            Slider(
              value: _cycleCount,
              min: 0.5,
              max: 6,
              onChanged: (v) => setState(() => _cycleCount = v),
            ),
            _buildSection('速度 (speed): ${_speed.toStringAsFixed(1)}'),
            Slider(
              value: _speed,
              min: 0.2,
              max: 3,
              onChanged: (v) => setState(() => _speed = v),
            ),
            _buildSection('叠加层数 (waveCount): $_waveCount'),
            Slider(
              value: _waveCount.toDouble(),
              min: 1,
              max: 4,
              divisions: 3,
              onChanged: (v) => setState(() => _waveCount = v.round()),
            ),
            SwitchListTile(
              title: const Text('裁剪到边界 (clampToBarBounds)'),
              value: _clampToBarBounds,
              onChanged: (v) => setState(() => _clampToBarBounds = v),
            ),
          ],

          const SizedBox(height: 32),
        ],
      ),
    );
  }

  SineWaveConfig _buildSineConfig() {
    return SineWaveConfig(
      amplitude: _amplitude,
      cycleCount: _cycleCount,
      speed: _speed,
      waveCount: _waveCount,
      clampToBarBounds: _clampToBarBounds,
    );
  }

  Widget _buildSection(String title) {
    return Padding(
      padding: const EdgeInsets.only(top: 12, bottom: 4),
      child: Text(title, style: const TextStyle(fontWeight: FontWeight.w600)),
    );
  }
}
1
likes
0
points
22
downloads

Publisher

unverified uploader

Weekly Downloads

An enhanced Flutter progress bar, featuring dynamic sine-wave animations.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on process_bar_with_sine