Flutter in Native Android App, back pressed not working - android

I read a lot of topics about that but nothing works and was really same context that mine.
I'm trying to add flutter views inside native Android project, I've got a native Activity which launch a flutter fragment. This flutter fragment contains 2 views (firstScreen and secondScreen). FirstScreen redirect to SecondScreen on button pressed and secondScreen pop back to first screen on button pressed. Until now everything is ok.
But when I'm on second screen I'd like to go back on firstScreen on device back button pressed but instead flutter Fragment is closed and I'm back on native Activity.
The back process looks good as it works when I run flutter module alone.
Here are some screenshots:
And here are some code:
In native MainActivity
override fun startFlutterModule() {
val newFlutterFragment: FlutterFragment = FlutterFragment.createDefault()
supportFragmentManager.beginTransaction()
.replace(
fragmentContainerId,
newFlutterFragment,
TAG_FLUTTER_FRAGMENT
)
.addToBackStack(TAG_FLUTTER_FRAGMENT)
.commit()
}
Base Flutter App
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
routes: {
'/first': (context) => FirstScreen(),
'/second': (context) => SecondScreen(),
},
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FirstScreen(),
);
}
}
First Flutter Screen
class FirstScreen extends StatefulWidget {
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"First Screen",
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w600,
),
),
Padding(
padding: EdgeInsets.all(10.0),
child: RaisedButton(
padding: EdgeInsets.symmetric(
horizontal: 20.0,
vertical: 10.0,
),
onPressed: (){
Navigator.pushNamed(context, '/second');
},
child: Text(
"Screen 2",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
),
)
],
),
),
);
}
}
Second Flutter Screen
class SecondScreen extends StatefulWidget {
#override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
#override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: () async {
Navigator.pop(context);
return Future.value(false);
},
child: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Second Screen",
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w600,
),
),
Padding(
padding: EdgeInsets.all(10.0),
child: RaisedButton(
padding: EdgeInsets.symmetric(
horizontal: 20.0,
vertical: 10.0,
),
onPressed: () {
Navigator.pop(context);
},
child: Text(
"Screen 1",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
),
)
],
),
),
)
);
}
}

From your native activity invoke the onBackPressed() method of the FlutterFragment.
override fun onBackPressed() {
_flutterFragment.onBackPressed()
}

Set true for this attribute when using FlutterFragment, if not, the default hardware back press (or WillPopScope) on dart code will not work.

Related

In Flutter the sub-menu items of a particular menu appears beside to the menu that is below of it when clicking

I am using a Flutter Package named multilevel_drawer where the sub menu items of a particular menu appears beside to the menu below of it as shown below.
The sub-menu of My Account menu comes beside to the My Payment menu
The sub-menu of My Payment menu comes below to the My Payment menu
I have tried in this way by reading the article given here https://pub.dev/packages/multilevel_drawer
import 'package:flutter/material.dart';
import 'package:multilevel_drawer/multilevel_drawer.dart';
//import 'package:multilevel_drawer_demo/SecondScreen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter ML Menu',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
drawer: MultiLevelDrawer(
backgroundColor: Colors.white,
rippleColor: Colors.white,
subMenuBackgroundColor: Colors.grey.shade100,
divisionColor: Colors.grey,
header: Container(
height: size.height * 0.25,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset(
"assets/dp_default.png",
width: 100,
height: 100,
),
SizedBox(
height: 10,
),
Text("Subhadip Saha")
],
)),
),
children: [
MLMenuItem(
leading: Icon(Icons.person),
trailing: Icon(Icons.arrow_right),
subMenuItems: [
MLSubmenu(
submenuContent: Text("Username"),
onClick: () {
debugPrint("Username clicked!");
}),
MLSubmenu(onClick: () {}, submenuContent: Text("Password")),
],
content: Text(
"My Account",
),
onClick: () {}),
MLMenuItem(
leading: Icon(Icons.payment),
trailing: Icon(Icons.arrow_right),
subMenuItems: [
MLSubmenu(
submenuContent: Text("UPI"),
onClick: () {
debugPrint("UPI clicked!");
}),
MLSubmenu(
onClick: () {}, submenuContent: Text("Debit Card")),
],
content: Text(
"My Payment",
),
onClick: () {}),
]),
appBar: AppBar(
backgroundColor: Colors.white,
iconTheme: IconThemeData(color: Colors.black),
title: Text(
"Multi Level Menu",
style: TextStyle(color: Colors.black),
),
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.purple, Colors.blueAccent],
begin: Alignment.bottomLeft,
end: Alignment.topRight,
stops: [0.4, 0.7],
tileMode: TileMode.repeated,
),
),
child: Center()),
),
);
}
}
The sub menu should come beside to the right menu as expected.

