hyzp_ybqx-Commit182:已经实现播放视频时双击视频界面暂停时,播放按钮跟随变化

master
WinUser01 3 years ago
parent 26d6b4aa3f
commit 16cab1dcae

@ -0,0 +1,50 @@
//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.
//r:\Flutter\FlutterSDK\flutter\.pub-cache\hosted\pub.flutter-io.cn\fijkplayer-0.8.4\lib\core\MyFijkValue.dart
//part of fijkplayer;
import 'dart:core';
//
class MyFijkData {
static String fijkViewPanelVolume = "__fijkview_panel_init_volume";
static String fijkViewPanelBrightness = "__fijkview_panel_init_brightness";
static String fijkViewPanelSeekto = "__fijkview_panel_sekto_position";
}
//
String mYduration2String(Duration duration) {
if (duration.inMilliseconds < 0) return "-: negtive";
String twoDigits(int n) {
if (n >= 10) return "$n";
return "0$n";
}
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
int inHours = duration.inHours;
return inHours > 0
? "$inHours:$twoDigitMinutes:$twoDigitSeconds"
: "$twoDigitMinutes:$twoDigitSeconds";
}

@ -0,0 +1,828 @@
import 'dart:async';
import 'dart:core';
import 'dart:math';
import 'dart:ui';
import 'dart:typed_data';
import 'package:fijkplayer/fijkplayer.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'my_fijkvalue.dart';
import '../components/commonFun.dart';
import 'package:provider/provider.dart';
import '../provider/player_ratio.dart';
import 'my_slider.dart';
import '../my_extended_image/common/image_picker/_image_picker_io.dart';
import '../services/Storage.dart';
// class MyFijkPanelWidgetBuilder extends StatefulWidget {
// const MyFijkPanelWidgetBuilder({Key key, this.path}) : super(key: key);
// final path;
// @override
// State<StatefulWidget> createState() {
// return MyFijkPanelWidgetBuilderState();
// }
// }
// snapshot
ImageProvider myImageProvider;
//ImageProvider _imageProvider;
//Timer _snapshotTimer;
FijkPanelWidgetBuilder fijkPanel2Builder3(
{Key key,
final FijkPlayer player,
final bool fill = false,
final int duration = 4000,
final bool doubleTap = true,
final bool snapShot = false,
final VoidCallback onBack}) {
return (FijkPlayer player, FijkData data, BuildContext context, Size viewSize,
Rect texturePos) {
return MyFijkPanelWidgetBuilder(
key: key,
player: player,
data: data,
onBack: onBack,
viewSize: viewSize,
texPos: texturePos,
fill: fill,
doubleTap: doubleTap,
snapShot: snapShot,
hideDuration: duration,
);
};
}
class MyFijkPanelWidgetBuilder extends StatefulWidget {
final FijkPlayer player;
final FijkData data;
final VoidCallback onBack;
final Size viewSize;
final Rect texPos;
final bool fill;
final bool doubleTap;
final bool snapShot;
final int hideDuration;
const MyFijkPanelWidgetBuilder(
{Key key,
@required this.player,
this.data,
this.fill,
this.onBack,
this.viewSize,
this.hideDuration,
this.doubleTap,
this.snapShot,
this.texPos})
: assert(player != null),
assert(
hideDuration != null && hideDuration > 0 && hideDuration < 10000),
super(key: key);
// @override
// FijkPanel2State createState() => FijkPanel2State();
// @override
//State<StatefulWidget> createState() {
MyFijkPanelWidgetBuilderState createState() {
return MyFijkPanelWidgetBuilderState(player);
}
}
class MyFijkPanelWidgetBuilderState extends State<MyFijkPanelWidgetBuilder>
with SingleTickerProviderStateMixin {
FijkPlayer player;
MyFijkPanelWidgetBuilderState(@required this.player) {
_oldFullScreen = player.value.fullScreen;
}
PlayerRatioProvide playerRatioProvide;
AnimationController _controller;
Animation<Offset> _animation;
Offset _normalizedOffset;
double _previousScale;
double _kMinFlingVelocity = 600.0;
Offset _offset = Offset.zero;
double _scale = 1.0;
Offset _focalPoint = Offset.zero;
Offset _deltaPoint = Offset.zero;
bool _oldFullScreen;
bool _bScaleing = false;
//FijkPlayer get player => widget.player;
Timer _hideTimer;
bool _hideStuff = true;
Timer _statelessTimer;
bool _prepared = false;
bool _playing = false;
//bool _dragLeft;
int _nDrag; //0 Left, 1 Center, 2 Right
double _volume;
double _brightness;
double _deltaX = 0;
double _deltaY = 0;
double _seekPos = -1.0;
Duration _duration = Duration();
Duration _currentPos = Duration();
Duration _bufferPos = Duration();
StreamSubscription _currentPosSubs;
StreamSubscription _bufferPosSubs;
StreamController<double> _valController;
// snapshot
//ImageProvider _imageProvider;
Timer _snapshotTimer;
// Is it needed to clear seek data in FijkData (widget.data)
bool _needClearSeekData = true;
static const MyFijkSliderColors sliderColors = MyFijkSliderColors();
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
_controller.addListener(() {
setState(() {
_offset = _animation.value;
});
});
_valController = StreamController.broadcast();
_prepared = player.state.index >= FijkState.prepared.index;
_playing = player.state == FijkState.started;
_duration = player.value.duration;
_currentPos = player.currentPos;
_bufferPos = player.bufferPos;
_currentPosSubs = player.onCurrentPosUpdate.listen((v) {
if (_hideStuff == false) {
setState(() {
_currentPos = v;
});
} else {
_currentPos = v;
}
if (_needClearSeekData) {
widget.data.clearValue(MyFijkData.fijkViewPanelSeekto);
}
_needClearSeekData = false;
});
if (widget.data.contains(MyFijkData.fijkViewPanelSeekto)) {
var pos = widget.data.getValue(MyFijkData.fijkViewPanelSeekto) as double;
_currentPos = Duration(milliseconds: pos.toInt());
}
_bufferPosSubs = player.onBufferPosUpdate.listen((v) {
if (_hideStuff == false) {
setState(() {
_bufferPos = v;
});
} else {
_bufferPos = v;
}
});
player.addListener(_playerValueChanged);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
_valController?.close();
_hideTimer?.cancel();
_statelessTimer?.cancel();
_snapshotTimer?.cancel();
_currentPosSubs?.cancel();
_bufferPosSubs?.cancel();
player.removeListener(_playerValueChanged);
}
double dura2double(Duration d) {
return d != null ? d.inMilliseconds.toDouble() : 0.0;
}
void _playerValueChanged() {
FijkValue value = player.value;
if (value.duration != _duration) {
if (_hideStuff == false) {
setState(() {
_duration = value.duration;
});
} else {
_duration = value.duration;
}
}
bool playing = (value.state == FijkState.started);
bool prepared = value.prepared;
if (playing != _playing ||
prepared != _prepared ||
value.state == FijkState.asyncPreparing) {
setState(() {
_playing = playing;
_prepared = prepared;
});
}
}
void _restartHideTimer() {
_hideTimer?.cancel();
_hideTimer = Timer(Duration(milliseconds: widget.hideDuration), () {
setState(() {
_hideStuff = true;
});
});
}
void onTapFun() {
if (_hideStuff == true) {
_restartHideTimer();
}
setState(() {
_hideStuff = !_hideStuff;
});
}
void playOrPause() {
if (player.isPlayable() || player.state == FijkState.asyncPreparing) {
if (player.state == FijkState.started) {
//bPlaying = false;
playerRegionProvide.changePlayerState(false);
Storage.setString('bPlaying', 'false');
player.pause();
} else {
//bPlaying = true;
playerRegionProvide.changePlayerState(true);
Storage.setString('bPlaying', 'true');
player.start();
}
//setState(() {});
} else {
FijkLog.w("Invalid state ${player.state} ,can't perform play or pause");
}
}
void onVerticalDragStartFun(DragStartDetails d) {
// if (_bScaleing) {
// return;
// }
if (d.localPosition.dx > panelWidth() * 3 / 4) {
// right, volume
//_dragLeft = false;
_nDrag = 2; //0 Left, 1 Center, 2 Right
//https://fijkplayer.befovy.com/docs/zh/system-volume.html#gsc.tab=0
/// never show system volume changed UI.
int neverShowUI = 2;
FijkVolume.setUIMode(neverShowUI);
FijkVolume.getVol().then((v) {
if (widget.data != null &&
!widget.data.contains(MyFijkData.fijkViewPanelVolume)) {
widget.data.setValue(MyFijkData.fijkViewPanelVolume, v);
}
setState(() {
_volume = v;
_valController.add(v);
});
});
} else if (d.localPosition.dx < panelWidth() / 4) {
// left, brightness
//_dragLeft = true;
_nDrag = 0; //0 Left, 1 Center, 2 Right
FijkPlugin.screenBrightness().then((v) {
if (widget.data != null &&
!widget.data.contains(MyFijkData.fijkViewPanelBrightness)) {
widget.data.setValue(MyFijkData.fijkViewPanelBrightness, v);
}
setState(() {
_brightness = v;
_valController.add(v);
});
});
} else {
_nDrag = 1; //0 Left, 1 Center, 2 Right
// setState(() {
// if (_oldFullScreen != player.value.fullScreen) {
// //便
// _oldFullScreen = player.value.fullScreen;
// // _offset = Offset.zero;
// // _scale = 1.0;
// //_focalPoint = Offset.zero;
// //_deltaPoint = Offset.zero;
// }
// // _bScaleing = true;
// // _previousScale = _scale;
// // _normalizedOffset = (d.localPosition - _offset) / _scale;
// // //
// // _controller.stop();
// });
}
_statelessTimer?.cancel();
_statelessTimer = Timer(const Duration(milliseconds: 2000), () {
setState(() {});
});
}
void onVerticalDragUpdateFun(DragUpdateDetails d) {
// if (_bScaleing) {
// return;
// }
double delta = d.primaryDelta / panelHeight();
print("d.primaryDelta = ${d.primaryDelta}, delta = {$delta}");
delta = -delta.clamp(-1.0, 1.0);
//if (_dragLeft != null && _dragLeft == false) {
if (_nDrag != null && _nDrag == 2) {
if (_volume != null) {
_volume += delta;
_volume = _volume.clamp(0.0, 1.0);
FijkVolume.setVol(_volume);
setState(() {
_valController.add(_volume);
});
}
//} else if (_dragLeft != null && _dragLeft == true) {
} else if (_nDrag != null && _nDrag == 0) {
if (_brightness != null) {
_brightness += delta;
_brightness = _brightness.clamp(0.0, 1.0);
FijkPlugin.setScreenBrightness(_brightness);
setState(() {
_valController.add(_brightness);
});
}
} else {
setState(() {
//_scale = (_previousScale * details.scale).clamp(1.0, 10.0);
// 1~10
// _offset = _clampOffset(d.localPosition - _normalizedOffset * _scale);
// playerRatioProvide.changeOffset(_offset);
_deltaY -= 2 * d.primaryDelta / panelHeight();
_deltaY = _deltaY.clamp(-1.0, 1.0);
playerRatioProvide.changeDeltaY(_deltaY);
//
});
}
}
void onVerticalDragEndFun(DragEndDetails e) {
_volume = null;
_brightness = null;
}
Widget buildPlayButton(BuildContext context, double height) {
Icon icon = (player.state == FijkState.started)
? Icon(Icons.pause)
: Icon(Icons.play_arrow);
bool fullScreen = player.value.fullScreen;
return IconButton(
padding: EdgeInsets.all(0),
iconSize: fullScreen ? height : height * 0.8,
color: Color(0xFFFFFFFF),
icon: icon,
onPressed: playOrPause,
);
}
Widget buildFullScreenButton(BuildContext context, double height) {
Icon icon = player.value.fullScreen
? Icon(Icons.fullscreen_exit)
: Icon(Icons.fullscreen);
bool fullScreen = player.value.fullScreen;
return IconButton(
padding: EdgeInsets.all(0),
iconSize: fullScreen ? height : height * 0.8,
color: Color(0xFFFFFFFF),
icon: icon,
onPressed: () {
player.value.fullScreen
? player.exitFullScreen()
: player.enterFullScreen();
},
);
}
Widget buildTimeText(BuildContext context, double height) {
String text = "${mYduration2String(_currentPos)}" +
"/${mYduration2String(_duration)}";
return Text(text, style: TextStyle(fontSize: 12, color: Color(0xFFFFFFFF)));
}
Widget buildSlider(BuildContext context) {
double duration = dura2double(_duration);
double currentValue = _seekPos > 0 ? _seekPos : dura2double(_currentPos);
currentValue = currentValue.clamp(0.0, duration);
double bufferPos = dura2double(_bufferPos);
bufferPos = bufferPos.clamp(0.0, duration);
return Padding(
padding: EdgeInsets.only(left: 0),
child: MyFijkSlider(
colors: sliderColors,
value: currentValue,
cacheValue: bufferPos,
min: 0.0,
max: duration,
onChanged: (v) {
_restartHideTimer();
setState(() {
_seekPos = v;
});
},
onChangeEnd: (v) {
setState(() {
player.seekTo(v.toInt());
_currentPos = Duration(milliseconds: _seekPos.toInt());
widget.data.setValue(MyFijkData.fijkViewPanelSeekto, _seekPos);
_needClearSeekData = true;
_seekPos = -1.0;
});
},
),
);
}
Widget buildBottom(BuildContext context, double height) {
if (_duration != null && _duration.inMilliseconds > 0) {
return Row(
children: <Widget>[
buildPlayButton(context, height),
buildTimeText(context, height),
Expanded(child: buildSlider(context)),
buildFullScreenButton(context, height),
],
);
} else {
return Row(
children: <Widget>[
buildPlayButton(context, height),
Expanded(child: Container()),
buildFullScreenButton(context, height),
],
);
}
}
void takeSnapshot() {
player.takeSnapShot().then((v) {
var provider = MemoryImage(v);
precacheImage(provider, context).then((_) {
setState(() {
myImageProvider = provider;
});
});
FijkLog.d("get snapshot succeed");
//Uint8List fileData;
String fileFath;
ImageSaver.save('extended_image_cropped_image.jpg', v).then((value) {
fileFath = value;
// var fileFath = await ImagePickerSaver.saveFile(fileData: fileData);
print('my save fileFath : $fileFath');
});
}).catchError((e) {
FijkLog.d("get snapshot failed");
});
}
Widget buildPanel(BuildContext context) {
double height = panelHeight();
bool fullScreen = player.value.fullScreen;
Widget centerWidget = Container(
color: Color(0x00000000),
);
Widget centerChild = Container(
color: Color(0x00000000),
);
if (fullScreen && widget.snapShot) {
centerWidget = Row(
children: <Widget>[
Expanded(child: centerChild),
Padding(
padding: EdgeInsets.only(left: 10, right: 10, top: 8, bottom: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
IconButton(
padding: EdgeInsets.all(0),
color: Color(0xFFFFFFFF),
icon: Icon(Icons.camera_alt),
onPressed: () {
takeSnapshot();
},
),
],
),
)
],
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
height: height > 200 ? 80 : height / 5,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0x88000000), Color(0x00000000)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
),
Expanded(
child: centerWidget,
),
Container(
height: height > 80 ? 80 : height / 2,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0x88000000), Color(0x00000000)],
end: Alignment.topCenter,
begin: Alignment.bottomCenter,
),
),
alignment: Alignment.bottomCenter,
child: Container(
height: height > 80 ? 45 : height / 2,
padding: EdgeInsets.only(left: 8, right: 8, bottom: 5),
child: buildBottom(context, height > 80 ? 40 : height / 2),
// child: CustomFijkWidgetBottom(
// player: player,
// buildContext: context,
// viewSize:
// Size(widget.viewSize.width, widget.viewSize.height - 50),
// texturePos: Rect.fromLTRB(widget.texPos.left, widget.texPos.top,
// widget.texPos.width, widget.texPos.height - 50),
//),
),
)
],
);
}
Rect panelRect() {
Rect rect = player.value.fullScreen || (true == widget.fill)
? Rect.fromLTWH(0, 0, widget.viewSize.width, widget.viewSize.height)
: Rect.fromLTRB(
max(0.0, widget.texPos.left),
max(0.0, widget.texPos.top),
min(widget.viewSize.width, widget.texPos.right),
min(widget.viewSize.height, widget.texPos.bottom));
return rect;
}
double panelHeight() {
if (player.value.fullScreen || (true == widget.fill)) {
return widget.viewSize.height;
} else {
return min(widget.viewSize.height, widget.texPos.bottom) -
max(0.0, widget.texPos.top);
}
}
double panelWidth() {
if (player.value.fullScreen || (true == widget.fill)) {
return widget.viewSize.width;
} else {
return min(widget.viewSize.width, widget.texPos.right) -
max(0.0, widget.texPos.left);
}
}
Widget buildBack(BuildContext context) {
return IconButton(
padding: EdgeInsets.only(left: 5),
icon: Icon(
Icons.arrow_back_ios,
color: Color(0xDDFFFFFF),
),
onPressed: widget.onBack,
);
}
Widget buildStateless() {
if (_volume != null || _brightness != null) {
Widget toast = _volume == null
? defaultFijkBrightnessToast(_brightness, _valController.stream)
: defaultFijkVolumeToast(_volume, _valController.stream);
return IgnorePointer(
child: AnimatedOpacity(
opacity: 1,
duration: Duration(milliseconds: 500),
child: toast,
),
);
} else if (player.state == FijkState.asyncPreparing) {
return Container(
alignment: Alignment.center,
child: SizedBox(
width: 30,
height: 30,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.white)),
),
);
} else if (player.state == FijkState.error) {
return Container(
alignment: Alignment.center,
child: Icon(
Icons.error,
size: 30,
color: Color(0x99FFFFFF),
),
);
} else if (myImageProvider != null) {
_snapshotTimer?.cancel();
_snapshotTimer = Timer(Duration(milliseconds: 1500), () {
if (mounted) {
setState(() {
myImageProvider = null;
});
}
});
return Center(
child: IgnorePointer(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.yellowAccent, width: 3)),
child:
Image(height: 200, fit: BoxFit.contain, image: myImageProvider),
),
),
);
} else {
return Container();
}
}
GestureDetector buildGestureDetector(BuildContext context) {
return GestureDetector(
onScaleStart: _handleOnScaleStart,
onScaleUpdate: _handleOnScaleUpdate,
onScaleEnd: _handleOnScaleEnd,
onDoubleTap: () {
// FijkView
print('My onDoubleTap');
if (1.0 == playerRatioProvide.scale) {
playOrPause();
} else {
_handleScaleBack();
}
},
onTap: onTapFun,
//onDoubleTap: widget.doubleTap ? onDoubleTapFun : null,
onVerticalDragUpdate: onVerticalDragUpdateFun,
onVerticalDragStart: onVerticalDragStartFun,
onVerticalDragEnd: onVerticalDragEndFun,
//onHorizontalDragUpdate: (d) {},
child: AbsorbPointer(
absorbing: _hideStuff,
child: AnimatedOpacity(
opacity: _hideStuff ? 0 : 1,
duration: Duration(milliseconds: 300),
child: buildPanel(context),
),
),
);
}
void _handleOnScaleStart(ScaleStartDetails details) {
setState(() {
// if (_oldFullScreen != player.value.fullScreen) {
// //便
// _oldFullScreen = player.value.fullScreen;
// // _offset = Offset.zero;
// // _scale = 1.0;
// //_focalPoint = Offset.zero;
// //_deltaPoint = Offset.zero;
// }
_bScaleing = true;
_previousScale = _scale;
_normalizedOffset = (details.focalPoint - _offset) / _scale;
//
_controller.stop();
_focalPoint = details.focalPoint;
});
}
void _handleScaleBack() {
//
playerRatioProvide.changeScale(1.0);
playerRatioProvide.changeOffset(Offset(0, 0));
playerRatioProvide.changeDeltaX(0.0);
playerRatioProvide.changeDeltaY(0.0);
}
void _handleOnScaleUpdate(ScaleUpdateDetails details) {
setState(() {
print('details.scale = ${details.scale}');
//print('_scale = $_scale, offset.dx = ${_offset.dx}, offset.dy = ${_offset.dy}');
//print('details.focalPoint = (${details.focalPoint.dx}, ${details.focalPoint.dy})');
//print('details.horizontalScale = ${details.horizontalScale}; details.verticalScale = ${details.verticalScale})');
if (1.0 != details.scale) {
_scale = (_previousScale * details.scale).clamp(1.0, 10.0);
playerRatioProvide.changeScale(_scale);
// 1~10
_offset = _clampOffset(details.focalPoint - _normalizedOffset * _scale);
} else {
_deltaPoint = _clampdeltaPoint(details.focalPoint - _focalPoint);
_focalPoint = details.focalPoint;
print('_deltaPoint = (${_deltaPoint.dx}, ${_deltaPoint.dy})');
playerRatioProvide.changeDeltaX(_deltaPoint.dx);
playerRatioProvide.changeDeltaY(_deltaPoint.dy);
}
//
playerRatioProvide.changeOffset(_offset);
});
}
Offset _clampdeltaPoint(Offset delta) {
final Size size = context.size; // widget
double rate = 2.0;
Offset deltaPoint =
Offset((rate * delta.dx / size.width), (rate * delta.dy / size.height));
_deltaPoint -= deltaPoint;
return Offset(
_deltaPoint.dx.clamp(-1.0, 1.0), _deltaPoint.dy.clamp(-1.0, 1.0));
}
Offset _clampOffset(Offset offset) {
final Size size = context.size;
// widget
final Offset minOffset = Offset(size.width, size.height) * (1.0 - _scale);
//
return Offset(
offset.dx.clamp(minOffset.dx, 0.0), offset.dy.clamp(minOffset.dy, 0.0));
}
void _handleOnScaleEnd(ScaleEndDetails details) {
final double magnitude = details.velocity.pixelsPerSecond.distance;
if (magnitude < _kMinFlingVelocity) return;
final Offset direction = details.velocity.pixelsPerSecond / magnitude;
//
final double distance = (Offset.zero & context.size).shortestSide;
// 600*4801.25
_animation = _controller.drive(Tween<Offset>(
begin: _offset, end: _clampOffset(_offset + direction * distance)));
_controller
..value = 0.0
..fling(velocity: magnitude / 1000.0);
_bScaleing = false;
}
@override
Widget build(BuildContext context) {
playerRatioProvide = Provider.of<PlayerRatioProvide>(context);
Rect rect = panelRect();
List ws = <Widget>[];
if (_statelessTimer != null && _statelessTimer.isActive) {
ws.add(buildStateless());
} else if (player.state == FijkState.asyncPreparing) {
ws.add(buildStateless());
} else if (player.state == FijkState.error) {
ws.add(buildStateless());
} else if (myImageProvider != null) {
ws.add(buildStateless());
}
ws.add(buildGestureDetector(context));
if (widget.onBack != null) {
ws.add(buildBack(context));
}
return Positioned.fromRect(
rect: rect,
child: Stack(children: ws),
);
}
}

