Reputation: 2034
Can anyone help?
Currently, the Text that I am displaying over a video has a fixed size and position.
I'm wondering how I can change this dynamically/responsively to match the size of its parent widget (the Video).
I tried a method using a GlobalKey
but got an error, I think it's because the video hadn't loaded..
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
NavBar(),
Body(),
Footer(),
],
),
),
),
);
}
}
class Body extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ResponsiveLayout(
largeScreen: LargeScreen(),
mediumScreen: LargeScreen(),
smallScreen: LargeScreen(),
);
}
}
class LargeScreen extends StatefulWidget {
@override
_LargeScreenState createState() => _LargeScreenState();
}
class _LargeScreenState extends State<LargeScreen> {
VideoPlayerController _videoPlayerController;
Future<void> _initializeVideoPlayerFuture;
@override
void initState() {
_videoPlayerController = VideoPlayerController.asset(
'assets/videos/video.mp4',
);
_initializeVideoPlayerFuture = _videoPlayerController.initialize();
super.initState();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: <Widget>[
FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
!_videoPlayerController.value.isBuffering) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the VideoPlayer.
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: Stack(
children: <Widget>[
VideoPlayer(_videoPlayerController),
Positioned(
bottom: 20,
left: 20,
child: FittedBox(
child: Text(
'Text over\na video',
style: TextStyle(
color: Colors.white,
fontSize:50),
),
),
)
],
),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
],
),
);
}
@override
void dispose() {
super.dispose();
_videoPlayerController.dispose();
}
}
Upvotes: 1
Views: 966
Reputation: 7509
LayoutBuilder
can provide you with width
and height
properties which corresponds to the currently available space. Check this documentation here. It provides the builder with a BoxConstraints
instance as in here. You can use this information to size your text.
Check the Align
widget. It can place the child on specific location within the parent widget's coordinate system. In your case it will be on the coordinates of the Stack
widget.
I would try something like the following.
Text
widget inside a Align
widget and use FractionalOffset
to place align the widget. You can directly use the Alignment
instance also. The origin will vary vary for both the approach. Check the docs hereAlign
widget inside a LayoutBuilder
widget to get the available size and decide my font size based on it. Something like fontSize: constraints.maxWidth / 25
Below is sample working code.
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
// drawer: ResponsiveLayout.isSmallScreen(context) ? NavDrawer() : null,
body: Container(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
// NavBar(),
Body(),
// Footer(),
],
),
),
),
);
}
}
class Body extends StatelessWidget {
@override
Widget build(BuildContext context) {
// return ResponsiveLayout(
// largeScreen: LargeScreen(),
// mediumScreen: LargeScreen(),
// smallScreen: LargeScreen(),
// );
return LargeScreen();
}
}
class LargeScreen extends StatefulWidget {
@override
_LargeScreenState createState() => _LargeScreenState();
}
class _LargeScreenState extends State<LargeScreen> {
VideoPlayerController _videoPlayerController;
Future<void> _initializeVideoPlayerFuture;
@override
void initState() {
_videoPlayerController = VideoPlayerController.network(
'http://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_20mb.mp4',
);
_initializeVideoPlayerFuture =
_videoPlayerController.initialize().then((onValue) {
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: <Widget>[
FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
!_videoPlayerController.value.isBuffering) {
// If the VideoPlayerController has finished initialization, use
// the data it provides to limit the aspect ratio of the VideoPlayer.
return AspectRatio(
aspectRatio: _videoPlayerController.value.aspectRatio,
// Use the VideoPlayer widget to display the video.
child: Stack(
children: <Widget>[
VideoPlayer(_videoPlayerController),
LayoutBuilder(
builder: (context, constraints) {
return Align(
// this decides the position of the text.
alignment: FractionalOffset(0.05, 0.95),
child: FittedBox(
child: Text(
'Text over\na video',
style: TextStyle(
color: Colors.white,
// here font size is ratio of the maxwidth available for this widget.
fontSize: constraints.maxWidth / 25,
),
),
),
);
},
)
],
),
);
} else {
// If the VideoPlayerController is still initializing, show a
// loading spinner.
return Center(child: CircularProgressIndicator());
}
},
),
FloatingActionButton(
onPressed: () {
setState(() {
_videoPlayerController.value.isPlaying
? _videoPlayerController.pause()
: _videoPlayerController.play();
});
},
child: Icon(
_videoPlayerController.value.isPlaying
? Icons.pause
: Icons.play_arrow,
),
),
],
),
);
}
@override
void dispose() {
super.dispose();
_videoPlayerController.dispose();
}
}
Upvotes: 1
Reputation: 2236
It's easily accessible via MediaQuery.of(context).size
(Documentation).
Remember that you have to call inside your build method since it demands the context
Upvotes: 0