我正在尝试从图库中获取视频,并希望在网格视图和容器内部显示它们,然后在保存按钮上想要将其上传到 firebase firestore。首先,我无法从图库中获取视频并将其显示在 UI 中。我已经看过很多例子并遵循了它们,但它对我不起作用,因为我对这一切都是新手,无法将它放在一起,它需要放在哪里......请帮助我。提前致谢。虽然完整的代码可能与我的查询相关,也可能不相关,但它可能会帮助那些试图实现相同目标的人。这是具有播放按钮、带指示器的视频长度的完整代码。我想我在这里遗漏了一些东西:-
@override
void initState() {
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
这是我要显示视频的地方:-
Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.all(20),
child:GridView.builder(
itemCount: _video.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context,index){
return Container(
child: _controller.value.isInitialized ?
Stack(
children: [
VideoPlayer(_controller),
_ControlsOverlay(_controller),
],
)
:Container(),
);
}
),
),
这是我打开画廊并选择视频的地方;-
chooseVideo() async {
final pickedVideo = await picker.getVideo(
source: ImageSource.gallery,
maxDuration: const Duration(seconds: 60)
);
setState(() {
_video.add(File(pickedVideo?.path));
_controller = VideoPlayerController.file(File(_video.toString()));
});
if (pickedVideo.path == null) retrieveLostData();
}
Future<void> retrieveLostData() async {
final LostData response = await picker.getLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
setState(() {
_video.add(File(response.file.path));
});
} else {
print(response.file);
}
}
这是完整的代码:-
class AddVideo extends StatefulWidget {
@override
_AddVideo createState() => _AddVideo();
}
class _AddVideo extends State<AddVideo> {
bool uploading = false;
double val = 0;
CollectionReference imgRef;
firebase_storage.Reference ref;
List<File> _video = [];
File videoFile;
List<String> urls = [];
final picker = ImagePicker();
final auth = FirebaseAuth.instance;
final _stoarge = FirebaseStorage.instance;
VideoPlayerController _controller;
@override
void initState() {
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
actions: [
ElevatedButton(
child: Text("SAVE", style: TextStyle(fontSize: 15)),
onPressed: () {
setState(() {
uploading = true;
});
_uploadVideo().whenComplete(() => Navigator.of(context).pop());
},
style: ElevatedButton.styleFrom(
padding: EdgeInsets.fromLTRB(25.0, 15.0, 25.0, 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
),
],
),
body: Container(
child: SafeArea(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
// padding: EdgeInsets.all(20),
child: ElevatedButton(
child: Text("Open Gallery", style: TextStyle(fontSize: 20)),
onPressed: () => !uploading ? chooseVideo() : null,
style: ElevatedButton.styleFrom(
padding: EdgeInsets.fromLTRB(25.0, 15.0, 25.0, 10.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0))),
),
),
Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.all(20),
child:GridView.builder(
itemCount: _video.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context,index){
return Container(
child: _controller.value.isInitialized ?
Stack(
children: [
VideoPlayer(_controller),
_ControlsOverlay(_controller),
],
)
:Container(),
);
}
),
),
uploading ?
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
child: Text(
'uploading...',
style: TextStyle(fontSize: 20),
),
),
SizedBox(
height: 10,
),
CircularProgressIndicator(
value: val,
valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
)
],
)
)
: Container(),
],
),
),
),
),
);
}
chooseVideo() async {
final pickedVideo = await picker.getVideo(
source: ImageSource.gallery,
maxDuration: const Duration(seconds: 60)
);
setState(() {
_video.add(File(pickedVideo?.path));
_controller = VideoPlayerController.file(File(_video.toString()));
});
if (pickedVideo.path == null) retrieveLostData();
}
Future<void> retrieveLostData() async {
final LostData response = await picker.getLostData();
if (response.isEmpty) {
return;
}
if (response.file != null) {
setState(() {
_video.add(File(response.file.path));
});
} else {
print(response.file);
}
}
_uploadVideo() async {
for (var video in _video) {
var _ref = _stoarge.ref().child("videos/" + Path.basename(video.path));
await _ref.putFile(video);
String url = await _ref.getDownloadURL();
print(url);
urls.add(url);
print(url);
}
print("uploading:" + urls.asMap().toString());
await FirebaseFirestore.instance
.collection("users")
.doc(auth.currentUser.uid)
.update({"images": urls});
// .doc(auth.currentUser.uid).update({"images": FieldValue.arrayUnion(urls) });
}
}
class _ControlsOverlay extends StatelessWidget {
String getPosition() {
final duration = Duration(
milliseconds: controller.value.position.inMilliseconds.round());
return [duration.inMinutes, duration.inSeconds]
.map((seg) => seg.remainder(60).toString().padLeft(2, '0'))
.join(':');
}
const _ControlsOverlay(this.controller);
final VideoPlayerController controller;
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
AnimatedSwitcher(
duration: Duration(milliseconds: 50),
reverseDuration: Duration(milliseconds: 200),
child: controller.value.isPlaying
? SizedBox.shrink()
: Container(
color: Colors.black26,
child: Center(
child: Icon(
Icons.play_arrow,
color: Colors.white,
size: 100.0,
),
),
),
),
GestureDetector(
onTap: () {
controller.value.isPlaying ? controller.pause() : controller.play();
},
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Row(
children: [
const SizedBox(width: 8),
Expanded(child: Text(getPosition()),),
const SizedBox(width: 8),
Expanded(child: buildIndicator()),
const SizedBox(width: 8),
],
)
),
],
);
}
Widget buildIndicator() => Container(
margin: EdgeInsets.all(8).copyWith(right: 0),
height: 10,
child: VideoProgressIndicator(
controller, allowScrubbing: true,
),
);
}