How to get Bottom Navigation Functionality with FAB in Flutter

I have this design where when we open the app, it first goes to the Home Screen by default and I have two Bottom Navigation Bar Items.
I am unable to get it working because I want it to behave how Bottom Navigation Bar works but I want default screen to be the home. And when you click on Cart or Profile, it should highlight that tab but when you click on home, it should remove highlighting from it.
Here is a simple workaround or try search for bottomnavigation packages
check this persistent_bottom_nav_bar pacakge it allows to show bottom navigation in all pages with navigator,In other packages you have to do it yourself all the things.
if you want use persistent_bottom_nav_bar check this example for persistent_bottom_nav_bar
Top 16 Flutter Navigation Libraries
flutter-bottomappbar-navigation-with-fab
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
appBar: AppBar(title: Text('Title')),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
child: Container(
height: 56,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.home), onPressed: () {}),
IconButton(icon: Icon(Icons.search), onPressed: () {}),
SizedBox(width: 40), // The dummy child
IconButton(icon: Icon(Icons.notifications), onPressed: () {}),
IconButton(icon: Icon(Icons.message), onPressed: () {}),
],
),
)),
),
);
}
}
you can try with this persistent_bottom_nav_bar
Here is the Code for Bottom TabBar in Flutter
class TabView extends StatefulWidget {
const TabView({Key? key}) : super(key: key);
#override
_TabViewState createState() => _TabViewState();
}
class _TabViewState extends State<TabView> with SingleTickerProviderStateMixin {
late TabController tabController;
#override
void initState() {
super.initState();
// TODO: CHANGE LENGTH
tabController = TabController(length: 2, vsync: this);
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
tabController.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: Container(
height: 50,
child: TabBar(
unselectedLabelColor: Colors.grey,
labelColor: kPrimaryColor,
indicatorColor: kPrimaryColor,
labelStyle: TextStyle(fontSize: 11, fontWeight: FontWeight.w500),
tabs: [
Tab(
icon: Icon(Icons.home, size: 25.0,),
text: "Tab1",
iconMargin: EdgeInsets.zero,
),
Tab(
icon: Icon(Icons.person, size: 25.0),
text: "Tab2",
iconMargin: EdgeInsets.zero,
),
],
controller: tabController,
),
),
body: TabBarView(
controller: tabController,
children: [
Tab1(),
Tab2()
],
),
);
}
}

How to show the fetched data from api on a button click in flutter?

