How to remove Android back buttons on MaterialApp on Flutter? - android

void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
OrientationSingleton.left = true;
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft])
.then((_) {
runApp(new MyApp());
});
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
Here's my app. I've found some tutorials on how to remove it: flutter remove back button on appbar but it's for an AppBar. I tried making my app work on an AppBar but I get
MediaQuery.of() called with a context that does not contain a MediaQuery.
Because I rely on MediaQuery.of() inside my app.
So, how do I remove the Android back, home and square buttons on Flutter for a MaterialApp?

As stated in the error message, SystemChrome requires context - a place to call it could be the initState() method of the Widget:
class MyApp extends StatefulWidget {
const MyApp({ Key key }) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
OrientationSingleton.left = true;
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]);
}
#override
Widget build(BuildContext context) {
return MaterialApp(); // your MaterialApp class
}
}
To hide the system bottom bar on Android, one option could be to call the setEnabledSystemUIOverlays() function with an empty list:
SystemChrome.setEnabledSystemUIOverlays([]);
However, this function is not globally supported on all Android devices.

Related

I can't show images in splash screen

class _SplashScreenState extends State<SplashScreen> {
void init(){
loadDatas();
super.initState();
}
Future<void> loadDatas()async{
await Future.delayed(Duration(seconds:2));
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Image.asset('assets/todo3.png'),
),
);
}
}
SplashScreen Widget I created.
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: const SplashScreen(),
);
}
}
The part where I call SplashScreen in Main.dart. Am I adding the image in the wrong place? Or should I not make SplashScreen my homepage?
Instead of adding dependency for splash screen, it will better to create a screen for splash and navigate from that screen.
Steps for Creating a Splash Screen
Make a new screen.
On the init method of the splash screen, call a async function and add the necessary code to execute in the splash screen.
#override
void initState(){
loadDatas();
super.initState();
}
Future<void> loadDatas()async{
await Future.Delayed(Duration(seconds:2));
}

Flutter - Cannot set an appbar as a widget to the scaffold

I want to create a responsive appbar without need to setState to the entire scaffold when there are changes. The problem is I can set a BottomNavigationBar widget to the scaffold's bottomNavigationBar but I can't do the same with an AppBar to set to it's appBar. I get this error
The argument type 'TopBar' can't be assigned to the parameter type 'PreferredSizeWidget'
I've simplified the code with the States only part.
class StateLayoutNav extends State<LayoutNav>{
#override
Widget build(BuildContext context) => Scaffold(
bottomNavigationBar : BottomBar(), appBar : TopBar()
);
}
class StateTopBar extends State<TopBar>{
#override
Widget build(BuildContext context) => AppBar();
}
class StateBottomBar extends State<BottomBar>{
#override
Widget build(BuildContext context) => BottomNavigationBar();
}
My solution would be implementing your Appbar widget with PreferredSizeWidget as Appbar need to be of preferredSize
class TopBar extends StatefulWidget with PreferredSizeWidget {
TopBar({Key key}) : preferredSize = Size.fromHeight(kToolbarHeight), super(key: key);
#override
final Size preferredSize;
#override
StateTopBar createState() => StateTopBar();
}
class StateTopBar extends State<TopBar>{
#override
Widget build(BuildContext context) => AppBar();
}
Try appBar: TopBar() as PreferredSizeWidget
Try this. It will give you a custom app bar with any customisable widget. You can add fixed Container. Solution is implementing app bar with PreferredSizeWidget.
class TopBar extends StatefulWidget implements PreferredSizeWidget {
TopBar({Key? key}) : preferredSize = Size.fromHeight(kToolbarHeight), super(key: key);
#override
final Size preferredSize; // default is 56.0
#override
_TopBarState createState() => _TopBarState();
}
class _TopBarState extends State<TopBar>{
#override
Widget build(BuildContext context) {
return Container( child: Text("Sample App Bar") );
}
}

How can we get callback when application killed in Flutter?

