Flutter getx is changing var state when changing language translation which it's not ment to do - flutter-getx

Please Look at the gif.
The problem is the second number is changing value if I change the translation. Why changing translation is changing a variable value that is not related to the translation function. Although the app is named after riverpod, but only getx is used. riverpod is just in the name.
here is Github
Full code check on GitHub Here is the code:
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_app_riverpod/screens/screen1.dart';
void main() {
runApp( MyApp());
}
screen1.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_app_riverpod/screens/screen2.dart';
import 'package:flutter_app_riverpod/class/translation.dart';
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return GetMaterialApp(
translations: MyTranslations(),
locale: const Locale('pt', 'BR'),
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'test app'),
);
}
}
controller.dart
import 'package:get/get.dart';
var count = 0.obs;
screen2.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_app_riverpod/class/translation.dart';
import 'package:flutter_app_riverpod/class/controller.dart';
class MyHomePage extends StatelessWidget {
MyHomePage({Key? key, required this.title, }) : super(key: key);
final String title;
// number variable to store last state of the count variable from controller.dart
final number = RxInt(count.value);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(title.tr),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
onPressed: () => count--,
tooltip: 'Decrement',
child: const Icon(Icons.delete),
),
Text(
'text'.tr,
),
ElevatedButton(
child: Text('Change locale to Brasil'),
onPressed: () {
Get.updateLocale(Locale('pt', 'BR'));
},
),
const Text(
'You have pushed the button this many times:',
),
Obx(
() => Text(
//count value is in controller.dart file
'$count',
style: Theme.of(context).textTheme.headline4,
),
),
Obx(
() => Text(
'$number',
style: Theme.of(context).textTheme.headline4,
),
),
ElevatedButton(
child: Text('Change locale to English'),
onPressed: () {
Get.updateLocale(Locale('en', 'UK'));
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
count++;
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
translation.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class MyTranslations extends Translations {
#override
Map<String, Map<String, String>> get keys => {
'en': {
'title': 'Hello World %s',
'text' : 'This is EN Text',
},
'en_US': {
'title': 'Hello World from US',
'text' : 'This is ENUS Text',
},
'pt': {
'title': 'Olá de Portugal',
'text' : 'This is Portugal Text',
},
'pt_BR': {
'title': 'Olá do Brasil',
'text' : 'This is Brasil Text',
},
};
}

Related

Managing routing and state from a central place in flutter

I have this simple flutter app that consists of just two pages linked with the router which is defined in the main() function. However, i would like to isolate my classes into their own files since my app consists of many pages. Here is my code
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Named Routes',
initialRoute: '/',
routes: {
'/': (context) => const firstRoute(),
'/second': (context) => const secondRoute(),
},
));
}
// ignore: camel_case_types
class firstRoute extends StatelessWidget {
const firstRoute({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GFG First Route'),
backgroundColor: Colors.green,
),
body: Center(
child: ElevatedButton(
child: const Text('Launch screen'),
onPressed: () {
Navigator.pushNamed(context, '/second');
},
), // Elevated
// RaisedButton is deprecated now
// child: RaisedButton(
// child: const Text('Launch screen'),
// onPressed: () {
// Navigator.pushNamed(context, '/second');
// },
// ),
),
);
}
}
// ignore: camel_case_types
class secondRoute extends StatelessWidget {
const secondRoute({Key? key}) : super(key: key);
#override
// ignore: dead_code
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GFG Second Route"),
backgroundColor: Colors.green,
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
), // ElevatedButton
),
// RaisedButton is deprecated now
// child: RaisedButton(
// onPressed: () {
// Navigator.pop(context);
// },
// child: const Text('Go back!'),
// ),
);
}
}
How would i go about isolating each of my classes in separate .dart files and still make use of the routing defined in main?
Also, i would like to have some global state accessible in each of the dart files i shall create. How would i go about solving the first and second problems?.
you can separate your current code into 3 files.
1: main.dart
import 'package:flutter/material.dart';
import 'package:<app_name>/screens/firstRoute.dart';
import 'package:<app_name>/screens/secondRoute.dart';
// this is a globally available variable
final valueNotifier = ValueNotifier('hello');
void main() {
runApp(MaterialApp(
title: 'Named Routes',
initialRoute: '/',
routes: {
'/': (context) => const firstRoute(),
'/second': (context) => const secondRoute(),
},
));
}
2: firstFile.dart
class firstRoute extends StatelessWidget {
const firstRoute({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('GFG First Route'),
backgroundColor: Colors.green,
),
body: Center(
child: ElevatedButton(
child: const Text('Launch screen'),
onPressed: () {
Navigator.pushNamed(context, '/second');
},
),
),
);
}
}
3: secondFile.dart
// imported main.dart so that we can use valueNotifier
import 'package:<app_name>/main.dart';
import 'package:flutter/material.dart';
class secondRoute extends StatelessWidget {
secondRoute({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("GFG Second Route"),
backgroundColor: Colors.green,
),
body: Column(children: [
ValueListenableBuilder(
valueListenable: valueNotifier,
builder: ((BuildContext context, String updatedValue, Widget? child) {
return Text(updatedValue);
}),
),
Center(
child: ElevatedButton(
onPressed: () {
valueNotifier.value = 'got changed';
},
child: const Text('Change me'),
), // ElevatedButton
),
]),
);
}
}
once you've separated the files, you'll need to import them... say, you've created the files in lib/screens
so, the import line will be something like this, vs code/Android Studio can take care of it
import 'package:<app_name>/screens/secondRoute.dart';
for global state management, you can have a ValueNotifier which is globally exposed from main.dart you can simply listen to its change via ValueListenableBuilder a very basic implementation is shown as well
although this is not recommended for bigger projects, if that's the case then you should use something like provider