I want to show the fetched love calculator data after button click but how to visible it? Please answer
import 'dart:io';
import 'package:AllInOneCalci/CustomTextField.dart';
import 'package:AllInOneCalci/Post.dart';
import 'package:AllInOneCalci/customAppBar.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
class LoveCalUI extends StatelessWidget {
#override
Widget build(BuildContext context) {
var AppBarHeight = MediaQuery.of(context).size.height;
return Scaffold(
appBar: customAppBar(
height: (AppBarHeight / 3) * 0.4,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(top: 18.0),
child: Text(
'All In One Cali',
style: TextStyle(
color: Colors.black,
fontSize: 35.0,
fontFamily: 'DancingScript',
fontWeight: FontWeight.bold),
),
),
],
),
),
body: CustomFetchData(),
);
}
}
class CustomFetchData extends StatefulWidget {
#override
_CustomFetchDataState createState() => _CustomFetchDataState();
}
class _CustomFetchDataState extends State<CustomFetchData> {
TextEditingController firstNameController = new TextEditingController();
TextEditingController secondNameController = new TextEditingController();
Future<Post> getData() async {
final response = await http.get(
'https://love-calculator.p.rapidapi.com/getPercentage?fname=aalia&sname=Alice',
headers: {
'x-rapidapi-host': 'love-calculator.p.rapidapi.com',
'x-rapidapi-key':
'84e84770b9msh59a96d8b03cb4aap1615a1jsn1cd0ef******',
});
if (response.statusCode == 200) {
return Post.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load api');
}
}
Widget ErrorDesign() {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
alignment: Alignment.center,
child: Text(
'Error: Kindly Connect to Internet',
style: TextStyle(
color: Colors.redAccent,
fontFamily: 'DancingScript',
fontSize: 40.0,
fontWeight: FontWeight.bold,
),
),
),
);
}
Widget DisplayData(String percentageValue, String result) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: 100.0,
color: Colors.black,
child: Column(
children: [
Text('Percentage is $percentageValue',
style: TextStyle(
color: Colors.white,
)),
Text('Result is: $result',
style: TextStyle(
color: Colors.white,
)),
],
),
),
);
}
Widget FetchedCalculationValues() {
return Column(
children: [
Container(
child: FutureBuilder<Post>(
future: getData(),
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: CircularProgressIndicator(),
),
);
} else {
if (snapshot.hasError) {
return Container(
child: ErrorDesign(),
);
} else {
return DisplayData(
snapshot.data.percentage, snapshot.data.result);
}
}
})),
],
);
}
#override
Widget build(BuildContext context) {
return Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 18.0, right: 18.0, top: 15.0),
child: CustomTextField('First Name', "", Colors.cyan,
Colors.cyanAccent, Colors.redAccent, firstNameController),
),
Padding(
padding: const EdgeInsets.only(left: 18.0, right: 18.0),
child: CustomTextField('Second Name', "", Colors.red,
Colors.redAccent, Colors.cyanAccent, secondNameController),
),
Padding(
padding: const EdgeInsets.all(18.0),
child: MaterialButton(
color: Colors.redAccent,
child: Text(
'Result',
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {
FetchedCalculationValues();
print('Fetch Calling');
}),
),
Visibility(
visible: false,
child: FetchedCalculationValues(),
),
],
);
}
#override
// ignore: must_call_super
void initState() {
getData();
}
}
How to make the function for api call visible to the screen after button click.
Also I want to use the text field's values at the place of defalut values
Can you solve my problem? It will be very helpful if you do so. I am a newbie and learning flutter since 15 days. Help me so that I can learn it fast. Also the flutter's community is growing fast so it will be easy for me not to wait for response. Thank You.
I have created simplified, single-screen, app without any extra capabilities to solve exactly your issue. It contains two text fields, two Text widgets to display API results and a floating action button to make request.
Key concepts that you should know to make this code are http requests and asynchronous coding. Those links are good starting points for you to get a sense of what actually happens
To summarize what exactly you need:
You send request asynchronously to the API declaring function with async keyword and await keyword in front of http.get() function. This allows you to wait for the result of the request without freezing the app
When result comes back, the rest of the _getNames() function gets executed, which includes setState(). setState() rebuilds your widget and updates values in Text() widgets
Full code:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
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();
}
class _MyHomePageState extends State<MyHomePage> {
int percentage = 0;
String resultString = "";
Map<String, String> requestHeaders = {
'x-rapidapi-host': 'love-calculator.p.rapidapi.com',
'x-rapidapi-key': 'your API key',
};
final name1Controller = TextEditingController();
final name2Controller = TextEditingController();
void _getNames({String name1, String name2}) async {
final response = await http.get(
'https://love-calculator.p.rapidapi.com/getPercentage?fname=$name1&sname=$name2',
// Send authorization headers to the backend.
headers: requestHeaders,
);
final responseJson = json.decode(response.body);
setState(() {
percentage = int.parse(responseJson['percentage']);
resultString = responseJson['result'];
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: name1Controller,
decoration: InputDecoration(
hintText: "name 1",
),
),
TextField(
controller: name2Controller,
decoration: InputDecoration(
hintText: "name 2",
),
),
SizedBox(
height: 10,
),
Text(
'Your Score is: $percentage',
),
Text(
'$resultString',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_getNames(
name1: name1Controller.text,
name2: name2Controller.text,
);
},
tooltip: 'Increment',
child: Text('Go'),
),
);
}
}

The shadow of the child elements changes position within a wrap in flutter