In Flutter, I don't get any callback when the application is killed. Now, how can I stop streaming when my application is killed?
You should use the Stateful Widget and there is a dispose method, there you can dispose everything you want when application is killed.
Example:
class MyApp extends StatefulWidget {
MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
void dispose() {
//something.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container());
}
}
You must use app lifecycle state in Flutter.

Changing an attribute in a parent widget from a child widget

I am trying to create an app. I want to change an attribute in a parent class (so it can display a Visibility item, SlidingUpPanel) after submitting a query in the child class (which is a search bar).
I have tried using a callback function and followed How can I pass the callback to another StatefulWidget? but it doesn't seem to do anything when I submit my query in the search bar. Previously, I have also tried to use Navigator.push to call SlidingUpPanel directly but it resulted in a black screen with only SlidingUpPanel.
Parent class (Map):
class MapPage extends StatefulWidget {
const MapPage({Key? key}) : super(key: key);
#override
_MapPageState createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
bool IsVisible = false;
void callbackFunction() {
setState(() {
IsVisible = true;
});
}
...
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
children: [
...
Visibility(
visible: IsVisible,
child: SlidingUpPanel()),
SearchPage(callbackFunction),
]),
);
}
}
Child class (Search Bar):
class SearchPage extends StatefulWidget {
final Function callback;
SearchPage(this.callback);
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
...
#override
Widget build(BuildContext context) {
return FloatingSearchBar(
...
onSubmitted: (query) {
// callback here, but doesn't seem to do anything
widget.callback;
controller.close();
},
...
);
}
}
To actually call a function (execute it) you must use ().
Try calling the callback function like this:
onSubmitted: (query) {
// use () to actually call the function
widget.callback();
controller.close();
},

Flutter: Why Future.then() doesn't work on class variable?

Code I show you is the simplified code which I'm troubled in.
My expected result is [1,2,3,4,5,6], but app says [1,2,3].
I know "loadMoreInterger()" should be in "initState()", but for some reason I have to put it in Widget build() {"HERE"}.
I wonder if why doesn't it work, and the solution for correct result.....
I really appreciate for your help :)
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
// ↓↓↓↓↓↓↓↓↓↓↓WHERE I CANNOT UNDERSTAND↓↓↓↓↓↓↓↓↓↓↓
class _MyHomePageState extends State<MyHomePage> {
List<int> intList = [1,2,3];
Future<List<int>> loadMoreInteger() async {
print('Future');
return [4,5,6];
}
#override
Widget build(BuildContext context) {
loadMoreInteger().then((value) {
intList.addAll(value); // why doesn't it work?
});
print("console: $intList");
return Scaffold(
body: Center(
child: Text("display: $intList")
)
);
}
}
//Expected result: [1,2,3,4,5,6]
//Actual result: [1,2,3]
put it in initState override function and it works for yu !!!!
List<int> intList = new List();
Future<List<int>> loadMoreInteger() async {
print('Future');
return [4,5,6];
}
#override
void initState() {
super.initState();
intList = [1,2,3];
loadMoreInteger().then((v){
setState(() {
intList.addAll(v) ;
});
}); }
Here is what your build method does: after entering the method it starts to execute loadMoreInteger() future. Afterwards even if executed future is synchronous it only schedules call of next future that is produced by calling .then. So build method continues to execute with old intList value. And [4,5,6] will be added only after build completes.
In general you can wait for future to complete by calling it with await keyword. But build method is overriden and already has predefined return type that is not future, so you can not call await inside build.
What you can do:
I highly recommend moving any manipulation with data from build method. Its purpose is to produce widgets as fast as possible. It can be called multiple times at some moment unexpected for developer.
One of possible options for you will be moving loadMoreInteger() to initState and calling setState when intList is updated
#override
void initState() {
super.initState();
loadMoreInteger().then((value) {
setState(() {
intList.addAll(value);
});
});
}

Categories

Resources