I have a situation where my AppBar
in the Scaffold
needs to be changed when I switch page on the BottomNavigationBar
widget. One AppBar
is a plain AppBar(title: Text('Saved'))
and another is an AppBarTextField
widget ( https://pub.dev/packages/appbar_textfield ). From this one, I would like to keep the text that was already entered before the switch. However with the below code, everytime I return to the relative page, the bar has been reset:
import 'package:flutter/material.dart';
import 'package:gifs/screens/main/search.dart';
import 'package:gifs/screens/main/saved.dart';
import 'package:gifs/screens/main/search_appbar.dart';
import '../../models/search_result.dart';
class Navigation extends StatefulWidget {
Navigation({required Key key}) : super(key: key);
final SearchResult _searchResult = SearchResult();
late List<PreferredSizeWidget> _appBars = [
SearchAppBar(key: GlobalKey(debugLabel: 'search_appbar_ui'), searchResult: _searchResult),
AppBar(title: Text('Saved'))
];
late List<Widget> _pages = [
Search(key: GlobalKey(debugLabel: 'search_ui'), searchResult: _searchResult),
Saved(key: GlobalKey(debugLabel: 'saved_ui')),
];
@override
_NavigationState createState() => _NavigationState();
}
class _NavigationState extends State<Navigation> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: widget._appBars[_currentIndex],
body: IndexedStack(
index: _currentIndex,
children: widget._pages,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Saved'),
],
onTap: (index) => {
setState(() {
_currentIndex = index;
})
}
),
);
}
}
This is the SearchBar
code:
import 'package:flutter/material.dart';
import 'package:gifs/models/search_result.dart';
import 'package:appbar_textfield/appbar_textfield.dart';
class SearchAppBar extends StatefulWidget with PreferredSizeWidget {
final SearchResult searchResult;
const SearchAppBar({required Key key, required this.searchResult}) : super(key: key);
@override
_SearchAppBarState createState() => _SearchAppBarState();
@override
Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
class _SearchAppBarState extends State<SearchAppBar> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return AppBarTextField(
title: Text("Enter a search term"),
onBackPressed: _onRestoreAllData,
onClearPressed: _onRestoreAllData,
onChanged: _onSearchChanged,
);
}
void _onSearchChanged(String value) {
widget.searchResult.searchTerm(value);
}
void _onRestoreAllData() {
_onSearchChanged('');
}
}
As you can see I switch the _appBars
based on the index, but the text in the bar disappears after every single switch. Is there a way to keep its current status?
Try this: I wasn't able to run your own code but I tested out my solution in a starter flutter app and it worked (code provided at the very end)
This is your modified Navigation
widget code:
import 'package:flutter/material.dart';
import 'package:gifs/screens/main/search.dart';
import 'package:gifs/screens/main/saved.dart';
import 'package:gifs/screens/main/search_appbar.dart';
import '../../models/search_result.dart';
class Navigation extends StatefulWidget {
Navigation({required Key key}) : super(key: key);
@override
_NavigationState createState() => _NavigationState();
}
class _NavigationState extends State<Navigation> {
int _currentIndex = 0;
final SearchResult _searchResult = SearchResult();
List<PreferredSizeWidget> get _appBars => [
SearchAppBar(
key: GlobalKey(debugLabel: 'search_appbar_ui'),
searchResult: _searchResult,
setSearchResult: (String value) {
//set your string value of the SearchResult class
setState(() => _searchResult.term = value);
}
),
AppBar(title: Text('Saved'))
];
List<Widget> get _pages => [
Search(key: GlobalKey(debugLabel: 'search_ui'), searchResult: _searchResult),
Saved(key: GlobalKey(debugLabel: 'saved_ui')),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: widget._appBars[_currentIndex],
body: IndexedStack(
index: _currentIndex,
children: widget._pages,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Saved'),
],
onTap: (index) => {
setState(() {
_currentIndex = index;
})
}
),
);
}
}
Notes about what I did:
_appBars
and _pages
and _searchResult
variables into your state class and removed late initialization and made them getters. And this is your modified SearchAppBar
widget code:
import 'package:flutter/material.dart';
import 'package:gifs/models/search_result.dart';
import 'package:appbar_textfield/appbar_textfield.dart';
class SearchAppBar extends StatefulWidget with PreferredSizeWidget {
final SearchResult searchResult;
final ValueChanged<String> setSearchResult;
const SearchAppBar({required Key key, required this.searchResult, required this.setSearchResult}) : super(key: key);
@override
_SearchAppBarState createState() => _SearchAppBarState();
@override
Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
class _SearchAppBarState extends State<SearchAppBar> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return AppBarTextField(
title: Text("Enter a search term"),
onBackPressed: _onRestoreAllData,
onClearPressed: _onRestoreAllData,
onChanged: _onSearchChanged,
// Give your string value of the SearchResult class
// as an initial value to your text field.
// If this was a regular TextFormField() widget you would
// have been able to use the initialValue param, but I'm not
// sure if there's a better alternative than using the
// controller for this package
controller: TextEditingController()..text = widget.searchResult.term,
);
}
void _onSearchChanged(String value) {
widget.setSearchResult(value);
}
void _onRestoreAllData() {
_onSearchChanged('');
}
}
Notes about what I did:
widget.setSearchResult
function in the AppBarTextField
's onChanged
param to update the value in parent widgetwidget.searchResult
's string value as an initial value to the text field so that when you revisit the page it is assigned again to the text field and not lost.And this is my code in a sandbox app if you want to try it out: (put it in a dartpad and run it and you should see it working)
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String searchResult = '';
List<PreferredSizeWidget> get _appBars => [
SearchAppBar(
setSearchResult: (String value) =>
setState(() => searchResult = value),
searchResult: searchResult,
),
AppBar(title: const Text('Saved')),
];
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: _appBars[_selectedIndex],
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
backgroundColor: Colors.red,
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
backgroundColor: Colors.green,
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
class SearchAppBar extends StatefulWidget with PreferredSizeWidget {
final String searchResult;
final ValueChanged<String> setSearchResult;
const SearchAppBar({required this.setSearchResult, this.searchResult = ''});
@override
_SearchAppBarState createState() => _SearchAppBarState();
@override
Size get preferredSize => const Size.fromHeight(56);
}
class _SearchAppBarState extends State<SearchAppBar> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return TextFormField(
onChanged: _onSearchChanged,
controller: TextEditingController()..text = widget.searchResult,
// initialValue: widget.searchResult,
);
}
void _onSearchChanged(String value) {
widget.setSearchResult(value);
}
}
Hope this helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.