Flutter 轮子:视频广告倒计时页
用不了多久,你就会和我一样明白,每个人都要经历属于自我的起起落落,我们的那些孤独、彷徨、失落,无人能懂,但人人都会体验,那些最初无法忍受的情绪,不必深究不用纪念,真正需要铭记的,是身边陪伴你的人事,是爱。
先来看看今天要完成的效果吧:
效果图(1.1)
:
分析:
- 背景视屏动画
- 右上角白色框圆角倒计时
- 当按钮为0时完成跳转页面
- 当点击按钮时完成跳转页面
仿照的是视频动画广告页,视频为KFC广告
背景视频
官方例子:
import 'package:video_player/video_player.dart';
import 'package:flutter/material.dart';
void main() => runApp(VideoApp());
class VideoApp extends StatefulWidget {
@override
_VideoAppState createState() => _VideoAppState();
}
class _VideoAppState extends State<VideoApp> {
VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller = VideoPlayerController.network(
'https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4')
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Demo',
home: Scaffold(
body: Center(
child: _controller.value.initialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
}
可以看出:
- VideoPlayerController.network()是加载的网络视频
- VideoPlayerController.asset()是加载的本地视频
通过控制器参数可以控制视屏是否播放:
- _controller.pause() 暂停动画
- _controller.play() 开始动画
官方效果图:效果图(1.2)
:
效果图(1.2)
:
官方使用的是网络视频,一般视频广告页都是用的本地视频
咋们稍微修改一下代码,使用本地视频:
创建assets文件夹,并创建video文件夹,吧咋们准备好的视频放到里面并在pubspec.xml中声明;
pubspec.xml:
assets:
- assets/video/
VideoPlayerWidget:
import 'package:flutter/material.dart';
import 'package:flutter_trip/tests/video_page_widget.dart';
import 'package:video_player/video_player.dart';
class VideoPlayerWidget extends StatefulWidget {
String url;
///VideoPageEnum.asset 本地视屏 默认
/// VideoPageEnum.network 网络视频
VideoPageEnum type;
VideoPlayerWidget({@required this.url, this.type = VideoPageEnum.asset});
@override
_VideoPlayerWidgetState createState() => _VideoPlayerWidgetState();
}
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
VideoPlayerController _controller;
@override
void initState() {
super.initState();
_controller =
widget.type == VideoPageEnum.asset
? VideoPlayerController.asset(widget.url)
: VideoPlayerController.network(widget.url)
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
//开始视频
_controller.play();
}
@override
Widget build(BuildContext context) {
return SizedBox(
//占满全屏
width: double.infinity,
height: double.infinity,
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
));
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
}
这个页面有2个参数;
- url 本地路径或者网络路径(必传参数)
- type:视屏类型(默认是本地)
- VideoPageEnum.asset 本地视屏
- VideoPageEnum.network 网络视频
因为视频和倒计时是同一个页面,所以咋们创建一个Widget来调用他:
VideoPageWidget 页面:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_trip/tests/video_player_text.dart';
import 'package:flutter_trip/util/log_util.dart';
import 'package:flutter_trip/util/navigator_util.dart';
import 'package:flutter_trip/util/toast.dart';
class VideoPageWidget extends StatefulWidget {
String url;
int time; //默认5s
///VideoPageEnum.asset 本地视屏
/// VideoPageEnum.network 网络视频
VideoPageEnum type;
Widget widget;
/// [url] 路径地址
/// [time] 倒计时时间
/// [type] VideoPageEnum.asset本地视频(默认) VideoPageEnum.network 网络视频
/// [widget] 要跳转的页面
VideoPageWidget({
@required this.url,
this.time = 5,
this.type = VideoPageEnum.asset,
@required this.widget,
});
@override
_VideoPageWidgetState createState() => _VideoPageWidgetState();
}
class _VideoPageWidgetState extends State<VideoPageWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
//视屏播放
VideoPlayerWidget(url: widget.url, type: widget.type),
//右上角跳转
Positioned(...),
],
),
);
}
}
enum VideoPageEnum {
//本地视频 通过assets下的video引用
asset,
// 网络 视频
network
}
参数介绍:
- [url] 路径地址(必传参数)
- [time] 倒计时时间(默认5s)
- [type] 视频类型(默认本地视频)
- VideoPageEnum.asset本地视频
- VideoPageEnum.network 网络视频
- [widget] 要跳转的页面(必传参数)
效果图(1.3)
:
倒计时
倒计时可点击布局:
Positioned(
child: GestureDetector(
onTap: () {
goHome();
}, // 倒计时按钮布局
child: buildContainer(context)),
right: 20,
top: 40,
),
//倒计时按钮布局
Widget buildContainer(BuildContext context) {
return Container(
width: 100,
height: 30,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 2,
),
borderRadius: BorderRadius.all(Radius.circular(15))),
alignment: Alignment.center,
child: Text(
'${widget.time}s',
style: TextStyle(color: Colors.white, fontSize: 16),
),
);
}
//跳转到Home页面
//NavigatorUtil使用的是工具类
void goHome() {
NavigatorUtil.pushColsePage(
context: context,
widget: widget.widget,
);
}
这段代码还是比较简单的,这里要说的就是
- widget.widget 要跳转的页面
- widget.time 倒计时时间
在State中widget.
属性就是和State绑定的Widget
class VideoPageWidget extends StatefulWidget {
String url;
int time; //默认5s
///VideoPageEnum.asset 本地视屏
/// VideoPageEnum.network 网络视频
VideoPageEnum type;
Widget widget;
VideoPageWidget({
@required this.url,
this.time = 5,
this.type = VideoPageEnum.asset,
@required this.widget,
});
@override
_VideoPageWidgetState createState() => _VideoPageWidgetState();
}
class _VideoPageWidgetState extends State<VideoPageWidget> {
........
}
这里State绑定的是VideoPageWidget
所以widget.
就是.
的VideoPageWidget中的属性
效果图(1.4)
:
Timer倒计时效果
Timer _timer;
@override
void initState() {
super.initState();
//1s执行一下
_timer = Timer.periodic(new Duration(seconds: 1), (value) {
if (widget.time == 1) {
//关闭
_timer.cancel();
goHome();
}
widget.time--;
setState(() {});
print("time: ${widget.time}");
});
}
@override
void dispose() {
//计时器是否是活动状态
if (_timer.isActive) {
_timer.cancel();
}
super.dispose();
}
分析:
Timer.periodic(new Duration(seconds: 1), (value) {}
通过这个方法来来1s执行一下,当执行到
if (widget.time == 1) {
_timer.cancel();
}
widget.time == 1时,让_timer停止,并每次刷新数据,完成数据的倒计时效果
切记,一定要在销毁时销毁Timer哦
@override
void dispose() {
//计时器是否是活动状态
if (_timer.isActive) {
_timer.cancel();
}
super.dispose();
}
猜你喜欢:
原创不易,您的点赞就是对我最大的支持,留下您的点赞吧~
下面是我的公众号,平时会发一些andorid和 flutter 的小知识等,主要用来记录工作开发中的一些小知识,有喜欢的朋友可以扫描二维码咋们互相进步~