I'm new to flutter and I'm using flutter video_player plugin to play videos. After I capture a video file (using camera plugin), I'd like to start video playback 1 second into the video (essentially to skip the first second). I tried using .seekTo and passed it a Duration but it returned the following error:
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The getter '_duration' was called on null.
Receiver: null
Tried calling: _duration
The API reference seemed straightforward enough but it's not like Duration. Here's my code and thanks in advance!
Future<void> _startVideoPlayer() async {
videoPlayerController = VideoPlayerController.file(File(videoPath));
videoPlayerController.setVolume(1.0);
videoPlayerController.setLooping(true);
videoPlayerController.seekTo(Duration(seconds: 1));
await videoPlayerController.initialize();
await videoPlayerController.play();
}
You need to initialize first then do seekTo and play
code snippet
_videoPlayerController1..initialize().then((_){
setState(() {
_videoPlayerController1.seekTo(Duration(seconds: 3));
_videoPlayerController1.play();
});
});
demo skip 3 seconds
full code
import 'package:chewie/chewie.dart';
import 'package:chewie/src/chewie_player.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: ChewieDemo(title: 'Flutter Demo Home Page'),
);
}
}
class ChewieDemo extends StatefulWidget {
ChewieDemo({this.title = 'Chewie Demo'});
final String title;
#override
State<StatefulWidget> createState() {
return _ChewieDemoState();
}
}
class _ChewieDemoState extends State<ChewieDemo> {
TargetPlatform _platform;
VideoPlayerController _videoPlayerController1;
VideoPlayerController _videoPlayerController2;
ChewieController _chewieController;
#override
void initState() {
super.initState();
_videoPlayerController1 = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4');
_videoPlayerController2 = VideoPlayerController.asset(
'assets/videos/sample.mp4');
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: false,
looping: true,
// Try playing around with some of these other options:
// showControls: false,
// materialProgressColors: ChewieProgressColors(
// playedColor: Colors.red,
// handleColor: Colors.blue,
// backgroundColor: Colors.grey,
// bufferedColor: Colors.lightGreen,
// ),
// placeholder: Container(
// color: Colors.grey,
// ),
// autoInitialize: true,
);
}
#override
void dispose() {
_videoPlayerController1.dispose();
_videoPlayerController2.dispose();
_chewieController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: widget.title,
theme: ThemeData.light().copyWith(
platform: _platform ?? Theme.of(context).platform,
),
home: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: Chewie(
controller: _chewieController,
),
),
),
FlatButton(
onPressed: () {
_chewieController.enterFullScreen();
},
child: Text('Fullscreen'),
),
Row(
children: <Widget>[
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_chewieController.dispose();
/*_videoPlayerController2.pause();
_videoPlayerController2.seekTo(Duration(seconds: 0));*/
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: false,
looping: true,
);
_videoPlayerController1..initialize().then((_){
setState(() {
_videoPlayerController1.seekTo(Duration(seconds: 3));
_videoPlayerController1.play();
});
});
});
},
child: Padding(
child: Text("Seek To"),
padding: EdgeInsets.symmetric(vertical: 16.0),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_chewieController.dispose();
_videoPlayerController2.pause();
_videoPlayerController2.seekTo(Duration(seconds: 0));
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
);
});
},
child: Padding(
child: Text("Video 1"),
padding: EdgeInsets.symmetric(vertical: 16.0),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_chewieController.dispose();
_videoPlayerController1.pause();
_videoPlayerController1.seekTo(Duration(seconds: 0));
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController2,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
);
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Text("Video 2"),
),
),
)
],
),
Row(
children: <Widget>[
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_platform = TargetPlatform.android;
});
},
child: Padding(
child: Text("Android controls"),
padding: EdgeInsets.symmetric(vertical: 16.0),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_platform = TargetPlatform.iOS;
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Text("iOS controls"),
),
),
)
],
)
],
),
),
);
}
}
Related
I am working on a large-scale project and integrating video calls into it. So I made a separate project just for practice and I achieved good results. The group calling worked perfectly on both android and IOS. But then I integrated the same code in my large-scale project which uses firebase as a backend and when I navigate to the video screen it gives me an error saying "Unhandled Exception: LateInitializationError: Field 'requestPort' has not been initialized". The Agora console is on Testing for now and the channel wasn't expired just in case you guys are wondering. As I said it works perfectly in a separate project.
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
class VideoCallPage extends StatefulWidget {
const VideoCallPage({Key? key}) : super(key: key);
#override
VideoCallPageState createState() => VideoCallPageState();
}
class VideoCallPageState extends State<VideoCallPage> {
static final _users = <int>[];
Logger logger = Logger();
bool muted = false;
late RtcEngine _engine;
bool isRigning = true;
bool isSpeakerOn = true;
final String channelName = 'video';
final String appID = 'xxx';
final String tokenAudio ='xxx';
#override
void dispose() {
_dispose();
super.dispose();
}
Future<void> _dispose() async {
_users.clear();
await _engine.leaveChannel();
await _engine.stopPreview();
await _engine.release();
}
#override
void initState() {
super.initState();
// initialize agora sdk
initialize();
}
Future<void> initialize() async {
logger.i('Initialize');
if (appID.isEmpty) {
setState(() {
logger.e(
'APP_ID missing, please provide your APP_ID in settings.dart',
);
logger.e('Agora Engine is not starting');
});
return;
}
await _initAgoraRtcEngine();
_addAgoraEventHandlers();
onOffSpeaker();
await _engine.joinChannel(
token: tokenAudio,
channelId: channelName,
uid: 0,
options: const ChannelMediaOptions(
channelProfile: ChannelProfileType.channelProfileCommunication,
clientRoleType: ClientRoleType.clientRoleBroadcaster));
}
Future<void> _initAgoraRtcEngine() async {
logger.i('_initAgoraRtcEngine');
//create the engine
_engine = createAgoraRtcEngine();
logger.i('RtcEngineContext');
await _engine.initialize(RtcEngineContext(
appId: appID,
));
logger.i('enablbing video');
await _engine.enableVideo();
// await _engine.setVideoEncoderConfiguration(
// const VideoEncoderConfiguration(
// dimensions: VideoDimensions(width: 640, height: 360),
// frameRate: 15,
// bitrate: 0,
// ),
// );
await _engine.startPreview();
}
void _addAgoraEventHandlers() {
_engine.registerEventHandler(RtcEngineEventHandler(
onError: (ErrorCodeType errorCodeType, String value) {
if (mounted) {
setState(() {
final info = 'onError: ${errorCodeType.name}';
logger.e(info);
});
}
},
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
setState(() {
final info =
'onJoinChannel: ${connection.channelId}, uid: ${connection.localUid}';
logger.i(info);
});
},
onLeaveChannel: (RtcConnection rtcConnection, RtcStats rtcStats) {
setState(() {
logger.i('onLeaveChannel');
_users.clear();
});
},
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
setState(() {
isRigning = false;
final info = 'remoteUserJoined: $remoteUid';
logger.i(info);
_users.add(remoteUid);
});
},
onUserOffline: (RtcConnection connection, int remoteUid,
UserOfflineReasonType reason) {
setState(() {
final info =
'remoteUserOffline: $remoteUid , reason: ${reason.index}';
logger.i(info);
_users.remove(remoteUid);
});
},
onFirstRemoteVideoFrame: (connection, uid, width, height, elapsed) {
setState(() {
final info = 'firstRemoteVideoFrame: $uid';
logger.i(info);
});
},
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Agora Group Video Calling'),
),
backgroundColor: Colors.black,
body: Center(
child: Stack(
children: <Widget>[
Opacity(
opacity: isRigning ? 0.2 : 1,
child: _viewRows(),
),
_toolbar(),
if (isRigning)
Positioned(
top: 100,
left: MediaQuery.of(context).size.width * 0.3,
right: MediaQuery.of(context).size.width * 0.3,
child: Center(
child: Text(
'Ringing...',
style: TextStyle(color: Colors.white, fontSize: 30),
),
))
],
),
),
);
}
/// Helper function to get list of native views
List<Widget> _getRenderViews() {
final List<StatefulWidget> list = [];
list.add(AgoraVideoView(
controller: VideoViewController(
rtcEngine: _engine,
canvas: const VideoCanvas(uid: 0),
)));
_users.forEach((int uid) => list.add(AgoraVideoView(
controller: VideoViewController.remote(
rtcEngine: _engine,
canvas: VideoCanvas(uid: uid),
connection: RtcConnection(channelId: channelName),
),
)));
return list;
}
/// Video view wrapper
Widget _videoView(view) {
return Expanded(child: Container(child: view));
}
/// Video view row wrapper
Widget _expandedVideoRow(List<Widget> views) {
final wrappedViews = views.map<Widget>(_videoView).toList();
return Expanded(
child: Row(
children: wrappedViews,
),
);
}
Widget _viewRows() {
final views = _getRenderViews();
switch (views.length) {
case 1:
return Container(
child: Column(
children: <Widget>[_videoView(views[0])],
));
case 2:
return Container(
child: Column(
children: <Widget>[
_expandedVideoRow([views[0]]),
_expandedVideoRow([views[1]])
],
));
case 3:
return Container(
child: Column(
children: <Widget>[
_expandedVideoRow(views.sublist(0, 2)),
_expandedVideoRow(views.sublist(2, 3))
],
));
case 4:
return Container(
child: Column(
children: <Widget>[
_expandedVideoRow(views.sublist(0, 2)),
_expandedVideoRow(views.sublist(2, 4))
],
));
default:
}
return Container();
}
Widget _toolbar() {
return Container(
alignment: Alignment.bottomCenter,
padding: const EdgeInsets.symmetric(vertical: 48),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RawMaterialButton(
onPressed: onOffSpeaker,
child: Icon(
isSpeakerOn ? Icons.volume_up_sharp : Icons.volume_off,
color: isSpeakerOn ? Colors.white : Colors.blueAccent,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: isSpeakerOn ? Colors.blueAccent : Colors.white,
padding: const EdgeInsets.all(12.0),
),
RawMaterialButton(
onPressed: _onToggleMute,
child: Icon(
muted ? Icons.mic_off : Icons.mic,
color: muted ? Colors.white : Colors.blueAccent,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: muted ? Colors.blueAccent : Colors.white,
padding: const EdgeInsets.all(12.0),
),
RawMaterialButton(
onPressed: () => _onCallEnd(context),
child: Icon(
Icons.call_end,
color: Colors.white,
size: 35.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.redAccent,
padding: const EdgeInsets.all(15.0),
),
RawMaterialButton(
onPressed: _onSwitchCamera,
child: Icon(
Icons.switch_camera,
color: Colors.blueAccent,
size: 20.0,
),
shape: CircleBorder(),
elevation: 2.0,
fillColor: Colors.white,
padding: const EdgeInsets.all(12.0),
)
],
),
);
}
void _onToggleMute() {
setState(() {
muted = !muted;
});
_engine.muteLocalAudioStream(muted);
}
void _onCallEnd(BuildContext context) {
Navigator.pop(context);
}
void _onSwitchCamera() {
_engine.switchCamera();
}
Future onOffSpeaker() async {
setState(() {
isSpeakerOn = !isSpeakerOn;
});
await _engine.setEnableSpeakerphone(isSpeakerOn);
}
}
I used Logger package to view logs and I found out the error occurs in this piece of code
await _engine.initialize(RtcEngineContext(
appId: appID,
));
The app uses agora_rtc_engine: ^6.1.0 and defined in pubspec.yaml file
In Agora SDK, there must be a late field requestPort which is accessed before the initialization.
It seems already similar issue raised in Agora SDK github repo. But its closed.
You can open a new issue or reopen existing with steps to reproduce the issue.
I am new to Flutter, i want to built an app that can control the Screen Brightness using flutter, i found a Plugin in screen 0.0.5 it is working , it can effect the screen brightness.
I am using Screen Plugin you can check it.
But My Problem is that when i hide the Application then the Brightness Set by my App is overwritten by Mobile's default Brightness?
How it is possible to full control the phone brightness?
code
import 'package:flutter/material.dart';
import 'package:screen/screen.dart';
void main() => runApp(MaterialApp(
theme: ThemeData(primarySwatch: Colors.red, brightness: Brightness.dark),
themeMode: ThemeMode.dark,
darkTheme: ThemeData(brightness: Brightness.dark),
debugShowCheckedModeBanner: false,
home: ScreenBrightness()));
//ManageScreenDemoState pageState;
class ScreenBrightness extends StatefulWidget {
#override
_ScreenBrightnessState createState() => _ScreenBrightnessState();
}
class _ScreenBrightnessState extends State<ScreenBrightness> {
#override
double _brightness;
bool _enableKeptOn;
#override
void initState() {
super.initState();
getBrightness();
getIsKeptOnScreen();
}
void getBrightness() async {
double value = await Screen.brightness;
setState(() {
_brightness = double.parse(value.toStringAsFixed(1));
});
}
void getIsKeptOnScreen() async {
bool value = await Screen.isKeptOn;
setState(() {
_enableKeptOn = value;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Screen Brightness")),
body: Column(
children: <Widget>[
// Notice
Container(
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.all(10),
alignment: Alignment(0, 0),
height: 50,
decoration: BoxDecoration(color: Colors.orange),
child: Text(
"Do this example on a Real Phone, not an Emulator.",
style: TextStyle(color: Colors.white),
),
),
// Brightness Settings
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Brightness:"),
(_brightness == null)
? CircularProgressIndicator(
backgroundColor: Colors.grey,
)
: Slider(
activeColor: Colors.grey,
value: _brightness,
min: 0,
max: 1.0,
divisions: 20,
onChanged: (newValue) {
setState(() {
_brightness = newValue;
});
// set screen's brightness
Screen.setBrightness(_brightness);
},
),
Text((_brightness * 100).toStringAsFixed(1) + "%"),
],
),
),
// Kept-On Settings
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Kept on Screen:"),
Text(_enableKeptOn.toString()),
(_enableKeptOn == null)
? CircularProgressIndicator(
backgroundColor: Colors.blue,
)
: Switch(
activeColor: Colors.grey,
value: _enableKeptOn,
onChanged: (flag) {
Screen.keepOn(flag);
getIsKeptOnScreen();
},
)
],
),
)
],
),
);
}
}
Image
Try it:
MaterialApp(
theme: ThemeData.dark(),
)
Also check :
how to implement dark mode in flutter
I have a video in my assets folder, and when I am trying the code, it is giving some exceptions. Can anyone help me?
class VideoExample extends StatefulWidget {
#override
VideoState createState() => VideoState();
}
class VideoState extends State<VideoExample> {
VideoPlayerController playerController;
VoidCallback listener;
#override
void initState() {
super.initState();
listener = () {
setState(() {});
};
}
void createVideo() {
if (playerController == null) {
playerController = VideoPlayerController.asset("assets/videos/video.mp4")
..addListener(listener)
..setVolume(1.0)
..initialize();
}
}
#override
void deactivate() {
playerController.setVolume(0.0);
playerController.removeListener(listener);
super.deactivate();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Video'),
),
body: Center(
child: AspectRatio(
aspectRatio: 16 / 9,
child: Container(
child: (playerController != null
? VideoPlayer(
playerController,
)
: Container()),
))),
floatingActionButton: FloatingActionButton(
onPressed: () {
createVideo();
playerController.play();
},
child: Icon(Icons.play_arrow),
),
);
}
}
I just want that the video should run in the full screen with landscape mode.
I had imported every essential package and changed the pubspec.yaml file.
It is playing the video but not playing it in full-screen landscape mode.
You can copy paste run full code below
You can use package https://pub.dev/packages/chewie and https://pub.dev/packages/auto_orientation
You can enter full screen mode with _chewieController.enterFullScreen()
code snippet
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
routePageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondAnimation, provider) {
return AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
return VideoScaffold(
child: Scaffold(
resizeToAvoidBottomPadding: false,
body: Container(
alignment: Alignment.center,
color: Colors.black,
child: provider,
),
),
);
},
);
}
FlatButton(
onPressed: () {
_chewieController.enterFullScreen();
},
child: Text('Fullscreen'),
),
working demo
full code
import 'package:auto_orientation/auto_orientation.dart';
import 'package:chewie/chewie.dart';
import 'package:chewie/src/chewie_player.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(
ChewieDemo(),
);
}
class ChewieDemo extends StatefulWidget {
ChewieDemo({this.title = 'Chewie Demo'});
final String title;
#override
State<StatefulWidget> createState() {
return _ChewieDemoState();
}
}
class _ChewieDemoState extends State<ChewieDemo> {
TargetPlatform _platform;
VideoPlayerController _videoPlayerController1;
VideoPlayerController _videoPlayerController2;
ChewieController _chewieController;
#override
void initState() {
super.initState();
_videoPlayerController1 = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4');
_videoPlayerController2 = VideoPlayerController.network(
'https://www.sample-videos.com/video123/mp4/480/big_buck_bunny_480p_20mb.mp4');
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
routePageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondAnimation, provider) {
return AnimatedBuilder(
animation: animation,
builder: (BuildContext context, Widget child) {
return VideoScaffold(
child: Scaffold(
resizeToAvoidBottomPadding: false,
body: Container(
alignment: Alignment.center,
color: Colors.black,
child: provider,
),
),
);
},
);
}
// Try playing around with some of these other options:
// showControls: false,
// materialProgressColors: ChewieProgressColors(
// playedColor: Colors.red,
// handleColor: Colors.blue,
// backgroundColor: Colors.grey,
// bufferedColor: Colors.lightGreen,
// ),
// placeholder: Container(
// color: Colors.grey,
// ),
// autoInitialize: true,
);
}
#override
void dispose() {
_videoPlayerController1.dispose();
_videoPlayerController2.dispose();
_chewieController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: widget.title,
theme: ThemeData.light().copyWith(
platform: _platform ?? Theme.of(context).platform,
),
home: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: Chewie(
controller: _chewieController,
),
),
),
FlatButton(
onPressed: () {
_chewieController.enterFullScreen();
},
child: Text('Fullscreen'),
),
Row(
children: <Widget>[
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_chewieController.dispose();
_videoPlayerController2.pause();
_videoPlayerController2.seekTo(Duration(seconds: 0));
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController1,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
);
});
},
child: Padding(
child: Text("Video 1"),
padding: EdgeInsets.symmetric(vertical: 16.0),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_chewieController.dispose();
_videoPlayerController1.pause();
_videoPlayerController1.seekTo(Duration(seconds: 0));
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController2,
aspectRatio: 3 / 2,
autoPlay: true,
looping: true,
);
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Text("Video 2"),
),
),
)
],
),
Row(
children: <Widget>[
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_platform = TargetPlatform.android;
});
},
child: Padding(
child: Text("Android controls"),
padding: EdgeInsets.symmetric(vertical: 16.0),
),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
_platform = TargetPlatform.iOS;
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Text("iOS controls"),
),
),
)
],
)
],
),
),
);
}
}
class VideoScaffold extends StatefulWidget {
const VideoScaffold({Key key, this.child}) : super(key: key);
final Widget child;
#override
State<StatefulWidget> createState() => _VideoScaffoldState();
}
class _VideoScaffoldState extends State<VideoScaffold> {
#override
void initState() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
]);
AutoOrientation.landscapeAutoMode();
super.initState();
}
#override
dispose() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
AutoOrientation.portraitAutoMode();
super.dispose();
}
#override
Widget build(BuildContext context) {
return widget.child;
}
}
i have setup banner ads in flutter and those are overlapping the bottom navigation bar
I want to display ads below that bottom navigation bar,
is there any way that i can add a margin below the bottom navigation bar ?
i have implemented ads in home.dart (mainpage)
import 'package:provider/provider.dart';
import '../../ui/widgets/bottom_nav_bar.dart';
import '../../core/utils/theme.dart';
import 'search_page.dart';
import 'category.dart';
import 'main_page.dart';
import 'settings.dart';
import 'package:flutter/material.dart';
import 'package:firebase_admob/firebase_admob.dart';
import 'for_you.dart';
const String AD_MOB_APP_ID = 'ca-app-pub-3940256099942544~3347511713';
const String AD_MOB_TEST_DEVICE = 'DEC3010B2445165B43EB949F5D97D0F8 - run ad then check device logs for value';
const String AD_MOB_AD_ID = 'ca-app-pub-3940256099942544/6300978111';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
BannerAd _bannerAd;
static final MobileAdTargetingInfo targetingInfo = new MobileAdTargetingInfo(
testDevices: <String>[AD_MOB_TEST_DEVICE],
);
BannerAd createBannerAd() {
return new BannerAd(
adUnitId: AD_MOB_AD_ID,
size: AdSize.banner,
targetingInfo: targetingInfo,
);
}
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
int _selectedIndex = 0;
final PageController _pageController = PageController();
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
_pageController.dispose();
}
#override
Widget build(BuildContext context) {
final stateData = Provider.of<ThemeNotifier>(context);
final ThemeData state = stateData.getTheme();
FirebaseAdMob.instance.initialize(appId: AD_MOB_APP_ID);
_bannerAd = createBannerAd()..load()..show();
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
centerTitle: false,
backgroundColor: state.primaryColor,
elevation: 0,
title: Text(
'RevWalls',
style: state.textTheme.headline,
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.search,
color: state.textTheme.body1.color,
),
onPressed: () => showSearch(
context: context, delegate: WallpaperSearch(themeData: state)),
)
],
),
body: Container(
color: state.primaryColor,
child: PageView(
controller: _pageController,
physics: BouncingScrollPhysics(),
onPageChanged: (index) {
setState(() {
_selectedIndex = index;
});
},
children: <Widget>[
MainBody(),
Category(),
ForYou(),
SettingsPage(),
],
),
),
bottomNavigationBar: BottomNavyBar(
selectedIndex: _selectedIndex,
unselectedColor: state.textTheme.body1.color,
onItemSelected: (index) {
_pageController.jumpToPage(index);
},
selectedColor: state.accentColor,
backgroundColor: state.primaryColor,
showElevation: false,
items: [
BottomNavyBarItem(
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavyBarItem(
icon: Icon(Icons.category),
title: Text('Subreddits'),
),
BottomNavyBarItem(
icon: Icon(Icons.phone_android),
title: Text('Exact Fit'),
),
BottomNavyBarItem(
icon: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
);
}
Widget oldBody(ThemeData state) {
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool boxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: state.primaryColor,
elevation: 4,
title: Text(
'reWalls',
style: state.textTheme.headline,
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search, color: state.accentColor),
onPressed: () {
showSearch(
context: context,
delegate: WallpaperSearch(themeData: state));
},
)
],
floating: true,
pinned: _selectedIndex == 0 ? false : true,
snap: false,
centerTitle: false,
),
];
},
body: Container(
color: state.primaryColor,
child: PageView(
controller: _pageController,
onPageChanged: (index) {
setState(() {
_selectedIndex = index;
});
},
children: <Widget>[
MainBody(),
Category(),
ForYou(),
SettingsPage(),
],
),
),
);
}
}
and here is the bottom navigation bar -
library bottom_navy_bar;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class BottomNavyBar extends StatelessWidget {
final int selectedIndex;
final double iconSize;
final Color backgroundColor, selectedColor, unselectedColor;
final bool showElevation;
final Duration animationDuration;
final List<BottomNavyBarItem> items;
final ValueChanged<int> onItemSelected;
BottomNavyBar(
{Key key,
this.selectedIndex = 0,
this.showElevation = true,
this.iconSize = 20,
this.backgroundColor,
this.selectedColor,
this.unselectedColor,
this.animationDuration = const Duration(milliseconds: 250),
#required this.items,
#required this.onItemSelected}) {
assert(items != null);
assert(items.length >= 2 && items.length <= 5);
assert(onItemSelected != null);
}
Widget _buildItem(BottomNavyBarItem item, bool isSelected) {
return AnimatedContainer(
width: isSelected ? 120 : 50,
height: double.maxFinite,
duration: animationDuration,
decoration: BoxDecoration(
color: isSelected ? selectedColor.withOpacity(0.2) : backgroundColor,
borderRadius: BorderRadius.all(Radius.circular(100.0)),
),
alignment: Alignment.center,
child: ListView(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 8),
child: IconTheme(
data: IconThemeData(
size: iconSize,
color: isSelected ? selectedColor : unselectedColor),
child: item.icon,
),
),
isSelected
? DefaultTextStyle.merge(
style: TextStyle(
fontSize: 16,
color: selectedColor,
fontWeight: FontWeight.bold),
child: item.title,
)
: SizedBox.shrink()
],
)
],
),
);
}
#override
Widget build(BuildContext context) {
return Container(
color: backgroundColor,
child: Container(
width: double.infinity,
height: 55,
padding: EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: items.map((item) {
var index = items.indexOf(item);
return GestureDetector(
onTap: () {
onItemSelected(index);
},
child: _buildItem(item, selectedIndex == index),
);
}).toList(),
),
),
);
}
}
class BottomNavyBarItem {
final Icon icon;
final Text title;
BottomNavyBarItem({
#required this.icon,
#required this.title,
}) {
assert(icon != null);
assert(title != null);
}
}
Please help
adding builder like this will solve the problem
var paddingBottom = 60.0;
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
//
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'World General info',
//theme: ThemeData(primarySwatch: Colors.cyan,),
theme: ThemeData(
primaryColor: Colors.cyan,
accentColor: Colors.green,
textTheme: TextTheme(bodyText2: TextStyle(color: Colors.purple)),
),
home: MyHomePage(title: 'World General Info'),
builder: (BuildContext context, Widget child) {
return new Padding(
child: child,
padding: EdgeInsets.only(bottom: paddingBottom),
);
}
);
}
}
You can use the MediaQuery.of(context) for that.
Wrap the whole Code inside a Container of height: MediaQuery.of(context).size.height - 60 . (the height of ad)
Column(
children: [
Container(
height: MediaQuery.of(context).size.height - 60,
child: HomePage(),
),
BannerAd(),
]
);
Found answer myself
We can use this to set margin in a container with other things like height, width
This code will add margin to bottom of bottom nav bar, as per my need i want to show ads below navbar so this solves my problem
margin: const EdgeInsets.only(bottom: 50)
Add this to your scaffold
bottomNavigationBar: Container(
height: 50.0,
color: Colors.white,
),
Think Simplest bro ... wrap your column ( mainAxisSize : MainAxisSize.min )
Scaffold(
appBar: _appBar,
body: _body,
bottomNavigationBar: Column(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
Container(
color: Colors.amber,
height: 70,
child: Center(child: Text('Banner'))),
BottomNavigationBar(
items: const [
BottomNavigationBarItem(icon: Icon(Icons.add), label: 'Add'),
BottomNavigationBarItem(icon: Icon(Icons.add), label: 'Add'),
BottomNavigationBarItem(icon: Icon(Icons.add), label: 'Add')
],
)
]))
I have a main dart file and a settings dart file. The settings dart file is responsible for the appearance of the main dart file. Settings dart has a AppTheme class. Upon users typing on this settings page I want the main page to update.
My attempt at this was calling the class and redefining the variables based on user input. Doesnt work whether or not I use setState(). I also tried jus staying on the main page and tried changing the theme onPressed for the settings button. That didnt work either. Iconbutton update doesnt update the state either.
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:resume/settings.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
theme: ThemeData.light(),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
double buttonMargin = MediaQuery.of(context).size.width / 10;
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
return MaterialApp(
home: Scaffold(
backgroundColor: AppTheme().backgroundMain,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 20, 0, 0),
child: Column(
children: <Widget>[
Container(
height: (MediaQuery.of(context).size.height / 2.25),
child: Column(children: <Widget>[
Container(
margin: EdgeInsets.all(10),
child: Text(AppTheme().name,
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: screenWidth / 8.57142857143,
color: AppTheme().nameTextColor,
fontWeight: FontWeight.bold)),
),
]),
),
Container(
height: screenHeight / 2.3,
alignment: Alignment.bottomCenter,
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(
buttonMargin * 1.5,
buttonMargin * 3,
buttonMargin * 1.5,
buttonMargin * 3),
height: MediaQuery.of(context).size.height / 2,
width: MediaQuery.of(context).size.width / 2,
child: RaisedButton(
color: AppTheme().backgroundSecondary,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.settings,
color: Colors.white,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Settings',
style: TextStyle(color: Colors.white),
),
)
],
),
onPressed: () {
setState(() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return MySettings();
}),
);
},
);
},
),
),
],
),
),
],
),
),
),
),
);
}
}
settings.dart
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
void settings() {
runApp(MySettings());
}
class AppTheme {
var backgroundMain = Colors.red;
var backgroundSecondary = Colors.teal;
var backgroundAvatar = Colors.white;
var nameTextColor = Colors.white;
var professionTextColor = Colors.red[100];
var contactTextColor = Colors.teal;
var testPrint = print("hi");
String name = 'John Doe';
String nameFont = 'Pacifico';
String professionFont = 'roboto';
}
class MySettings extends StatefulWidget {
#override
MySettingsState createState() => MySettingsState();
}
class MySettingsState extends State<MySettings> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
backgroundColor: AppTheme().backgroundMain,
title: Text('Settings'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
setState(() {
AppTheme().backgroundMain = Colors.yellow;
print(AppTheme().name);
Navigator.pop(context);
});
},
),
),
backgroundColor: Colors.teal,
body: SafeArea(
child: ListView(
children: <Widget>[
Container(
child: TextField(
onChanged: (text) {
setState(() {
AppTheme().name = text;
});
},
),
),
Container(
child: TextField(),
),
],
)),
),
);
}
}
1 Make sure to properly import
Flutter/Dart Static variables lost / keep getting reinitialized
2 You cannot alter the variables in the class. You must create an object and alter the object.
i.e I was doing
Class MyClass {
var myVariable = someValue
}
MyClass.myVariale = aDifferentValue
This did not update MyClass
What I needed to do worked once I created an object
var myClassObject = new Myclass();
myClassObject.myVariable = aDifferentValue
Now I just alter and call on myClassObject.