Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
3a393249
Commit
3a393249
authored
Dec 01, 2017
by
Sigurd Meldgaard
Committed by
Mikkel Nygaard Ravn
Dec 01, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Gallery video demo (#13195)
parent
1bd8ffbc
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
387 additions
and
1 deletion
+387
-1
all.dart
examples/flutter_gallery/lib/demo/all.dart
+1
-0
video_demo.dart
examples/flutter_gallery/lib/demo/video_demo.dart
+376
-0
item.dart
examples/flutter_gallery/lib/gallery/item.dart
+8
-1
pubspec.yaml
examples/flutter_gallery/pubspec.yaml
+2
-0
No files found.
examples/flutter_gallery/lib/demo/all.dart
View file @
3a393249
...
...
@@ -12,3 +12,4 @@ export 'material/material.dart';
export
'pesto_demo.dart'
;
export
'shrine_demo.dart'
;
export
'typography_demo.dart'
;
export
'video_demo.dart'
;
examples/flutter_gallery/lib/demo/video_demo.dart
0 → 100644
View file @
3a393249
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'package:connectivity/connectivity.dart'
;
import
'package:flutter/material.dart'
;
import
'package:video_player/video_player.dart'
;
// TODO(sigurdm): These should not be stored here.
const
String
butterflyUri
=
'https://flutter.github.io/assets-for-api-docs/videos/butterfly.mp4'
;
const
String
beeUri
=
'https://flutter.github.io/assets-for-api-docs/videos/bee.mp4'
;
class
VideoCard
extends
StatelessWidget
{
final
VideoPlayerController
controller
;
final
String
title
;
final
String
subtitle
;
const
VideoCard
({
Key
key
,
this
.
controller
,
this
.
title
,
this
.
subtitle
})
:
super
(
key:
key
);
Widget
_buildInlineVideo
()
{
return
new
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
10.0
,
horizontal:
30.0
),
child:
new
Center
(
child:
new
AspectRatio
(
aspectRatio:
3
/
2
,
child:
new
Hero
(
tag:
controller
,
child:
new
VideoPlayer
(
controller
),
),
),
),
);
}
Widget
_buildFullScreenVideo
()
{
return
new
Scaffold
(
appBar:
new
AppBar
(
title:
new
Text
(
title
),
),
body:
new
Center
(
child:
new
AspectRatio
(
aspectRatio:
3
/
2
,
child:
new
Hero
(
tag:
controller
,
child:
new
VideoPlayPause
(
controller
),
),
),
),
);
}
@override
Widget
build
(
BuildContext
context
)
{
Widget
fullScreenRoutePageBuilder
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
return
new
AnimatedBuilder
(
child:
_buildFullScreenVideo
(),
animation:
animation
,
builder:
(
BuildContext
context
,
Widget
child
)
{
// TODO(sigurdm): It seems we get a animation.value of 1.0
// at first when entering the route. Find out how to avoid
// this.
controller
.
setVolume
(
animation
.
value
);
return
child
;
},
);
}
void
pushFullScreenWidget
()
{
final
TransitionRoute
<
Null
>
route
=
new
PageRouteBuilder
<
Null
>(
settings:
new
RouteSettings
(
name:
title
,
isInitialRoute:
false
),
pageBuilder:
fullScreenRoutePageBuilder
,
);
route
.
completed
.
then
((
Null
_
)
{
controller
.
setVolume
(
0.0
);
});
Navigator
.
of
(
context
).
push
(
route
);
}
return
new
Card
(
child:
new
Column
(
children:
<
Widget
>[
new
ListTile
(
title:
new
Text
(
title
),
subtitle:
new
Text
(
subtitle
)),
new
GestureDetector
(
onTap:
pushFullScreenWidget
,
child:
_buildInlineVideo
(),
),
],
),
);
}
}
class
VideoPlayPause
extends
StatefulWidget
{
final
VideoPlayerController
controller
;
const
VideoPlayPause
(
this
.
controller
);
@override
State
createState
()
=>
new
_VideoPlayPauseState
();
}
class
_VideoPlayPauseState
extends
State
<
VideoPlayPause
>
{
FadeAnimation
imageFadeAnimation
;
VoidCallback
listener
;
_VideoPlayPauseState
()
{
listener
=
()
{
setState
(()
{});
};
}
VideoPlayerController
get
controller
=>
widget
.
controller
;
@override
void
initState
()
{
super
.
initState
();
controller
.
addListener
(
listener
);
}
@override
void
deactivate
()
{
controller
.
removeListener
(
listener
);
super
.
deactivate
();
}
@override
Widget
build
(
BuildContext
context
)
{
final
List
<
Widget
>
children
=
<
Widget
>[
new
GestureDetector
(
child:
new
VideoPlayer
(
controller
),
onTap:
()
{
if
(!
controller
.
value
.
initialized
)
{
return
;
}
if
(
controller
.
value
.
isPlaying
)
{
imageFadeAnimation
=
new
FadeAnimation
(
child:
new
Icon
(
Icons
.
pause
,
size:
100.0
),
);
controller
.
pause
();
}
else
{
imageFadeAnimation
=
new
FadeAnimation
(
child:
new
Icon
(
Icons
.
play_arrow
,
size:
100.0
),
);
controller
.
play
();
}
},
),
new
Center
(
child:
imageFadeAnimation
),
];
if
(!
controller
.
value
.
initialized
)
{
children
.
add
(
new
Container
());
}
return
new
Stack
(
alignment:
Alignment
.
bottomCenter
,
fit:
StackFit
.
passthrough
,
children:
children
,
);
}
}
class
FadeAnimation
extends
StatefulWidget
{
final
Widget
child
;
final
Duration
duration
;
const
FadeAnimation
({
this
.
child
,
this
.
duration
:
const
Duration
(
milliseconds:
500
),
});
@override
_FadeAnimationState
createState
()
=>
new
_FadeAnimationState
();
}
class
_FadeAnimationState
extends
State
<
FadeAnimation
>
with
SingleTickerProviderStateMixin
{
AnimationController
animationController
;
@override
void
initState
()
{
super
.
initState
();
animationController
=
new
AnimationController
(
duration:
widget
.
duration
,
vsync:
this
,
);
animationController
.
addListener
(()
{
if
(
mounted
)
{
setState
(()
{});
}
});
animationController
.
forward
(
from:
0.0
);
}
@override
void
deactivate
()
{
animationController
.
stop
();
super
.
deactivate
();
}
@override
void
didUpdateWidget
(
FadeAnimation
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
if
(
oldWidget
.
child
!=
widget
.
child
)
{
animationController
.
forward
(
from:
0.0
);
}
}
@override
void
dispose
()
{
animationController
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
animationController
.
isAnimating
?
new
Opacity
(
opacity:
1.0
-
animationController
.
value
,
child:
widget
.
child
,
)
:
new
Container
();
}
}
class
ConnectivityOverlay
extends
StatefulWidget
{
final
Widget
child
;
final
Completer
<
Null
>
connectedCompleter
;
final
GlobalKey
<
ScaffoldState
>
scaffoldKey
;
const
ConnectivityOverlay
({
this
.
child
,
this
.
connectedCompleter
,
this
.
scaffoldKey
,
});
@override
_ConnectivityOverlayState
createState
()
=>
new
_ConnectivityOverlayState
();
}
class
_ConnectivityOverlayState
extends
State
<
ConnectivityOverlay
>
{
StreamSubscription
<
ConnectivityResult
>
connectivitySubscription
;
bool
connected
=
true
;
static
const
Widget
errorSnackBar
=
const
SnackBar
(
backgroundColor:
Colors
.
red
,
content:
const
ListTile
(
title:
const
Text
(
'No network'
),
subtitle:
const
Text
(
'To load the videos you must have an active network connection'
,
),
),
);
Stream
<
ConnectivityResult
>
connectivityStream
()
async
*
{
final
Connectivity
connectivity
=
new
Connectivity
();
ConnectivityResult
previousResult
=
await
connectivity
.
checkConnectivity
();
yield
previousResult
;
await
for
(
ConnectivityResult
result
in
connectivity
.
onConnectivityChanged
)
{
if
(
result
!=
previousResult
)
{
yield
result
;
previousResult
=
result
;
}
}
}
@override
void
initState
()
{
super
.
initState
();
connectivitySubscription
=
connectivityStream
().
listen
(
(
ConnectivityResult
connectivityResult
)
{
if
(!
mounted
)
{
return
;
}
if
(
connectivityResult
==
ConnectivityResult
.
none
)
{
widget
.
scaffoldKey
.
currentState
.
showSnackBar
(
errorSnackBar
);
}
else
{
if
(!
widget
.
connectedCompleter
.
isCompleted
)
{
widget
.
connectedCompleter
.
complete
(
null
);
}
}
},
);
}
@override
void
dispose
()
{
connectivitySubscription
.
cancel
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
=>
widget
.
child
;
}
class
VideoDemo
extends
StatefulWidget
{
const
VideoDemo
({
Key
key
})
:
super
(
key:
key
);
static
const
String
routeName
=
'/video'
;
@override
_VideoDemoState
createState
()
=>
new
_VideoDemoState
();
}
class
_VideoDemoState
extends
State
<
VideoDemo
>
with
SingleTickerProviderStateMixin
{
final
VideoPlayerController
butterflyController
=
new
VideoPlayerController
(
butterflyUri
,
);
final
VideoPlayerController
beeController
=
new
VideoPlayerController
(
beeUri
,
);
final
GlobalKey
<
ScaffoldState
>
scaffoldKey
=
new
GlobalKey
<
ScaffoldState
>();
final
Completer
<
Null
>
connectedCompleter
=
new
Completer
<
Null
>();
@override
void
initState
()
{
super
.
initState
();
Future
<
Null
>
initController
(
VideoPlayerController
controller
)
async
{
controller
.
setLooping
(
true
);
controller
.
setVolume
(
0.0
);
controller
.
play
();
await
connectedCompleter
.
future
;
await
controller
.
initialize
();
setState
(()
{});
}
initController
(
butterflyController
);
initController
(
beeController
);
}
@override
void
dispose
()
{
butterflyController
.
dispose
();
beeController
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
Scaffold
(
key:
scaffoldKey
,
appBar:
new
AppBar
(
title:
const
Text
(
'Videos'
),
),
body:
new
ConnectivityOverlay
(
child:
new
ListView
(
children:
<
Widget
>[
new
VideoCard
(
title:
'Butterfly'
,
subtitle:
'… flutters by'
,
controller:
butterflyController
,
),
new
VideoCard
(
title:
'Bee'
,
subtitle:
'… gently buzzing'
,
controller:
beeController
,
),
],
),
connectedCompleter:
connectedCompleter
,
scaffoldKey:
scaffoldKey
,
),
);
}
}
examples/flutter_gallery/lib/gallery/item.dart
View file @
3a393249
...
...
@@ -54,7 +54,7 @@ List<GalleryItem> _buildGalleryItems() {
// Demos
new
GalleryItem
(
title:
'Shrine'
,
subtitle:
'Basic shopping app'
,
subtitle:
'Basic shopping app'
,
category:
'Demos'
,
routeName:
ShrineDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
new
ShrineDemo
(),
...
...
@@ -73,6 +73,13 @@ List<GalleryItem> _buildGalleryItems() {
routeName:
AnimationDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
const
AnimationDemo
(),
),
new
GalleryItem
(
title:
'Video'
,
subtitle:
'Video playback'
,
category:
'Demos'
,
routeName:
VideoDemo
.
routeName
,
buildRoute:
(
BuildContext
context
)
=>
const
VideoDemo
(),
),
// Material Components
new
GalleryItem
(
title:
'Bottom navigation'
,
...
...
examples/flutter_gallery/pubspec.yaml
View file @
3a393249
...
...
@@ -4,9 +4,11 @@ dependencies:
sdk
:
flutter
collection
:
1.14.3
intl
:
0.15.2
connectivity
:
0.1.0
string_scanner
:
1.0.2
url_launcher
:
0.4.2+5
cupertino_icons
:
0.1.1
video_player
:
0.0.5
# Also update dev/benchmarks/complex_layout/pubspec.yaml
flutter_gallery_assets
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment