Cannot localize strings in Flutter TabBarView - flutter

When I try to localize a string in a TabBarView I get this error:
NoSuchMethodError: The method 'translate' was called on null. Receiver: null. Tried calling: translate("username).
I use this line of code to translate a key to a localized string:
AppLocalizations.of(context).translate('username')
This works great in all the other screens of my app except this one. Does anyone know why it's not working and how to solve it?
Some things I already tried:
pass the context of the main screen (the screen that holds all the TabBarViews)
wrap every ListTile in a Builder
wrap the ListView in a Builder
Code:
class AccountScreen extends StatelessWidget {
final String username;
final String email;
final int points;
AccountScreen(this.username, this.email, this.points);
#override
Widget build(BuildContext context) {
return Container(
child: Padding(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
ListTile(
title: Text(AppLocalizations.of(context).translate('username')),
subtitle: Text(username),
),
ListTile(
title:
Text(AppLocalizations.of(context).translate('email_address')),
subtitle: Text(email),
),
ListTile(
title: Text(AppLocalizations.of(context).translate('points')),
subtitle: Text('$points'),
),
],
),
),
);
}
}

I found same problem. But in my case is using MaterialApp without localizationsDelegates. (I mean all file not only main.dart).
So i add localizationsDelegates on every MaterialApp in all widget.
e.g.
MaterialApp(
localizationsDelegates: [
MainLocalizationsDelegate.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
home: DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
brightness: Brightness.light,
bottom: TabBar(
tabs: [
Tab(text: MainLocalizations.of(context).food),
Tab(text: MainLocalizations.of(context).car),
],
),
),
body: TabBarView(
children: [
TabA(),
TabB(),
],
),
),
),
);

The problem was that there were multiple MaterialApp widgets inside the app that were causing some conflicts regarding the localisation process. Removing the Redundant MaterialApp widgets fixed the issue.

Related

In Flutter, why Scaffold's body can't directly use Row()?

If I use Row() instead of Center(), it will not be displayed,just blank.
I expect a music player like layout.
Make 2 Row, the 1st Row contain "LeftMenu" and "Expanded Container" for content .
Putting this in scaffold gives you the left menu:
drawer: const Drawer(
child: Text("Left Menu")
),
Putting this inside scaffold body works. Expanded and a row:
Column(
children: [
Expanded(
child: Container(
color: Colors.green,
child: const Center(child: Text("1")),
)
),
Row(
children: const [
Text("1"),
SizedBox(width: 10),
Text("2"),
],
),
],
)
If you replace center with row, it probably displays but in the top left corner and not middle. Try to wrap your Row with Center and it should display in the middle. For the row you need to add a mainAxisAlignment.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center (child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children:[ Text('Left menu'),Text('Place container here')]
),),
),
);
}
}
This is actually the wrong question.
The real problem is: if the ListView is nested by Column, Row, it will not be displayed.
You need to use Expanded or Container on the outside and then nest it with Colmn or Row.

floatingActionButton (SpeedDial library)

How can I open SpeedDial in a horizontal way in my project like this?
If there are other libraries, that is fine.
You can also create your own custom floating action button. But since you are open to packages too writing an answer in which you can achieve it using a package
Try https://pub.dev/packages/custom_floating_action_button
Add this to pubspec.yaml
custom_floating_action_button: ^0.0.3
You can wrap the scaffold with CustomFloatingActionButton
//add custom floating action button on top of your scaffold
//minimum 2 and maximum 5 items allowed
#override
Widget build(BuildContext context) {
return CustomFloatingActionButton(
body: Scaffold(
appBar: AppBar(
title: const Text('appbar title'),
),
body: Container(),
),
options: const [
CircleAvatar(
child: Icon(Icons.height),
),
CircleAvatar(
child: Icon(Icons.title),
),
//All widgets that should appear ontap of FAB.
],
type: CustomFloatingActionButtonType.horizontal,
openFloatingActionButton: const Icon(Icons.add),
closeFloatingActionButton: const Icon(Icons.close),
);
}

Alignment properties doesn't work so I use empty expanded widget

I want make text to the right, what am I doing so far
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _judul = 'Private Chat';
static var _warnaTema = Colors.pink[100];
Widget _dummyExpanded() {
return Expanded(
child: Container(), //contain empty data,
); //just for fill remaining space
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _judul,
theme: ThemeData(
primaryColor: _warnaTema,
),
home: Column(
children: [
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 1'),
],
),
),
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 2'),
],
),
)
],
),
);
}
}
The layout output is what I expected (the text is in right), however there's unneeded code.
As you see I use unnecessary method _dummyExpanded to fill
available space which it's just expanded with empty container. Of course it will be hard to read since there are many nested row and column, how I remove that unneeded method without loss layout output what I expect?
I believe I should have use alignment but I don't know how to
Method 1.
Container(
child: Row(
mainAxisAlignment:MainAxisAlignment.end,
children: [
Text('this is real data 2'),
],
),
)
Method 2.
I prefer this method, You can wrap text with this method.
You can also use Flexible widget instead of Expanded
Container(
child: Row(
children: [
Expanded(child: Text('this is real data 2', textAlign:TextAlign.end )),
],
),
)
Method 3.
If you have only Text widgets as children of Column widget then you can set crossAxisAlignment: CrossAxisAlignment.end, for your parent Column widget.

how we can use two rows in appbar flutter Like first row with title and the second with search input field

Hi There I am working on a app where i need to use two sections in appbar one upper
1->section with logo and some Icons
2-> Search input field below the Title Section.
UI images are attached for better understanding.
you can customize the size of app bar by using toolbarHeight: 120.0 // set value
then use flexibleSpace to add column or rows
it will look something like this
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
toolbarHeight: 120.10, //set your height
flexibleSpace: SafeArea(
child: Container(
color: Colors.blue, // set your color
child: Column(
children: [
Row(
children: [Text("Logo")],
),
Text("data"), // set an icon or image
IconButton(
icon: Icon(Icons.search),
onPressed: () {}) // set your search bar setting
],
),
),
),
),
),
);
}
}
Just simply create your AppBar as intended, in your screenshot, you don't actually need a second Row. A TextFormField will be enough (you will actually need to customise the InputDecoration as well):
return AppBar(
title: Column(children: [
Row(children: [
Icon(Icons.menu),
Text('First row'),
const Spacer(),
Icon(Icons.person),
]),
TextFormField(),
]),
);
You can use the bottom property from the AppBar widget.
AppBar(
title: YourFirstRowWidget(),
centerTitle: true,
bottom: PreferredSize(
child: YourSearchBarWidget(),
preferredSize: null),
)
But you may want to create your own AppBar widget for a perfect result.

How can I switch from one page to another using an AppBars TabBar?

I've got a simple custom AppBar with the following code (I've taken out some code for simplification. It's not necessary for the question.):
class SimpleAppBarPageState extends StatelessWidget implements PreferredSizeWidget {
#override
Size get preferredSize => const Size.fromHeight(100);
#override
Widget build(BuildContext context) => DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
...
bottom: TabBar(
isScrollable: true,
indicatorColor: Colors.white,
indicatorWeight: 5,
tabs: [
Tab(child: Text('1',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 20,
),
),
),
Tab(child: Text('2',
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 20,
),
),
)
],
),
elevation: 20,
titleSpacing: 20,
),
body: TabBarView(
children: [
buildPageOne(),
buildPageTwo()
],
),
),
);
Now I have two dart files of which one contains the code for Page one and the other file contains the code for page two.
Now I want page one to be open when Tab '1' is selected and page two should be open when Tab '2' is selected.
Therefor I thought of defining a new Widget which opens the corresponding page. Here are my thoughts:
Widget buildPageOne() {
Navigator.of(context)
.push(
MaterialPageRoute(
builder: (context) => PageOne()
),
);
}
I think this last code sample is complete useless, but it kind of shows my intention what should happen.
Can you guys help me out to solve this problem?
I'd be very happy about an answer!
Greetings
First of all don't use Navigator if you are using Tabs.
Second you need a TabController to handle your Tabs e.g. you can use the DefaultTabController. With TabBar you can set the text/icon of each tab below the Appbar. Within your TabBarView you set your Widgets you want to display. In your case omit the Navigator and just provide the Widgets you want to display in TabBarView
DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: 'Tabs',
bottom: TabBar(
tabs:[
Tab(icon: Icon(Icons.home)),
Tab(icon: Icon(Icons.settings)),
],
),
),
body: TabBarView(
children: [
Widget1(),
Widget2()
]
),
),
);
Don't use methods to navigator to new screen.
Create 2 separate stateless or statefull widgets: Widget1(), Widget2(),
And in childrens of TabBarView use these 2 widgets as children.
body: TabBarView(
children: [
Widget1(),
Widget2(),
],
),
Save them, do a hot restart