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.

245 lines
7.2 KiB
Dart

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

//MIT License
//
//Copyright (c) [2019] [Befovy]
//
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
//part of fijkplayer;
import 'package:flutter/material.dart';
import 'dart:core';
import 'dart:math';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
/// MyFijkSlider is like Slider in Flutter SDK.
/// MyFijkSlider support [cacheValue] which can be used
/// to show the player's cached buffer.
/// The [colors] is used to make colorful painter to draw the line and circle.
class MyFijkSlider extends StatefulWidget {
final double value;
final double cacheValue;
final ValueChanged<double> onChanged;
final ValueChanged<double> onChangeStart;
final ValueChanged<double> onChangeEnd;
final double min;
final double max;
final MyFijkSliderColors colors;
const MyFijkSlider({
Key key,
@required this.value,
@required this.onChanged,
this.cacheValue = 0.0,
this.onChangeStart,
this.onChangeEnd,
this.min = 0.0,
this.max = 1.0,
this.colors = const MyFijkSliderColors(),
}) : assert(value != null),
assert(cacheValue != null),
assert(min != null),
assert(max != null),
assert(min <= max),
assert(value >= min && value <= max),
super(key: key);
@override
State<StatefulWidget> createState() {
return _MyFijkSliderState();
}
}
class _MyFijkSliderState extends State<MyFijkSlider> {
bool dragging = false;
double dragValue;
static const double margin = 2.0;
@override
Widget build(BuildContext context) {
double v = widget.value / (widget.max - widget.min);
double cv = widget.cacheValue / (widget.max - widget.min);
return GestureDetector(
child: Container(
margin: EdgeInsets.only(left: margin, right: margin),
height: double.infinity,
width: double.infinity,
color: Colors.transparent,
child: CustomPaint(
painter: _MySliderPainter(v, cv, dragging, colors: widget.colors),
),
),
onHorizontalDragStart: (DragStartDetails details) {
setState(() {
dragging = true;
});
dragValue = widget.value;
if (widget.onChangeStart != null) {
widget.onChangeStart(dragValue);
}
},
onHorizontalDragUpdate: (DragUpdateDetails details) {
final box = context.findRenderObject() as RenderBox;
final dx = details.localPosition.dx;
dragValue = (dx - margin) / (box.size.width - 2 * margin);
dragValue = max(0, min(1, dragValue));
dragValue = dragValue * (widget.max - widget.min) + widget.min;
if (widget.onChanged != null) {
widget.onChanged(dragValue);
}
},
onHorizontalDragEnd: (DragEndDetails details) {
setState(() {
dragging = false;
});
if (widget.onChangeEnd != null) {
widget.onChangeEnd(dragValue);
}
},
);
}
}
/// Colors for the MyFijkSlider
class MyFijkSliderColors {
const MyFijkSliderColors({
this.playedColor = const Color.fromRGBO(255, 0, 0, 0.6),
this.bufferedColor = const Color.fromRGBO(50, 50, 100, 0.4),
this.cursorColor = const Color.fromRGBO(255, 0, 0, 0.8),
this.baselineColor = const Color.fromRGBO(200, 200, 200, 0.5),
});
final Color playedColor;
final Color bufferedColor;
final Color cursorColor;
final Color baselineColor;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MyFijkSliderColors &&
runtimeType == other.runtimeType &&
hashCode == other.hashCode;
@override
int get hashCode =>
hashValues(playedColor, bufferedColor, cursorColor, baselineColor);
}
class _MySliderPainter extends CustomPainter {
final double v;
final double cv;
final bool dragging;
final Paint pt = Paint();
final MyFijkSliderColors colors;
_MySliderPainter(this.v, this.cv, this.dragging,
{this.colors = const MyFijkSliderColors()})
: assert(colors != null),
assert(v != null),
assert(cv != null);
@override
void paint(Canvas canvas, Size size) {
double lineHeight = min(size.height / 2, 1);
pt.color = colors.baselineColor;
double radius = min(size.height / 2, 4);
// draw background
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromPoints(
Offset(0, size.height / 2 - lineHeight),
Offset(size.width, size.height / 2 + lineHeight),
),
Radius.circular(radius),
),
pt,
);
final double value = v * size.width;
// draw played part
pt.color = colors.playedColor;
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromPoints(
Offset(0, size.height / 2 - lineHeight),
Offset(value, size.height / 2 + lineHeight),
),
Radius.circular(radius),
),
pt,
);
// draw cached part
final double cacheValue = cv * size.width;
if (cacheValue > value && cacheValue > 0) {
pt.color = colors.bufferedColor;
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromPoints(
Offset(value, size.height / 2 - lineHeight),
Offset(cacheValue, size.height / 2 + lineHeight),
),
Radius.circular(radius),
),
pt,
);
}
//注意改变拖动圆形光标必须按Q退出App再重新flutter run才能生效
// draw circle cursor
// pt.color = colors.cursorColor;
// pt.color = pt.color.withAlpha(max(0, pt.color.alpha - 50));
//radius = min(size.height / 2, dragging ? 10 : 5);
pt.color = Colors.red;
//radius = 10;
radius = min(size.height / 2, 10);
canvas.drawCircle(Offset(value, size.height / 2), radius, pt);
//pt.color = colors.cursorColor;
//radius = min(size.height / 2, dragging ? 6 : 3);
//canvas.drawCircle(Offset(value, size.height / 2), radius, pt);
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is _MySliderPainter && hashCode == other.hashCode;
@override
int get hashCode => hashValues(v, cv, dragging, colors);
@override
bool shouldRepaint(_MySliderPainter oldDelegate) {
return hashCode != oldDelegate.hashCode;
}
}