@ -0,0 +1,244 @@
//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退Appflutter 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;
}
}

@ -16,6 +16,7 @@ import 'package:provider/provider.dart';
import '../components/commonFun.dart';
import '../services/Storage.dart';
import '../my_fijkPanel_fix/my_panel3.dart';
const _kControlViewTypes = [kControlViewTypeDefault, kControlViewTypeWithout];
@ -40,16 +41,20 @@ class SuperPlayerPage extends StatefulWidget {
_SuperPlayerPageState createState() => _SuperPlayerPageState();
}
class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListener {
class _SuperPlayerPageState extends State<SuperPlayerPage>
with WidgetsBindingObserver, AutomaticKeepAliveClientMixin {
// SuperPlayerController _playerController = SuperPlayerController();
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
final FijkPlayer _playerController = FijkPlayer();
String _sdkVersion = 'Unknown';
List<String> _logs = [];
bool bFullScreen = false;
String _controlViewType = _kControlViewTypes.first;
@override
void dispose() {
Playing = false;
@ -69,6 +74,9 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
// });
// init();
WidgetsBinding.instance.addObserver(this);
_playerController.setOption(FijkOption.hostCategory, "enable-snapshot", 1);
_playerController.setOption(FijkOption.playerCategory, "mediacodec-all-videos", 1);
startPlay();
@ -186,10 +194,14 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
PlayerRatioProvide playerRatioProvide;
FijkPanelWidgetBuilder _fijkPanelWidgetBuilder;
@override
Widget build(BuildContext context) {
_fijkPanelWidgetBuilder = fijkPanel2Builder3(snapShot: true, player: _playerController);
playerRegionProvide = Provider.of<PlayerRegionProvide>(context);
playerRatioProvide = Provider.of<PlayerRatioProvide>(context);
// List<Widget> listData = getDataListControl2();
double btnHeight1 = 70; //
double btnHeight2 = 160; //
@ -294,7 +306,8 @@ class _SuperPlayerPageState extends State<SuperPlayerPage> with SuperPlayerListe
//-OK
color: Colors.black,
player: _playerController,
panelBuilder: fijkPanel2Builder(snapShot: true),
// panelBuilder: fijkPanel2Builder(snapShot: true),
panelBuilder: _fijkPanelWidgetBuilder,
fsFit: FijkFit.fill,
// panelBuilder: simplestUI,
// panelBuilder: (FijkPlayer player, BuildContext context,

Loading…
Cancel
Save