location_info.dart 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. part of 'control_board.dart';
  2. /// 播放帧位置信息(帧索引、时间索引)
  3. class LocationInfo extends StatelessWidget {
  4. LocationInfo({Key? key}) : super(key: key);
  5. /// 值展示固定宽度
  6. // ignore: constant_identifier_names
  7. static const double C_VALUE_DISPLAY_WIDTH = 30.0;
  8. final playerController = Get.find<IPlayerController>() as VidPlayerController;
  9. late final int totalFrameCount;
  10. late final double totalDuration;
  11. @override
  12. Widget build(BuildContext context) {
  13. _initTotalInfo();
  14. return Row(
  15. mainAxisSize: MainAxisSize.min,
  16. children: [
  17. _buildLabelColumn(),
  18. SizedBox(
  19. width: C_VALUE_DISPLAY_WIDTH,
  20. child: _CurrentValueDisplayColumn(
  21. totalDuration: totalDuration,
  22. totalFrameCount: totalFrameCount,
  23. ),
  24. ),
  25. _buildTotalDescColumn(),
  26. ],
  27. );
  28. }
  29. void _initTotalInfo() {
  30. final channel = playerController.dataChannel;
  31. totalFrameCount = channel.imageCount;
  32. totalDuration = totalFrameCount / channel.probe.frameRate;
  33. }
  34. Widget _buildLabelColumn() {
  35. return _SpanColumn(
  36. alignment: CrossAxisAlignment.start,
  37. durationSpan: i18nBook.measure.playLocationDurationLabel.t,
  38. frameCountSpan: i18nBook.measure.playLocationFrameCountLabel.t,
  39. );
  40. }
  41. Widget _buildTotalDescColumn() {
  42. final totalDurationStr = '/${totalDuration.toStringAsFixed(1)} s';
  43. final totalFrameCountStr = '/$totalFrameCount';
  44. return _SpanColumn(
  45. durationSpan: totalDurationStr,
  46. frameCountSpan: totalFrameCountStr,
  47. );
  48. }
  49. }
  50. class _CurrentValueDisplayColumn extends StatefulWidget {
  51. const _CurrentValueDisplayColumn({
  52. Key? key,
  53. required this.totalDuration,
  54. required this.totalFrameCount,
  55. }) : super(key: key);
  56. final double totalDuration;
  57. final int totalFrameCount;
  58. @override
  59. State<StatefulWidget> createState() => _CurrentValueDisplayColumnState();
  60. }
  61. class _CurrentValueDisplayColumnState
  62. extends State<_CurrentValueDisplayColumn> {
  63. final playerController = Get.find<IPlayerController>() as VidPlayerController;
  64. int currentIndex = 0;
  65. @override
  66. void initState() {
  67. playerController.frameUpdated.addListener(_onFrameUpdated);
  68. super.initState();
  69. }
  70. @override
  71. void dispose() {
  72. playerController.frameUpdated.addListener(_onFrameUpdated);
  73. super.dispose();
  74. }
  75. @override
  76. Widget build(BuildContext context) {
  77. final currFrameNum = currentIndex + 1;
  78. double currDuration;
  79. if (currFrameNum == widget.totalFrameCount) {
  80. currDuration = widget.totalDuration;
  81. } else {
  82. currDuration =
  83. (currentIndex / widget.totalFrameCount) * widget.totalDuration;
  84. }
  85. return _SpanColumn(
  86. alignment: CrossAxisAlignment.end,
  87. frameCountSpan: currFrameNum.toString(),
  88. durationSpan: currDuration.toStringAsFixed(1),
  89. );
  90. }
  91. void _onFrameUpdated(Object sender, VidUsImage frame) {
  92. if (frame.index == currentIndex) return;
  93. if (mounted) {
  94. setState(() {
  95. currentIndex = frame.index;
  96. });
  97. }
  98. }
  99. }
  100. class _SpanColumn extends StatelessWidget {
  101. const _SpanColumn({
  102. Key? key,
  103. this.alignment = CrossAxisAlignment.start,
  104. this.durationSpan = '',
  105. this.frameCountSpan = '',
  106. }) : super(key: key);
  107. final CrossAxisAlignment alignment;
  108. final String durationSpan;
  109. final String frameCountSpan;
  110. @override
  111. Widget build(BuildContext context) {
  112. return Column(
  113. mainAxisAlignment: MainAxisAlignment.center,
  114. crossAxisAlignment: alignment,
  115. children: [
  116. _buildLine(durationSpan),
  117. _buildLine(frameCountSpan),
  118. ],
  119. );
  120. }
  121. Widget _buildLine(String content) {
  122. return Text(
  123. content,
  124. style: const TextStyle(color: Colors.white),
  125. );
  126. }
  127. }