
3.gif
Flutter 仿抖音效果 (一) 全屏點(diǎn)愛星
Flutter 仿抖音效果 (二) 界面布局
項(xiàng)目地址:https://github.com/CZXBigBrother/flutter_TikTok 持續(xù)效果更新
實(shí)現(xiàn)抖音視頻播放列表需要解決的問(wèn)題
- 1.視頻播放
- 2.切換時(shí)開始和停止視頻的播放
視頻播放
視頻播放實(shí)際實(shí)現(xiàn)是非常簡(jiǎn)單的只用使用VideoPlayerController就能快速的接入
video_player: ^0.10.1+5
使用到的API
/// finished.
Future<void> play() async {
/// Sets whether or not the video should loop after playing once. See also
/// [VideoPlayerValue.isLooping].
Future<void> setLooping(bool looping) async
/// Pauses the video.
Future<void> pause() async

Snip20200113_2.png
加載完成前,使用第一幀的圖片作為預(yù)留圖,加載完成之后,隱藏預(yù)覽圖,保證短視頻加載緩慢是不會(huì)出現(xiàn)黑屏的情況 ,播放按鍵和預(yù)留圖都通過(guò)stack布局的方式進(jìn)行.
return Stack(
children: <Widget>[
GestureDetector(
child: Stack(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: ScreenService.topSafeHeight),
width: ScreenService.width,
height: h, //h/w = sh/sw
child: VideoPlayer(_controller),
),
getPauseView()
],
),
onTap: () {
if (_controller.value.isPlaying) {
_controller.pause();
_hideActionButton = false;
} else {
_controller.play();
videoPrepared = true;
_hideActionButton = true;
}
setState(() {});
}),
// this.getVideo(),
getPreviewImg(),
getLikesView(),
this.getUserAndTitle()
],
);
上下切換列表
使用Swiper
body: Container(
child: Swiper(
autoStart: false,
circular: false,
direction: Axis.vertical,
children: children,
controller: _controller,
),
color: Colors.black,
),
切換時(shí)開始和停止視頻的播放
添加 SwiperController監(jiān)聽
SwiperController _controller = SwiperController();
初始化時(shí) 我們會(huì)使用
會(huì)標(biāo)記 一個(gè)tag值用來(lái)判斷當(dāng)前隊(duì)列的編號(hào)
然后在當(dāng)滑動(dòng)到某個(gè)視頻時(shí)通知開始播放
_controller.addListener(() {
if (_controller.page.floor() == _controller.page) {
eventBus.emit(keyPlayVideo + _controller.page.floor().toString(),
_controller.page.floor());
}
});
這里會(huì)用到一個(gè)東西就是eventBus.這個(gè)和iOS 的KVO 差不多的意思.添加監(jiān)聽的KEY 然后注冊(cè)接受.內(nèi)部存儲(chǔ)里一個(gè)事件的隊(duì)列.發(fā)送通知是會(huì)執(zhí)行所有的接受者
在視頻controller中注冊(cè)監(jiān)聽eventBus
eventBus.on(keyPlayVideo + widget.positionTag.toString(), (arg) {
if (arg == widget.positionTag) {
_controller.play();
videoPrepared = true;
_hideActionButton = true;
} else {
_controller.pause();
_hideActionButton = false;
}
setState(() {});
});
在dispose的時(shí)候必須移除eventBus 和 等等的Controller,否則會(huì)報(bào)錯(cuò)
@override
void dispose() {
this.scroController.dispose();
this.timer.cancel();
_controller.dispose(); //釋放播放器資源
super.dispose();
}