Flick Video Player 宽高比或 strech/fit Flutter 中的视频本身
Flick Video Player aspect ratio or strech/fit the video itself in Flutter
我正在使用来自此处 https://pub.dev/packages/flick_video_player 的 flick_video_player 插件。我正在显示来自 Firestorage 的视频。它正在工作,但我无法更改纵横比。就像你在下面看到的那样,我想要适合容器,因为现在它是从原来的容器中裁剪下来的。
我尝试使用 flickVideoWithControls: const FlickVideoWithControls(videoFit: BoxFit.cover,),但没有成功。
class SessionSubchapterClass extends StatefulWidget {
const SessionSubchapterClass({Key? key}) : super(key: key);
@override
State<SessionSubchapterClass> createState() => _SessionSubchapterClassState();
}
class _SessionSubchapterClassState extends State<SessionSubchapterClass> with TickerProviderStateMixin{
bool isLoading = false;
late FlickManager flickManager;
double getScale() {
double videoRatio = flickManager.flickVideoManager!.videoPlayerValue!.aspectRatio;
if (videoRatio < videoContainerRatio) {
///for tall videos, we just return the inverse of the controller aspect ratio
return videoContainerRatio / videoRatio;
} else {
///for wide videos, divide the video AR by the fixed container AR
///so that the video does not over scale
return videoRatio / videoContainerRatio;
}
}
@override
initState() {
super.initState();
flickManager = FlickManager(
videoPlayerController:
VideoPlayerController.network(widget.sessionSubchapter.video!),
);
}
@override
void dispose() {
flickManager.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
scale = getScale();
return isLoading ? const LoadingSpinner() : Sizer(
builder: (ctx, orientation, deviceType)
{
return Scaffold(
resizeToAvoidBottomInset : false,
backgroundColor: Colors.black,
appBar: AppBar(
toolbarHeight: SizerUtil.deviceType == DeviceType.mobile ? 8.h : 9.h,
centerTitle: true,
leading: FittedBox(
fit: BoxFit.cover,
child: Container(
margin: SizerUtil.deviceType == DeviceType.mobile ? EdgeInsets.fromLTRB(5.w, 1.h, 0, 1.h) : EdgeInsets.fromLTRB(5.w, 1.h, 0, 1.h),
child: ElevatedButton(
style:
ButtonStyle(
padding: SizerUtil.deviceType == DeviceType.mobile ? MaterialStateProperty.all(EdgeInsets.fromLTRB(2.w, 1.h, 2.w, 1.h)) : MaterialStateProperty.all(EdgeInsets.fromLTRB(2.w, 1.h, 2.w, 1.h)),
elevation: MaterialStateProperty.all(
0), //Defines Elevation
shadowColor: MaterialStateProperty
.all(Colors.white),
backgroundColor: MaterialStateProperty
.all(const Color(0xffE4BCB4)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(12.0),
)
)
),
onPressed: (){
Navigator.of(context).pop();
},
child: Icon(Icons.close, color: const Color(0xff393432), size: SizerUtil.deviceType == DeviceType.mobile ? 25 : 35,),
),
),
),
elevation: 0,
titleSpacing: 0,
actions: [
Container(
margin: EdgeInsets.fromLTRB(0, 1.h, 3.w, 1.h),
child: ElevatedButton(
style:
ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.fromLTRB(2.w, 1.h, 2.w, 1.h)),
elevation: MaterialStateProperty.all(
0), //Defines Elevation
shadowColor: MaterialStateProperty
.all(Colors.white),
backgroundColor: MaterialStateProperty
.all(const Color(0xffE4BCB4)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(12.0),
)
)
),
onPressed: (){
},
child: Text('MARK DONE',
style: TextStyle(
color: const Color(0xff393432),
fontSize: SizerUtil.deviceType == DeviceType.mobile ? 15 : 25,
fontWeight: FontWeight.bold,
),
),
),
)
],
backgroundColor: const Color(0xff393432),
),
body: SafeArea(
child: Column(
children: [
Expanded(
flex: 3,
child: FlickVideoPlayer(
flickManager: flickManager,
flickVideoWithControls: const FlickVideoWithControls(videoFit: BoxFit.cover,),
),
),
Expanded(
flex: 5,
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20))
),
child: Column(
children: [
TabBar(
controller: _tabController,
indicatorColor: const Color(0xffE4BCB4),
indicatorWeight: 4,
tabs: [
Container(
margin: SizerUtil.deviceType == DeviceType.mobile ? const EdgeInsets.all(0) : const EdgeInsets.fromLTRB(0, 13, 0, 13),
child: Tab(
child: Text(
"Class",
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold,
fontSize: SizerUtil.deviceType == DeviceType.mobile ? 15 : 25,
),
),
),
),
Container(
margin: SizerUtil.deviceType == DeviceType.mobile ? const EdgeInsets.all(0) : const EdgeInsets.fromLTRB(0, 13, 0, 13),
child: Tab(
child: Text(
"Work",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold,
fontSize:SizerUtil.deviceType == DeviceType.mobile ? 15 : 25,),
),
),
),
],
),
Expanded(
child: TabBarView(
controller: _tabController,
children:[
Container(
margin: const EdgeInsets.fromLTRB(15, 20, 15, 0),
child: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 50.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.titleOfChapter,
style: TextStyle(color: Colors.grey,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 14 : 23,),
)
],
),
),
SizedBox(
width: 40.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text("Activity ${widget.sessionSubchapter.order.toString()}/${widget.noOfActivities}", style:
TextStyle(
color: Colors.grey,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 14 : 23,
),)
],
),
)
],
),
const SizedBox(height: 15),
Row(children: [
Flexible(
child: Text(widget.sessionSubchapter.title!, style:
TextStyle(
color: Colors.black,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 20 : 30,
fontWeight: FontWeight.bold,
),),
)
],),
const SizedBox(height: 15),
Row(
children: [
Flexible(
child: Text(widget.sessionSubchapter.description!, style:
TextStyle(
color: Colors.black,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 17 : 27,
),),
)
],
)
],
),
),
),
SingleChildScrollView(
child: Column(
children: [
widget.sessionSubchapter.cleanSheet!="" ?
Container(
margin: const EdgeInsets.fromLTRB(15, 20, 15, 0),
width: 80.w,
height: 50.h,
padding: const EdgeInsets.all(1), // Border width
decoration: BoxDecoration(color: Colors.grey, borderRadius: BorderRadius.circular(20)),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: SizedBox.fromSize(
size: const Size.fromRadius(48), // Image radius
child: Image.network(widget.sessionSubchapter.cleanSheet!, fit: BoxFit.cover),
),
),
) :
Container(
width: 100.w,
height: 14.h,
color: const Color(0xffF3F2F2),
child: InkWell(
onTap: () async {
try {
log(widget.sessionSubchapter.cleanSheetPdf!);
setState(() {
});
}
catch(e) {
log(e.toString());
}
},
child: Container(
margin: EdgeInsets.fromLTRB(5.w, 3.5.h, 5.w, 3.5.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)
),
child:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
margin: const EdgeInsets.fromLTRB(15, 0, 15, 0),
child: Text("Activity Worksheet: Design Your Set", style:
TextStyle(
color: Colors.black,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 16 : 26,
fontWeight: FontWeight.bold,
),),
),
),
Container(
margin: const EdgeInsets.fromLTRB(15, 0, 15, 0),
child: Icon(Icons.insert_drive_file_outlined, size: SizerUtil.deviceType ==
DeviceType.mobile ? 24 : 34,color: Colors.grey,),
)
],
),
),
),
)
],
)),
]
),
),
],
),
),
)
],
),
),
);
}
);
}
}
情况如何:
我想要什么:
我使用 Chewie 插件从这里解决 https://pub.dev/packages/chewie。
videoPlayerController = VideoPlayerController.network(
widget.sessionSubchapter.video!);
videoPlayerController.initialize();
chewieController = ChewieController(
videoPlayerController: videoPlayerController,
autoPlay: true,
looping: true,
);
...
Expanded(
flex: 3,
child: Chewie(
controller: chewieController,
),
),
我正在使用来自此处 https://pub.dev/packages/flick_video_player 的 flick_video_player 插件。我正在显示来自 Firestorage 的视频。它正在工作,但我无法更改纵横比。就像你在下面看到的那样,我想要适合容器,因为现在它是从原来的容器中裁剪下来的。 我尝试使用 flickVideoWithControls: const FlickVideoWithControls(videoFit: BoxFit.cover,),但没有成功。
class SessionSubchapterClass extends StatefulWidget {
const SessionSubchapterClass({Key? key}) : super(key: key);
@override
State<SessionSubchapterClass> createState() => _SessionSubchapterClassState();
}
class _SessionSubchapterClassState extends State<SessionSubchapterClass> with TickerProviderStateMixin{
bool isLoading = false;
late FlickManager flickManager;
double getScale() {
double videoRatio = flickManager.flickVideoManager!.videoPlayerValue!.aspectRatio;
if (videoRatio < videoContainerRatio) {
///for tall videos, we just return the inverse of the controller aspect ratio
return videoContainerRatio / videoRatio;
} else {
///for wide videos, divide the video AR by the fixed container AR
///so that the video does not over scale
return videoRatio / videoContainerRatio;
}
}
@override
initState() {
super.initState();
flickManager = FlickManager(
videoPlayerController:
VideoPlayerController.network(widget.sessionSubchapter.video!),
);
}
@override
void dispose() {
flickManager.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
scale = getScale();
return isLoading ? const LoadingSpinner() : Sizer(
builder: (ctx, orientation, deviceType)
{
return Scaffold(
resizeToAvoidBottomInset : false,
backgroundColor: Colors.black,
appBar: AppBar(
toolbarHeight: SizerUtil.deviceType == DeviceType.mobile ? 8.h : 9.h,
centerTitle: true,
leading: FittedBox(
fit: BoxFit.cover,
child: Container(
margin: SizerUtil.deviceType == DeviceType.mobile ? EdgeInsets.fromLTRB(5.w, 1.h, 0, 1.h) : EdgeInsets.fromLTRB(5.w, 1.h, 0, 1.h),
child: ElevatedButton(
style:
ButtonStyle(
padding: SizerUtil.deviceType == DeviceType.mobile ? MaterialStateProperty.all(EdgeInsets.fromLTRB(2.w, 1.h, 2.w, 1.h)) : MaterialStateProperty.all(EdgeInsets.fromLTRB(2.w, 1.h, 2.w, 1.h)),
elevation: MaterialStateProperty.all(
0), //Defines Elevation
shadowColor: MaterialStateProperty
.all(Colors.white),
backgroundColor: MaterialStateProperty
.all(const Color(0xffE4BCB4)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(12.0),
)
)
),
onPressed: (){
Navigator.of(context).pop();
},
child: Icon(Icons.close, color: const Color(0xff393432), size: SizerUtil.deviceType == DeviceType.mobile ? 25 : 35,),
),
),
),
elevation: 0,
titleSpacing: 0,
actions: [
Container(
margin: EdgeInsets.fromLTRB(0, 1.h, 3.w, 1.h),
child: ElevatedButton(
style:
ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.fromLTRB(2.w, 1.h, 2.w, 1.h)),
elevation: MaterialStateProperty.all(
0), //Defines Elevation
shadowColor: MaterialStateProperty
.all(Colors.white),
backgroundColor: MaterialStateProperty
.all(const Color(0xffE4BCB4)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius
.circular(12.0),
)
)
),
onPressed: (){
},
child: Text('MARK DONE',
style: TextStyle(
color: const Color(0xff393432),
fontSize: SizerUtil.deviceType == DeviceType.mobile ? 15 : 25,
fontWeight: FontWeight.bold,
),
),
),
)
],
backgroundColor: const Color(0xff393432),
),
body: SafeArea(
child: Column(
children: [
Expanded(
flex: 3,
child: FlickVideoPlayer(
flickManager: flickManager,
flickVideoWithControls: const FlickVideoWithControls(videoFit: BoxFit.cover,),
),
),
Expanded(
flex: 5,
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20))
),
child: Column(
children: [
TabBar(
controller: _tabController,
indicatorColor: const Color(0xffE4BCB4),
indicatorWeight: 4,
tabs: [
Container(
margin: SizerUtil.deviceType == DeviceType.mobile ? const EdgeInsets.all(0) : const EdgeInsets.fromLTRB(0, 13, 0, 13),
child: Tab(
child: Text(
"Class",
style: TextStyle(
color: Colors.black, fontWeight: FontWeight.bold,
fontSize: SizerUtil.deviceType == DeviceType.mobile ? 15 : 25,
),
),
),
),
Container(
margin: SizerUtil.deviceType == DeviceType.mobile ? const EdgeInsets.all(0) : const EdgeInsets.fromLTRB(0, 13, 0, 13),
child: Tab(
child: Text(
"Work",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold,
fontSize:SizerUtil.deviceType == DeviceType.mobile ? 15 : 25,),
),
),
),
],
),
Expanded(
child: TabBarView(
controller: _tabController,
children:[
Container(
margin: const EdgeInsets.fromLTRB(15, 20, 15, 0),
child: SingleChildScrollView(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
width: 50.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.titleOfChapter,
style: TextStyle(color: Colors.grey,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 14 : 23,),
)
],
),
),
SizedBox(
width: 40.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text("Activity ${widget.sessionSubchapter.order.toString()}/${widget.noOfActivities}", style:
TextStyle(
color: Colors.grey,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 14 : 23,
),)
],
),
)
],
),
const SizedBox(height: 15),
Row(children: [
Flexible(
child: Text(widget.sessionSubchapter.title!, style:
TextStyle(
color: Colors.black,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 20 : 30,
fontWeight: FontWeight.bold,
),),
)
],),
const SizedBox(height: 15),
Row(
children: [
Flexible(
child: Text(widget.sessionSubchapter.description!, style:
TextStyle(
color: Colors.black,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 17 : 27,
),),
)
],
)
],
),
),
),
SingleChildScrollView(
child: Column(
children: [
widget.sessionSubchapter.cleanSheet!="" ?
Container(
margin: const EdgeInsets.fromLTRB(15, 20, 15, 0),
width: 80.w,
height: 50.h,
padding: const EdgeInsets.all(1), // Border width
decoration: BoxDecoration(color: Colors.grey, borderRadius: BorderRadius.circular(20)),
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: SizedBox.fromSize(
size: const Size.fromRadius(48), // Image radius
child: Image.network(widget.sessionSubchapter.cleanSheet!, fit: BoxFit.cover),
),
),
) :
Container(
width: 100.w,
height: 14.h,
color: const Color(0xffF3F2F2),
child: InkWell(
onTap: () async {
try {
log(widget.sessionSubchapter.cleanSheetPdf!);
setState(() {
});
}
catch(e) {
log(e.toString());
}
},
child: Container(
margin: EdgeInsets.fromLTRB(5.w, 3.5.h, 5.w, 3.5.h),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10)
),
child:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
margin: const EdgeInsets.fromLTRB(15, 0, 15, 0),
child: Text("Activity Worksheet: Design Your Set", style:
TextStyle(
color: Colors.black,
fontSize: SizerUtil.deviceType ==
DeviceType.mobile ? 16 : 26,
fontWeight: FontWeight.bold,
),),
),
),
Container(
margin: const EdgeInsets.fromLTRB(15, 0, 15, 0),
child: Icon(Icons.insert_drive_file_outlined, size: SizerUtil.deviceType ==
DeviceType.mobile ? 24 : 34,color: Colors.grey,),
)
],
),
),
),
)
],
)),
]
),
),
],
),
),
)
],
),
),
);
}
);
}
}
情况如何:
我想要什么:
我使用 Chewie 插件从这里解决 https://pub.dev/packages/chewie。
videoPlayerController = VideoPlayerController.network(
widget.sessionSubchapter.video!);
videoPlayerController.initialize();
chewieController = ChewieController(
videoPlayerController: videoPlayerController,
autoPlay: true,
looping: true,
);
...
Expanded(
flex: 3,
child: Chewie(
controller: chewieController,
),
),