I was trying to use fullscreen in my app, but I noticed that on devices with android 8.1 (API 27), when the user opens a keyboard the app exits fullscreen mode and doesn't comeback unless the ui is rebuild, does anyone have a solution?
I also tested on Android 7.1 (API 25) and the problem is easier to deal with, the only thing that doesn't come back to fullscreen is the top bar, but still, the code below only works flawless on new androids (API 28 +)
Code:
void main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
SystemChrome.setEnabledSystemUIOverlays([]);
return Scaffold(
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(flex: 1, child: Text('Fullscreen test')),
Flexible(
flex: 1,
child: TextFormField(
controller: TextEditingController(),
),
),
Flexible(flex: 1, child: SizedBox())
],
)),
);
}
}
You should call this in initState. Working code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MaterialApp(home: MyApp()));
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
// TODO: implement initState
super.initState();
SystemChrome.setEnabledSystemUIOverlays([]);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(flex: 1, child: Text('Fullscreen test')),
Flexible(
flex: 1,
child: TextFormField(
controller: TextEditingController(),
),
),
Flexible(flex: 1, child: SizedBox())
],
)),
);
}
}
Related
I'm developing a desktop app on Windows and am trying to move focus to a Textfield when the ENTER key is pressed on another textfield.
I'm able to detect the key has been pressed using RawKeyboardListener but focus isnt changed to the new field. How can I get this working?
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late FocusNode _txtNode;
#override
void initState() {
super.initState();
_txtNode = FocusNode();
}
#override
void dispose() {
_txtNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Stack(
children: [
Container(
height: 400,
width: 500,
color: Colors.grey[350],
child: Column(
children: [
Container(
height: 100,
child: RawKeyboardListener(
focusNode: FocusNode(),
onKey: (event){
if (event.toString().contains('RawKeyDownEvent') && event.toString().contains('Enter')) {
print("pressed ENTER");
_txtNode.requestFocus();
}
},
child: TextField(readOnly: true,))
),
TextField(
),
TextField(
focusNode: _txtNode,
),
],
),
),
]
),
),
),
);
}
}
I have achieved your use case by just modified your code snippets. Please check the below code snippets. FocusScope.of(context).nextFocus() is used to move the focus to the next. If you want to move a focus to a specific widget. you just call that focusNode.requestFocus().
class FocusDemo extends StatefulWidget {
#override
_FocusDemoState createState() => _FocusDemoState();
}
class _FocusDemoState extends State<FocusDemo> {
late FocusNode _txtNode;
#override
void initState() {
super.initState();
_txtNode = FocusNode();
}
#override
void dispose() {
_txtNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Focus(
focusNode: _txtNode,
onKey: (focusNode, event) {
if (event.runtimeType == RawKeyUpEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
focusNode.nextFocus();
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: Container(
height: 400,
width: 500,
color: Colors.grey[350],
child: Column(
children: [
TextField(),
TextField(),
TextField(),
],
),
),
),
),
);
}
}
I would like to know how to open a YouTube video and showing it on my Flutter app with a video player that allow the user to stop the video, moving forward, backward just dragging the finger on the bottom line of the video.
I was thinking to use youtube_player_iframe since I read on the internet that this is the only widget that allows to open YouTube videos (for iOS, youtube_player for Android) so I installed it and copy-pasted the example from docs and fixed some errors.
If anyone could help me to understand why it doesn't work I'll be very glad.
To install, from terminal run : flutter pub add youtube_player_iframe
Or just add the dependence : youtube_player_iframe: ^2.0.0
This is the code, just copy-paste and it can be run :
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(YoutubeApp());
}
///
class YoutubeApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Youtube Player IFrame Demo',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
iconTheme: const IconThemeData(color: Colors.deepPurpleAccent),
),
debugShowCheckedModeBanner: false,
home: YoutubeAppDemo(),
);
}
}
///
class YoutubeAppDemo extends StatefulWidget {
#override
_YoutubeAppDemoState createState() => _YoutubeAppDemoState();
}
class _YoutubeAppDemoState extends State<YoutubeAppDemo> {
late YoutubePlayerController _controller;
String urlVideoFromYouTube = 'v0RWej7Sqg4'; //this is the last part of the YouTube url https://www.youtube.com/watch?v=v0RWej7Sqg4 copy-pasted by me
#override
void initState() {
super.initState();
_controller = YoutubePlayerController(
initialVideoId: urlVideoFromYouTube,
params: const YoutubePlayerParams(
playlist: [
'nPt8bK2gbaU',//Default playlist
'K18cpp_-gP8',
'iLnmTe5Q2Qw',
'_WoCV4c6XOE',
'KmzdUe0RSJo',
'6jZDSSZZxjQ',
'p2lYr3vM_1w',
'7QUtEmBT_-w',
'34_PXCzGw1M',
],
startAt: const Duration(minutes: 1, seconds: 36),
showControls: true,
showFullscreenButton: true,
desktopMode: true,
privacyEnhanced: true,
useHybridComposition: true,
),
);
_controller.onEnterFullscreen = () {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
log('Entered Fullscreen');
};
_controller.onExitFullscreen = () {
log('Exited Fullscreen');
};
}
#override
Widget build(BuildContext context) {
const player = YoutubePlayerIFrame();
return YoutubePlayerControllerProvider(
// Passing controller to widgets below.
controller: _controller,
child: Scaffold(
appBar: AppBar(
title: const Text('Youtube Player IFrame'),
),
body: LayoutBuilder(
builder: (context, constraints) {
if (kIsWeb && constraints.maxWidth > 800) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Expanded(child: player),
const SizedBox(
width: 500,
child: SingleChildScrollView(
child: Controls(),
),
),
],
);
}
return ListView(
children: [
player,
const Controls(),
],
);
},
),
),
);
}
#override
void dispose() {
_controller.close();
super.dispose();
}
}
///
class Controls extends StatelessWidget {
///
const Controls();
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// _space,
// MetaDataSection(),
// _space,
// SourceInputSection(),
// _space,
// PlayPauseButtonBar(),
// _space,
// VolumeSlider(),
// _space,
// PlayerStateSection(),
],
),
);
}
Widget get _space => const SizedBox(height: 10);
}
Here's the link to that repository: https://pub.dev/packages/youtube_player_iframe, download it fully and run it's main.dart file using VS code or android studio, You can't run just a main.dart file without the other files for this plugin to work.Doing this, will give you an idea of how to run this plugin.
I want detect Keyboard. And want to show it other text when keyboard is visible or unvisible.
But my code is not working.
This is my code.
class Search extends StatefulWidget {
#override
_SearchState createState() => _SearchState();
}
class _SearchState extends State<Search> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Column(
children: [
Expanded(
flex: 1,
child: ListView(
children: [
MediaQuery.of(context).viewInsets.bottom !=0 ? Center(child: Text("true"),) : Center(child: Text("false"),)
],
),
)
],
),
),
);
}
}
As #Anas Mohammed mentioned, you can do it with the keyboard_visibility package. Here is a total example:
import 'package:flutter/material.dart';
import 'package:keyboard_visibility/keyboard_visibility.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Keyboard visibility example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: KeyboardVisibilityExample(),
);
}
}
class KeyboardVisibilityExample extends StatefulWidget {
KeyboardVisibilityExample({Key key}) : super(key: key);
#override
_KeyboardVisibilityExampleState createState() => _KeyboardVisibilityExampleState();
}
class _KeyboardVisibilityExampleState extends State<KeyboardVisibilityExample> {
KeyboardVisibilityNotification _keyboardVisibility = new KeyboardVisibilityNotification();
int _keyboardVisibilitySubscriberId;
bool _keyboardState;
#protected
void initState() {
super.initState();
_keyboardState = _keyboardVisibility.isKeyboardVisible;
_keyboardVisibilitySubscriberId = _keyboardVisibility.addNewListener(
onChange: (bool visible) {
setState(() {
_keyboardState = visible;
});
},
);
}
#override
void dispose() {
_keyboardVisibility.removeListener(_keyboardVisibilitySubscriberId);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Keyboard visibility example'),
),
body: Center(
child: Padding(
padding: EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: 'Input box for keyboard test',
),
),
Container(height: 60.0),
Text(
'The current state of the keyboard is: ' + (_keyboardState ? 'VISIBLE' : 'NOT VISIBLE'),
),
],
)
),
),
);
}
}
for to visible keyboard this code:
FocusScope.of(context).requestFocus();
for to unvisible keyboard this code:
FocusScope.of(context).unfocus();
for check visiblity of keyboard :
FocusScope.of(context).hasFocus
your provided code:
class Search extends StatefulWidget {
#override
_SearchState createState() => _SearchState();
}
class _SearchState extends State<Search> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.white,
child: Column(
children: [
Expanded(
flex: 1,
child: ListView(
children: [
FocusScope.of(context).hasFocus ? Center(child: Text("true"),) : Center(child: Text("false"),)
],
),
)
],
),
),
);
}
}
Accepted answer contains old library not support null safety, you can use this one flutter_keyboard_visibility which support null safety.
I am trying to navigate to a new screen after the splash screen, when i try to navigate to new screen in the init method it shows an error,
E/flutter ( 5636): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Navigator operation requested with a context that does not include a Navigator.
E/flutter ( 5636): The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
My code
import 'package:flutter/material.dart';
import 'package:igloled_app/home.dart';
import 'dart:async';
class SplashScreen extends StatefulWidget {
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 3),(){
print('3 sec done');
Navigator.push(context, MaterialPageRoute(builder: (context){
return AppHeader();
}));
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white70,
),
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(flex: 2,
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
margin: EdgeInsets.all(10.0),
child: Image.asset('images/splash_logo.png')
),
)
],
),
),
),
Expanded(flex: 1,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(valueColor: AlwaysStoppedAnimation<Color>(Colors.green),),
Padding(padding: EdgeInsets.only(top: 20.0),
),
Text('Make Your Life Brighter',
style: TextStyle(
color: Colors.lightGreen,
fontStyle: FontStyle.italic,
fontSize: 20.0,
),
),
],
),
)
],
),
],
),
),
);
}
}
}
Can anyone please help me with this.
Thank you in advance.
Here is a sample code of doing it right way.
void main() => runApp(MaterialApp(home: FirstScreen()));
class FirstScreen extends StatefulWidget {
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
#override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 3), () {
print('3 sec done');
Navigator.push(context, MaterialPageRoute(builder: (context) {
return SecondScreen();
}));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title: Text("First screen")));
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title: Text("Second screen")));
}
}
your MaterialApp is not in your context !!
a slight fix to move the MaterialApp to the runApp method.
but for a notice please but all underground widgets that won't use the setState to another class or to the runApp method to have the best functionality of your code .
I have this code and when i click on textfield it DOES appear on middle of screen above the keyboard, but it's very tightly fit there and the text below it does not appear. How can i make it so that when I click on the textfield the scrolling is enough to show the text below it as well?
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(height: 600,),
TextField(
),
SizedBox(height: 30,),
Text("I want this text to appear ")
],
),
),
),
);
}
}
There is no exact solution for this, however you can use ScrollController to scroll the rest of the area in your SingleChildScrollView
ScrollController _scrollController = ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: <Widget>[
SizedBox(height: 600),
TextField(
onTap: () {
Timer(Duration(milliseconds: 200), () {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
},
),
SizedBox(height: 30),
Text("I want this text to appear "),
],
),
),
);
}.