I have a problem with the shadow of the children of a Wrap.
I have managed to recreate it quickly.
Apparently, the more you scroll, the shadow at the bottom disappears and begins to come out at the top of each item, making a somewhat strange effect.
How could the shadow of the child items remain in the correct position?
At the bottom of the list, I have added several more buttons (but always outside the Wrap), and the shadow is cast correctly.
Edit:
I add the sample code to recreate the error
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 Hello World',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
const MyHomePage({#required this.title});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
child: ListView(
children:[
new LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
List<Widget> _list = List();
int _number_items = 30;
for(int a = 0; a < _number_items; a++){
_list.add(
Card(
elevation: 4,
child: Container(
margin: EdgeInsets.all(10),
width: 200,
height: 200,
),
)
);
}
for(int a = 0; a < _number_items; a++){
_list.add(
Container(
width: 400,
child: RaisedButton(
onPressed: () {},
child: Text(
"Button in the Wrap ",
style: TextStyle(color: colors.white),
),
color: Colors.red,
),
)
);
}
return Wrap(
children: _list,
);
}
),
RaisedButton(
onPressed: () {},
child: Text(
"Button outside the Wrap",
style: TextStyle(color: Colors.white),
),
color: Colors.red,
),
RaisedButton(
onPressed: () {},
child: Text(
"Button outside the Wrap",
style: TextStyle(color: Colors.white),
),
color: Colors.red,
),
RaisedButton(
onPressed: () {},
child: Text(
"Button outside the Wrap",
style: TextStyle(color: Colors.white),
),
color: Colors.red,
)
],
)
),
);
}
}
Example:
Add this to the ListView:
addRepaintBoundaries: false

Flutter : change position of text on the appbar

How can i change the position of my text "Sito Web" on the right of the appbar? I tryid with
alignment: Alignment.TopRight
but he move it the text on the top right corner down the appbar. Here a screen of what i mean https://ibb.co/X28TzNN change the position of "Sito Web" in the position of the red cirle. That's the codes, i tryid with this method too, but can't move in the appbar. Here the file with the appbar background_image_task-9.dart
import 'package:flutter/material.dart';
class BackgroundImage extends StatelessWidget{
final Widget body;
BackgroundImage({this.body});
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Text('Blumax', style: TextStyle(
fontWeight: FontWeight.w500,
fontFamily: 'DancingScript',
fontSize: 40
),),
centerTitle: false,
),
body: Stack(
children: <Widget>[Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage("assets/blumax.jpg"), fit: BoxFit.cover),
),
),
body
]
)
);
}
}
And here the file with the container hyperlink.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class Hyperlink extends StatelessWidget {
final String _url;
final String _text;
Hyperlink(this._url, this._text);
_launchURL() async {
if (await canLaunch(_url)) {
await launch(_url);
} else {
throw 'Could not launch $_url';
}
}
#override
Widget build(BuildContext context) {
return InkWell(
child: Container(
alignment: Alignment(0.9, -1.0),
child: Text(
_text,
textAlign: TextAlign.right,
style: TextStyle(
fontFamily: 'RobotoMono',
fontSize: 20,
color: Colors.white,
decoration: TextDecoration.underline),
)),
onTap: _launchURL,
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'background_image_task-9.dart';
import 'hyperlink.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Blumax',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: myColour
),
home: BackgroundImage(
body: Center(
child: Hyperlink('www.test.it', 'Sito Web',),
),
)
);
}
}
You can use Row widget and use mainAxisAlignment: MainAxisAlignment.spaceBetween to render BluMax and Sito Web elements on left and right of the appbar respectively. And since you want to open a url after tapping on sito web, you can wrap that element with GestureDetector and then call launchURL method that opens required url. A working sample code is as below:
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text('Blumax'),
GestureDetector(
child: Text('Sito Web'),
onTap: _openURL
)
],
),
centerTitle: false,
actions: <Widget>[
PopupMenuButton<int>(
itemBuilder: (context) =>
[
PopupMenuItem(
value: 1,
child: Text("First"),
),
PopupMenuItem(
value: 2,
child: Text("Second"),
),
],
)
],
),
This is rendered on screen as:
...
void _openURL() async {
const url = 'https://flutter.dev';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
I just used a text Blumax for demo, but you may replace it per your need.
Hope this answers your question.

Categories

Resources