Flutter get text from widgets

I am coming from java and now making my very initial steps with flutter.
In my first application I am playing around with the layouts and the buttons and I am facing difficulties getting the button actions to work, probably due to my coming from from java.
In my app I have, among others, the following widgets:
Widget _buttonOne = RaisedButton(
onPressed: () {},
child: Text('Button One', style: TextStyle(fontSize: 20)),
);
final _textContainer =
const Text('Container One', textAlign: TextAlign.center);
Container(
padding: const EdgeInsets.all(8),
child: _textContainer,
color: Colors.teal[200],
),
Now I want to print the text of the button and textchild of the container. How do I achieve that?
CupertinoButton.filled(
child: Text('Button Two'),
onPressed: () {
print(_textContainer); // how do I print the text of the text widget here?
print (_buttonOne. ....); // on java there is a getText() method .... how does this work in flutter?
),
You can access the text of a Text widget by using the data property:
final _textContainer =
const Text('Container One', textAlign: TextAlign.center);
#override
Widget build(BuildContext context) {
return Scaffold(body:
Center(
child: CupertinoButton.filled(
child: Text('Button Two'),
onPressed: () =>
{print(_textContainer.data)},
)
)
);
}
In a similar fashion, you could access the content of the RaisedButton child:
final _raisedButtonText = const Text('Button One', style: TextStyle(fontSize: 20));
Widget _buttonOne = RaisedButton(onPressed: () {}, child: _raisedButtonText);
final _textContainer =
const Text('Container One', textAlign: TextAlign.center);
#override
Widget build(BuildContext context) {
return Scaffold(body:
Center(
child: CupertinoButton.filled(
child: Text('Button Two'),
onPressed: () {
print(_textContainer.data);
print(_raisedButtonText.data);
}
)
)
);
}
You can copy paste run full code below
You can use as to do type casting then access attribute data
code snippet
CupertinoButton.filled(
child: Text('Button Two'),
onPressed: () {
print(_textContainer.data);
print(((_buttonOne as RaisedButton).child as Text).data);
}),
output
I/flutter (30756): Container One
I/flutter (30756): Button One
full code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
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();
}
class _MyHomePageState extends State<MyHomePage> {
Widget _buttonOne = RaisedButton(
onPressed: () {},
child: Text('Button One', style: TextStyle(fontSize: 20)),
);
final _textContainer =
const Text('Container One', textAlign: TextAlign.center);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CupertinoButton.filled(
child: Text('Button Two'),
onPressed: () {
print(_textContainer
.data); // how do I print the text of the text widget here?
print(((_buttonOne as RaisedButton).child as Text).data);
}),
],
),
),
);
}
}

I need hashtag sign in url launcher TEL, but it gets removed automatically

