tone_bar.dart 6.8 KB

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