tone_bar.dart 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. part of 'operate_bar.dart';
  2. class _ContrastToneBar extends StatefulWidget {
  3. @override
  4. State<StatefulWidget> createState() => _ContrastToneBarState();
  5. }
  6. class _ContrastToneBarState extends State<_ContrastToneBar> {
  7. final playerController = Get.find<IPlayerController>() as VidPlayerController;
  8. @override
  9. void initState() {
  10. WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
  11. if (mounted) {
  12. playerController.eventHandler.addListener(onControllerEvent);
  13. }
  14. });
  15. super.initState();
  16. }
  17. @override
  18. Widget build(BuildContext context) {
  19. return _ToneBar(
  20. max: 100,
  21. min: -100,
  22. value: 0,
  23. icon: const Icon(
  24. Icons.brightness_medium,
  25. color: Colors.white,
  26. ),
  27. onChange: (v) {
  28. playerController.setContrast(v.toInt());
  29. },
  30. );
  31. }
  32. @override
  33. void dispose() {
  34. playerController.eventHandler.removeListener(onControllerEvent);
  35. super.dispose();
  36. }
  37. void onControllerEvent(Object sender, VidPlayerEvent e) {
  38. if (e is VidPlayerContrastChangeEvent) {
  39. onPlayStatusChanged(e);
  40. }
  41. }
  42. void onPlayStatusChanged(VidPlayerContrastChangeEvent e) {
  43. setState(() {});
  44. }
  45. }
  46. class _BrightnessToneBar extends StatefulWidget {
  47. @override
  48. State<StatefulWidget> createState() => _BrightnessToneBarState();
  49. }
  50. class _BrightnessToneBarState extends State<_BrightnessToneBar> {
  51. final playerController = Get.find<IPlayerController>() as VidPlayerController;
  52. @override
  53. void initState() {
  54. WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
  55. if (mounted) {
  56. playerController.eventHandler.addListener(onControllerEvent);
  57. }
  58. });
  59. super.initState();
  60. }
  61. @override
  62. Widget build(BuildContext context) {
  63. return _ToneBar(
  64. max: 100,
  65. min: -100,
  66. value: 0,
  67. icon: const Icon(
  68. Icons.wb_sunny_sharp,
  69. color: Colors.white,
  70. ),
  71. onChange: (v) {
  72. playerController.setBrightness(v.toInt());
  73. },
  74. );
  75. }
  76. @override
  77. void dispose() {
  78. playerController.eventHandler.removeListener(onControllerEvent);
  79. super.dispose();
  80. }
  81. void onControllerEvent(Object sender, VidPlayerEvent e) {
  82. if (e is VidPlayerBrightnessChangeEvent) {
  83. onPlayStatusChanged(e);
  84. }
  85. }
  86. void onPlayStatusChanged(VidPlayerBrightnessChangeEvent e) {
  87. setState(() {});
  88. }
  89. }
  90. class _ToneBar extends StatefulWidget {
  91. const _ToneBar({
  92. Key? key,
  93. required this.icon,
  94. required this.min,
  95. required this.max,
  96. required this.value,
  97. this.onChange,
  98. }) : super(key: key);
  99. final Widget icon;
  100. final ValueChanged<double>? onChange;
  101. final double min;
  102. final double max;
  103. final double value;
  104. final Color themeColor = Colors.white;
  105. @override
  106. State<StatefulWidget> createState() => _ToneBarState();
  107. }
  108. class _ToneBarState extends State<_ToneBar> {
  109. static const _kIconSize = 20.0;
  110. static const splashRadius = _kIconSize / 2 + 3;
  111. late double _value;
  112. @override
  113. void initState() {
  114. syncProps();
  115. super.initState();
  116. }
  117. @override
  118. void didUpdateWidget(covariant _ToneBar oldWidget) {
  119. syncProps();
  120. super.didUpdateWidget(oldWidget);
  121. }
  122. void syncProps() {
  123. _value = widget.value;
  124. }
  125. @override
  126. Widget build(BuildContext context) {
  127. return Row(
  128. children: [
  129. widget.icon,
  130. const SizedBox(width: 8),
  131. buildReduceIcon(),
  132. buildSlider(context),
  133. buildIncreaseIcon(),
  134. const SizedBox(width: 8),
  135. SizedBox(
  136. width: 30,
  137. child: Text(
  138. '${_value.toInt()}',
  139. style: TextStyle(color: widget.themeColor),
  140. )),
  141. ],
  142. );
  143. }
  144. Widget buildReduceIcon() {
  145. return IconButton(
  146. color: widget.themeColor,
  147. constraints: const BoxConstraints(
  148. minHeight: _kIconSize,
  149. minWidth: _kIconSize,
  150. ),
  151. splashRadius: splashRadius,
  152. padding: EdgeInsets.zero,
  153. onPressed: () {
  154. updateValue(_value - 1);
  155. },
  156. icon: const Icon(Icons.remove_circle_outline, size: _kIconSize),
  157. );
  158. }
  159. Widget buildIncreaseIcon() {
  160. return IconButton(
  161. color: widget.themeColor,
  162. constraints: const BoxConstraints(
  163. minHeight: _kIconSize,
  164. minWidth: _kIconSize,
  165. ),
  166. splashRadius: splashRadius,
  167. padding: EdgeInsets.zero,
  168. onPressed: () {
  169. updateValue(_value + 1);
  170. },
  171. icon: const Icon(Icons.add_circle_outline, size: _kIconSize),
  172. );
  173. }
  174. Widget buildSlider(BuildContext context) {
  175. final trackColor = Theme.of(context).primaryColor;
  176. return SliderTheme(
  177. data: SliderThemeData(
  178. trackHeight: 4,
  179. activeTrackColor: trackColor,
  180. inactiveTrackColor: trackColor,
  181. thumbColor: Colors.grey[300],
  182. thumbShape: const RoundSliderThumbShape(
  183. enabledThumbRadius: 6,
  184. elevation: 3.0,
  185. ),
  186. overlayShape: SliderComponentShape.noOverlay,
  187. trackShape: const _FullWidthRectangularSliderTrackShape(
  188. padding: EdgeInsets.symmetric(horizontal: 4),
  189. ),
  190. ),
  191. child: Slider(
  192. max: widget.max,
  193. min: widget.min,
  194. value: _value,
  195. label: _value.toInt().toString(),
  196. divisions: (widget.max - widget.min).toInt(),
  197. onChanged: (v) {
  198. updateValue(v);
  199. },
  200. ),
  201. );
  202. }
  203. void updateValue(double value) {
  204. if (value < widget.min || value > widget.max) {
  205. return;
  206. }
  207. setState(() {
  208. _value = value;
  209. });
  210. widget.onChange?.call(value);
  211. }
  212. }
  213. class _FullWidthRectangularSliderTrackShape
  214. extends RectangularSliderTrackShape {
  215. const _FullWidthRectangularSliderTrackShape({this.padding});
  216. final EdgeInsets? padding;
  217. @override
  218. Rect getPreferredRect({
  219. required RenderBox parentBox,
  220. Offset offset = Offset.zero,
  221. required SliderThemeData sliderTheme,
  222. bool isEnabled = false,
  223. bool isDiscrete = false,
  224. }) {
  225. double trackHeight = sliderTheme.trackHeight ?? 2;
  226. double trackLeft = offset.dx;
  227. double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
  228. // 让轨道宽度等于 Slider 宽度
  229. double trackWidth = parentBox.size.width;
  230. if (padding != null) {
  231. trackHeight -= padding!.bottom;
  232. trackHeight -= padding!.top;
  233. trackWidth -= padding!.right;
  234. trackWidth -= padding!.left;
  235. trackTop += padding!.top;
  236. trackLeft += padding!.left;
  237. }
  238. return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
  239. }
  240. }