i want to dial this number as it is, in flutter url launcher but it removes the hashtag sign in the last bit of the String,
onTap: () {
String no = '*477*4*1#';
launch('tel:$no');
},
You can copy paste run full code below
You can use Uri.encodeComponent('*477*4*1#');
code snippet
onPressed: () {
String no = Uri.encodeComponent('*477*4*1#');
launch('tel:$no');
},
working demo
full code
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
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 _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text('click'),
onPressed: () {
String no = Uri.encodeComponent('*477*4*1#');
launch('tel:$no');
},
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
You need to use URL Encoding for special character so # is equals to \%23.

Using FontAwesomeIcons with value from custom class in Flutter

I'm trying to use fontawesome together with flutter. Depending on certain content of an Item I'd like to display a certain Icon from fontawesome.
Transaction(id: 1, title: 'lunch', amount: -23.10, type:'utensils'),
Transaction(id: 2, title: 'new shows', amount: -59.99, type:'tshirt'),
Transaction(id: 3, title: 'Falcon launch', amount: -62000000, type:'rocket')
so, I'd like to use the type as an indicator for my fontawesome icon.
When using FontAwesomeIcons.rocket, everything works quite well.
Column(children: <Widget>[
Card(
child: IconButton(
onPressed: null,
icon: new Icon(FontAwesomeIcons.rocket),
),
elevation: 0,
)
],),
since I'm using the map function I'm able to call the type itself without an issue like Text(tx.type). Is there a way to replace the static (in my case) rocket with the type from my transaction class? I'm trying to avoid if/switch cases at the moment just to get the basics going.
Any help very appreciated.
You can copy paste run full code below
You can use https://pub.dev/packages/icons_helper
just prefix rocket with fa.rocket
code snippet
Icon(getIconUsingPrefix(name: 'fa.rocket'),
color: Theme.of(context).backgroundColor, size: 60.0),
working demo
full code
import 'package:flutter/material.dart';
import 'package:icons_helper/icons_helper.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(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo + Icon Helper 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 _counter = 0;
Map iconMap = {"a":'fa.rocket'};
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(getIconUsingPrefix(name: 'fa.fiveHundredPx'),
color: Theme.of(context).backgroundColor, size: 60.0),
Icon(getIconUsingPrefix(name: 'fa.rocket'),
color: Theme.of(context).backgroundColor, size: 60.0),
Icon(getIconUsingPrefix(name: iconMap["a"]),
color: Theme.of(context).backgroundColor, size: 60.0),
Text(
'There should be an icon above. It\'s neat, isn\'t?\n\nYou can also push the + button and increment this counter for fun:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

How do I access BuildContext outside of a stateful or stateless widget?

I created a class that extends the AppBar class in Flutter so I can reuse it whenever I need it.
My problem is how do I access the Stateful/Stateless widget build context?
class AppBarLayout extends AppBar {
static final AppController _appController = new AppController();
final GlobalKey<ScaffoldState> _scaffoldKey;
final String appBarTitle;
AppBarLayout(this.appBarTitle,this._scaffoldKey): super(
title: Text(appBarTitle),
leading: IconButton(
onPressed: () => _scaffoldKey.currentState.openDrawer(),
iconSize: 28,
icon: Icon(Icons.menu,color: Colors.white),
),
actions: <Widget>[
IconButton(
onPressed: () => _appController.signOut().then((_) {
_appController.navigateTo(context, new GoogleSignView());
}),
icon: Icon(Icons.account_box),
padding: EdgeInsets.all(0.0),
),
],
);
}
You would need to wrap your Scaffold in a Staless or Stateful widget, so you can get the context, e.g.
import 'package:flutter/material.dart';
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();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBarLayout(GlobalKey(debugLabel: 'someLabel'), appBarTitle: 'The Title', context: context,),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class AppBarLayout extends AppBar {
final GlobalKey<ScaffoldState> _scaffoldKey;
final String appBarTitle;
final BuildContext context;
AppBarLayout(this._scaffoldKey, {this.appBarTitle, this.context}): super(
title: Text(appBarTitle),
leading: IconButton(
onPressed: () => _scaffoldKey.currentState.openDrawer(),
iconSize: 28,
icon: Icon(Icons.menu,color: Colors.white),
),
actions: <Widget>[
IconButton(
onPressed: () {
print('Button pressed');
},
icon: Icon(Icons.account_box),
padding: EdgeInsets.all(0.0),
),
],
);
}
Here I'm using a very similar Widget of what you have.