You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			190 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Dart
		
	
		
		
			
		
	
	
			190 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Dart
		
	
| 
								 
											3 years ago
										 
									 | 
							
								import 'dart:math';
							 | 
						||
| 
								 | 
							
								import 'package:audio_waveforms/audio_waveforms.dart';
							 | 
						||
| 
								 | 
							
								import 'package:flutter/material.dart';
							 | 
						||
| 
								 | 
							
								import 'package:mohem_flutter_app/classes/colors.dart';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SeekBar extends StatefulWidget {
							 | 
						||
| 
								 | 
							
								  final Duration duration;
							 | 
						||
| 
								 | 
							
								  final Duration position;
							 | 
						||
| 
								 | 
							
								  final Duration bufferedPosition;
							 | 
						||
| 
								 | 
							
								  final ValueChanged<Duration>? onChanged;
							 | 
						||
| 
								 | 
							
								  final ValueChanged<Duration>? onChangeEnd;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const SeekBar({
							 | 
						||
| 
								 | 
							
								    Key? key,
							 | 
						||
| 
								 | 
							
								    required this.duration,
							 | 
						||
| 
								 | 
							
								    required this.position,
							 | 
						||
| 
								 | 
							
								    required this.bufferedPosition,
							 | 
						||
| 
								 | 
							
								    this.onChanged,
							 | 
						||
| 
								 | 
							
								    this.onChangeEnd,
							 | 
						||
| 
								 | 
							
								  }) : super(key: key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  SeekBarState createState() => SeekBarState();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class SeekBarState extends State<SeekBar> {
							 | 
						||
| 
								 | 
							
								  double? _dragValue;
							 | 
						||
| 
								 | 
							
								  late SliderThemeData _sliderThemeData;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  void didChangeDependencies() {
							 | 
						||
| 
								 | 
							
								    super.didChangeDependencies();
							 | 
						||
| 
								 | 
							
								    _sliderThemeData = SliderTheme.of(context).copyWith(
							 | 
						||
| 
								 | 
							
								      // trackHeight: 2.0,
							 | 
						||
| 
								 | 
							
								      thumbColor: MyColors.lightGreenColor,
							 | 
						||
| 
								 | 
							
								      activeTrackColor: MyColors.lightGreenColor,
							 | 
						||
| 
								 | 
							
								      inactiveTrackColor: MyColors.grey57Color.withOpacity(0.4),
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Widget build(BuildContext context) {
							 | 
						||
| 
								 | 
							
								    return Stack(
							 | 
						||
| 
								 | 
							
								      children: [
							 | 
						||
| 
								 | 
							
								        SliderTheme(
							 | 
						||
| 
								 | 
							
								          data: _sliderThemeData.copyWith(
							 | 
						||
| 
								 | 
							
								            thumbShape: HiddenThumbComponentShape(),
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								          child: ExcludeSemantics(
							 | 
						||
| 
								 | 
							
								            child: Slider(
							 | 
						||
| 
								 | 
							
								              min: 0.0,
							 | 
						||
| 
								 | 
							
								              max: widget.duration.inMilliseconds.toDouble(),
							 | 
						||
| 
								 | 
							
								              value: min(widget.bufferedPosition.inMilliseconds.toDouble(), widget.duration.inMilliseconds.toDouble()),
							 | 
						||
| 
								 | 
							
								              onChanged: (value) {
							 | 
						||
| 
								 | 
							
								                setState(() {
							 | 
						||
| 
								 | 
							
								                  _dragValue = value;
							 | 
						||
| 
								 | 
							
								                });
							 | 
						||
| 
								 | 
							
								                if (widget.onChanged != null) {
							 | 
						||
| 
								 | 
							
								                  widget.onChanged!(Duration(milliseconds: value.round()));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              },
							 | 
						||
| 
								 | 
							
								              onChangeEnd: (value) {
							 | 
						||
| 
								 | 
							
								                if (widget.onChangeEnd != null) {
							 | 
						||
| 
								 | 
							
								                  widget.onChangeEnd!(Duration(milliseconds: value.round()));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                _dragValue = null;
							 | 
						||
| 
								 | 
							
								              },
							 | 
						||
| 
								 | 
							
								            ),
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								        ),
							 | 
						||
| 
								 | 
							
								        SliderTheme(
							 | 
						||
| 
								 | 
							
								          data: _sliderThemeData.copyWith(
							 | 
						||
| 
								 | 
							
								            inactiveTrackColor: Colors.transparent,
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								          child: Slider(
							 | 
						||
| 
								 | 
							
								            min: 0.0,
							 | 
						||
| 
								 | 
							
								            max: widget.duration.inMilliseconds.toDouble(),
							 | 
						||
| 
								 | 
							
								            value: min(_dragValue ?? widget.position.inMilliseconds.toDouble(), widget.duration.inMilliseconds.toDouble()),
							 | 
						||
| 
								 | 
							
								            onChanged: (value) {
							 | 
						||
| 
								 | 
							
								              setState(() {
							 | 
						||
| 
								 | 
							
								                _dragValue = value;
							 | 
						||
| 
								 | 
							
								              });
							 | 
						||
| 
								 | 
							
								              if (widget.onChanged != null) {
							 | 
						||
| 
								 | 
							
								                widget.onChanged!(Duration(milliseconds: value.round()));
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								            onChangeEnd: (value) {
							 | 
						||
| 
								 | 
							
								              if (widget.onChangeEnd != null) {
							 | 
						||
| 
								 | 
							
								                widget.onChangeEnd!(Duration(milliseconds: value.round()));
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								              _dragValue = null;
							 | 
						||
| 
								 | 
							
								            },
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								        ),
							 | 
						||
| 
								 | 
							
								      ],
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class PositionData {
							 | 
						||
| 
								 | 
							
								  final Duration position;
							 | 
						||
| 
								 | 
							
								  final Duration bufferedPosition;
							 | 
						||
| 
								 | 
							
								  final Duration duration;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  PositionData(this.position, this.bufferedPosition, this.duration);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class HiddenThumbComponentShape extends SliderComponentShape {
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Size getPreferredSize(bool isEnabled, bool isDiscrete) => Size.zero;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @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,
							 | 
						||
| 
								 | 
							
								  }) {}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class WaveBubble extends StatelessWidget {
							 | 
						||
| 
								 | 
							
								  final PlayerController playerController;
							 | 
						||
| 
								 | 
							
								  final VoidCallback onTap;
							 | 
						||
| 
								 | 
							
								  final bool isPlaying;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const WaveBubble({
							 | 
						||
| 
								 | 
							
								    Key? key,
							 | 
						||
| 
								 | 
							
								    required this.playerController,
							 | 
						||
| 
								 | 
							
								    required this.onTap,
							 | 
						||
| 
								 | 
							
								    required this.isPlaying,
							 | 
						||
| 
								 | 
							
								  }) : super(key: key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  @override
							 | 
						||
| 
								 | 
							
								  Widget build(BuildContext context) {
							 | 
						||
| 
								 | 
							
								    return Container(
							 | 
						||
| 
								 | 
							
								      margin: const EdgeInsets.all(10),
							 | 
						||
| 
								 | 
							
								      decoration: BoxDecoration(
							 | 
						||
| 
								 | 
							
								        borderRadius: BorderRadius.circular(30),
							 | 
						||
| 
								 | 
							
								        gradient: const LinearGradient(
							 | 
						||
| 
								 | 
							
								          transform: GradientRotation(.83),
							 | 
						||
| 
								 | 
							
								          begin: Alignment.topRight,
							 | 
						||
| 
								 | 
							
								          end: Alignment.bottomLeft,
							 | 
						||
| 
								 | 
							
								          colors: <Color>[
							 | 
						||
| 
								 | 
							
								            MyColors.gradiantEndColor,
							 | 
						||
| 
								 | 
							
								            MyColors.gradiantStartColor,
							 | 
						||
| 
								 | 
							
								          ],
							 | 
						||
| 
								 | 
							
								        ),
							 | 
						||
| 
								 | 
							
								      ),
							 | 
						||
| 
								 | 
							
								      child: Row(
							 | 
						||
| 
								 | 
							
								        mainAxisSize: MainAxisSize.min,
							 | 
						||
| 
								 | 
							
								        children: [
							 | 
						||
| 
								 | 
							
								          IconButton(
							 | 
						||
| 
								 | 
							
								            onPressed: onTap,
							 | 
						||
| 
								 | 
							
								            icon: Icon(isPlaying ? Icons.stop : Icons.play_arrow),
							 | 
						||
| 
								 | 
							
								            color: Colors.white,
							 | 
						||
| 
								 | 
							
								            splashColor: Colors.transparent,
							 | 
						||
| 
								 | 
							
								            highlightColor: Colors.transparent,
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								          AudioFileWaveforms(
							 | 
						||
| 
								 | 
							
								            size: Size(MediaQuery.of(context).size.width / 2, 10),
							 | 
						||
| 
								 | 
							
								            playerController: playerController,
							 | 
						||
| 
								 | 
							
								            padding: EdgeInsets.zero,
							 | 
						||
| 
								 | 
							
								            margin: EdgeInsets.zero,
							 | 
						||
| 
								 | 
							
								            enableSeekGesture: true,
							 | 
						||
| 
								 | 
							
								            density: 1,
							 | 
						||
| 
								 | 
							
								            playerWaveStyle: const PlayerWaveStyle(
							 | 
						||
| 
								 | 
							
								              fixedWaveColor: Colors.white,
							 | 
						||
| 
								 | 
							
								              liveWaveColor: MyColors.greenColor,
							 | 
						||
| 
								 | 
							
								              showTop: true,
							 | 
						||
| 
								 | 
							
								              showBottom: true,
							 | 
						||
| 
								 | 
							
								              waveCap: StrokeCap.round,
							 | 
						||
| 
								 | 
							
								              seekLineThickness: 2,
							 | 
						||
| 
								 | 
							
								              visualizerHeight: 4,
							 | 
						||
| 
								 | 
							
								              backgroundColor: Colors.transparent,
							 | 
						||
| 
								 | 
							
								            ),
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								        ],
							 | 
						||
| 
								 | 
							
								      ),
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |