How do i change appbar when a button is clicked flutter? - flutter

i have a widget with an AppBar:
class CustomersView extends StatefulWidget {
#override
State<CustomersView> createState() => _CustomersViewState();
}
class _CustomersViewState extends State<CustomersView> {
#override
Widget build(BuildContext context) {
//final controller = Get.put(EServicesController());
return Scaffold(
appBar: AppBar(
toolbarHeight: 60,
backgroundColor: Colors.white,
title: Text(
"Customers".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 20,
fontWeight: FontWeight.w600),
),
actions: [
SearchButtonWidget(),
SettingsButtonWidget(),
],
centerTitle: false,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
// leading: new IconButton(
// icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
// onPressed: () => {Get.back()},
// ),
),
body: RefreshIndicator(
onRefresh: () async {
// Get.find<LaravelApiClient>().forceRefresh();
// await controller.refreshNotifications(showMessage: true);
// Get.find<LaravelApiClient>().unForceRefresh();
},
child: ListView(
primary: true,
children: <Widget>[
mainHeader(),
SizedBox(
height: 10,
),
CustomersCategoriesBuilder(current: current),
],
),
),
//floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
bottomNavigationBar: current == 0 ? SizedBox() : MessageCustomersButton(),
);
}
}
And i have another customized AppBar in another widget :
class MessageCustomersAppBar extends StatelessWidget with PreferredSizeWidget {
final bool isSecondStyleAppBar;
const MessageCustomersAppBar(this.isSecondStyleAppBar, {Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return AppBar(
toolbarHeight: 60,
backgroundColor: Colors.white,
title: Text(
"Customers".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 20,
fontWeight: FontWeight.w600),
),
actions: [
// SearchButtonWidget(),
// SettingsButtonWidget(),
],
centerTitle: false,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
leading: new IconButton(
icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
onPressed: () => {Get.back()},
),
);
}
#override
Size get preferredSize => Size.fromHeight(kToolbarHeight);
}
In the initial widget, i have a bottomNavigationBar that has a button MessageCustomersButton() and in the second CustomAppBar widget i have a leading
I want to switch AppBar to the CustomAppBar when this button is pressed ( i am using Getx ) & switch back to the Original AppBar when the leading button is pressed.
I have tried managing state myself but it looks like i am getting it wrong for the past days now.
Please i need help. Thank you!

You can change the AppBar in GetX using the OBX method. Below is the code for implementing those things.
1.View File
class CustomersView extends StatefulWidget {
#override
State<CustomersView> createState() => _CustomersViewState();
}
class _CustomersViewState extends State<CustomersView> {
#override
Widget build(BuildContext context) {
final controller = Get.put(AppBarController());
return Obx(
() => Scaffold(
appBar: controller.isChangeAppBar.value
? MessageCustomersAppBar()
: AppBar(
toolbarHeight: 60,
backgroundColor: Colors.white,
title: Text(
"Customers".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 20,
fontWeight: FontWeight.w600),
),
actions: [
SearchButtonWidget(),
SettingsButtonWidget(),
],
centerTitle: false,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
),
body: RefreshIndicator(
onRefresh: () async {},
child: ListView(
primary: true,
children: <Widget>[
mainHeader(),
SizedBox(
height: 10,
),
CustomersCategoriesBuilder(current: current),
],
),
),
bottomNavigationBar:
current == 0 ? SizedBox() : MessageCustomersButton(),
//here's the ontap method for the button
// () {
// controller.isChangeAppBar.value = !controller.isChangeAppBar.value;
// }
),
);
}
}
Your custom AppBar file remains the same.
GetX controller File:
class AppBarController extends GetxController {
Rx<bool> isChangeAppBar = false.obs;
}

Related

How do i switch Appbar title and child content with state-management in flutter?

I have a problem i have been struggling to get done for a day now
I want to dynamically switch appbar from this :
to this :
when a button is pressed.
The button is situated in the scaffold bottomNavigationBar of the first appbar widget.
I will give the code snippet of this particular widget.
I tried creating an entirely different widget and set the button onTap function to route to the new widget created.
This is not a suitable solution for me as i wish to just change state of the appbar as to avoid the weird transition when changing pages.
Also please note that the second image has a leading button that would enable the user to go back to the previous appbar.
How do i achieve this?
THIS IS THE CODE SNIPPET
import 'package:flutter/material.dart';
class CustomersView extends StatefulWidget {
#override
State<CustomersView> createState() => _CustomersViewState();
}
class _CustomersViewState extends State<CustomersView> {
List<String> items = [
"All",
"Inactive",
"One time",
"Loyal",
"Active",
];
int current = 0;
List<DropdownMenuItem<String>> get dropdownItems {
List<DropdownMenuItem<String>> menuItems = [
DropdownMenuItem(
child: Text(
"Today",
),
value: "Today"),
];
return menuItems;
}
#override
Widget build(BuildContext context) {
//final controller = Get.put(EServicesController());
return Scaffold(
appBar: AppBar(
toolbarHeight: 60,
backgroundColor: Colors.white,
title: Text(
"Customers".tr,
style: GoogleFonts.poppins(
color: Color(0xff000000),
fontSize: 20,
fontWeight: FontWeight.w600),
),
actions: [
SearchButtonWidget(),
SettingsButtonWidget(),
],
centerTitle: false,
elevation: 0,
automaticallyImplyLeading: false,
leadingWidth: 15,
// leading: new IconButton(
// icon: new Icon(Icons.arrow_back_ios, color: Color(0xff3498DB)),
// onPressed: () => {Get.back()},
// ),
),
body: RefreshIndicator(
onRefresh: () async {
// Get.find<LaravelApiClient>().forceRefresh();
// await controller.refreshNotifications(showMessage: true);
// Get.find<LaravelApiClient>().unForceRefresh();
},
child: ListView(
primary: true,
children: <Widget>[
mainHeader(),
SizedBox(
height: 10,
),
CustomersCategoriesBuilder(current: current),
],
),
),
//floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
bottomNavigationBar: current == 0 ? SizedBox() : MessageCustomersButton(),
);
}
//Button that controls the appbar state
class MessageCustomersButton extends StatelessWidget {
const MessageCustomersButton({
Key key,
this.value = false,
}) : super(key: key);
final bool value;
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FadeInDown(
child: MaterialButton(
onPressed: () {
//this is the new page route ( unsatisfied approach )
Get.toNamed(Routes.MESSAGE_CUSTOMERS);
},
color: Color(0xff34495E),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.18),
),
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10),
minWidth: double.infinity,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.chat,
size: 18,
color: Colors.white,
),
SizedBox(
width: 10,
),
Text(
'Message Customers',
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600),
),
],
),
),
),
),
);
}
}
Try creating the widget for AppBar only and handle the different states of AppBar there only by passing a flag like isSecondStyleAppBar then in your CustomersView widget, handle the flag using setState
class CustomAppBar extends StatelessWidget {
final bool isSecondStyleAppBar;
const CustomAppBar(this.isSecondStyleAppBar, {Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const AppBar();
}
}

Flutter Searchdelegate, i want to add background color and appbar color when i click the search

i can change my background color and app bar in home just fine, but when i click the search icon which uses search delegate it all back to white, how do i change the color? just to make it clear, so before the user clicked the search icon the background and app bar was black but when they clicked it it turned to white, how do i change it?
here is the search code :
import 'package:flutter/material.dart';
import 'package:movie_app_3/model/movie_response.dart';
import 'package:movie_app_3/screens/movie_detail_screen/movie_detail_screen.dart';
import '../model/movie.dart';
import '../repository/repository.dart';
class DataSearch extends SearchDelegate {
// void initState() {
// searchBloc..getSearch(query);
// }
final movieRepo = MovieRepository();
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () => query = '',
)
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow, progress: transitionAnimation),
onPressed: () => close(context, null),
);
}
#override
Widget buildResults(BuildContext context) {
return Container();
}
#override
Widget buildSuggestions(BuildContext context) {
if (query.isEmpty) return Container();
return FutureBuilder<MovieResponse>(
future: movieRepo.getSearch(query),
builder: (BuildContext context, AsyncSnapshot<MovieResponse> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.error != null && snapshot.data.error.length > 0) {
return _buildErrorWidget(snapshot.data.error);
}
return _buildHomeWidget(snapshot.data);
} else if (snapshot.hasError) {
return _buildErrorWidget(snapshot.error);
} else {
return _buildLoadingWidget();
}
},
);
}
Widget _buildHomeWidget(MovieResponse data) {
List<Movie> movies = data.movies;
return ListView.builder(
itemCount: movies.length,
itemBuilder: (context, index) {
return ListTile(
leading: FadeInImage(
image: movies[index].poster == null
? AssetImage('assets/images/no-image.jpg')
: NetworkImage("https://image.tmdb.org/t/p/w200/" +
movies[index].poster),
placeholder: AssetImage('assets/images/no-image.jpg'),
width: 50.0,
fit: BoxFit.contain),
title: Text(
movies[index].title,
style: TextStyle(fontFamily: 'Poppins'),
),
subtitle: Text(
movies[index].overview,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontFamily: 'Raleway'),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MovieDetailScreen(movie: movies[index]),
),
);
},
);
},
);
}
Widget _buildLoadingWidget() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 25.0,
width: 25.0,
child: CircularProgressIndicator(
valueColor: new AlwaysStoppedAnimation<Color>(Colors.black),
strokeWidth: 4.0,
),
)
],
));
}
Widget _buildErrorWidget(String error) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Error occured: $error"),
],
));
}
// #override
// Widget buildSuggestions(BuildContext context) {
// final suggestedList = (query.isEmpty) ?
// recentMovies :
// movies.where((movie) => movie.toLowerCase().contains(query.toLowerCase())).toList();
// return ListView.builder(
// itemCount: suggestedList.length,
// itemBuilder: (context, i) {
// return ListTile(
// leading: Icon(Icons.movie),
// title: Text(suggestedList[i]),
// onTap: () {},
// );
// },
// );
// }
}
here is the home code :
import 'package:flutter/material.dart';
import 'package:movie_app_3/widget/drawer.dart';
import 'package:movie_app_3/screens/home_screen/widget/home_screen1.dart';
import 'package:movie_app_3/screens/home_screen/widget/home_screen2.dart';
import 'package:movie_app_3/widget/search.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: 2);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.black,
Color(0xff112339),
Colors.black,
],
),
),
child: DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0,
title: Text(
'Moviez',
style: TextStyle(
fontSize: 24,
color: Colors.white,
fontFamily: 'Poppins',
),
),
backgroundColor: Colors.transparent,
centerTitle: true,
actions: [
Padding(
padding: EdgeInsets.only(right: 20),
child: IconButton(
icon: Icon(Icons.search),
onPressed: () {
showSearch(context: context, delegate: DataSearch());
},
),
),
],
bottom: TabBar(
controller: _tabController,
indicatorColor: Colors.white,
indicatorSize: TabBarIndicatorSize.tab,
indicatorWeight: 2.0,
tabs: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'Discover',
style: TextStyle(fontSize: 16, fontFamily: 'Raleway'),
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
'Genres',
style: TextStyle(fontSize: 16, fontFamily: 'Raleway'),
),
),
],
),
),
drawer: MyDrawer(),
body: TabBarView(
controller: _tabController,
children: <Widget>[
FirstTab(),
SecondTab(),
],
),
),
),
);
}
}
For customizing the Search Delegate, you have to override a method called appBarTheme and then set your custom theme on that.
** NOTE: When you override appBarTheme of SearchDelegate you have to customize evrything related to SearchBar yourself. Just like the code below. **
Do this to change the AppBar Color:
#override
ThemeData appBarTheme(BuildContext context) {
return ThemeData(
appBarTheme: const AppBarTheme(
color: MyColors.mainColor, // affects AppBar's background color
hintColor: Colors.grey, // affects the initial 'Search' text
textTheme: const TextTheme(
headline6: TextStyle( // headline 6 affects the query text
color: Colors.white,
fontSize: 16.0,
fontWeight: FontWeight.bold)),
),
);
}
And for changing the background color of suggestions:
#override
Widget buildSuggestions(BuildContext context) {
return Container(
color: Colors.black,
...
);
}
Similarly do this for results:
#override
Widget buildResults(BuildContext context) {
return Container(
color: Colors.black,
...
);
}
Hope this helps.
Add this to your "DataSearch" class
class _SearchDelegate extends SearchDelegate {
#override
ThemeData appBarTheme(BuildContext context) {
return Theme.of(context).copyWith(
scaffoldBackgroundColor: Colors.green,
);
}
If you already set your MaterialApp theme you can simply use Theme.of(context).copywith to remain body theme. Then you can override appBarTheme to change desired color/styles.
#override
ThemeData appBarTheme(BuildContext context) {
return Theme.of(context).copyWith(
//scaffoldBackgroundColor: , to change scaffold color
appBarTheme: const AppBarTheme( //to change appbar
color: Colors.black,
//titleTextStyle: , to change title text
//toolbarTextStyle: , to change toolbar text style
),
);

flutter: is there an easy way to layout my app bar?

I'm new to flutter so please bear with me. When I implement an app bar, sometimes it only has a title, some other time it has a title and returns button on the left of the bar, also, sometimes it adds another button on the right of the bar. I have to layout differently to suit different situations which are quite troublesome. Is there a convenient widget that provides three optional properties to allow me to set my title, left button, and right button or any good layout strategy? What I have done is below.
AppBar(
backgroundColor: Colors.gray,
elevation: 0.0,
title: Container(
alignment: Alignment.bottomCenter,
child: Container(
margin: EdgeInsets.only(bottom: ScreenUtil.dp(11)),
height: ScreenUtil.dp(22),
width: ScreenUtil.dp(160),
child: Text(
'title',
style: TextStyle(
fontSize: ScreenUtil.sp(17), fontFamily: FontFamily.family, color: Colors.black, fontWeight: FontWeight.w600
)
),
alignment: Alignment.center,
),
),
),
),
```
You should learn more about the Appbar with other properties to assist with the things you need like leading, trailing, ...
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: _title,
home: MyStatelessWidget(),
);
}
}
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
final SnackBar snackBar = const SnackBar(content: Text('Showing Snackbar'));
void openPage(BuildContext context) {
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Next page'),
),
body: const Center(
child: Text(
'This is the next page',
style: TextStyle(fontSize: 24),
),
),
);
},
));
}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
leading: Icon(Icons.navigate_next),
title: const Text('AppBar Demo'),
centerTitle: true,
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_alert),
tooltip: 'Show Snackbar',
onPressed: () {
scaffoldKey.currentState.showSnackBar(snackBar);
},
),
IconButton(
icon: const Icon(Icons.navigate_next),
tooltip: 'Next page',
onPressed: () {
openPage(context);
},
),
],
),
body: const Center(
child: Text(
'This is the home page',
style: TextStyle(fontSize: 24),
),
),
);
}
}

DropDownMenuItem Text Is Huge and Double Underlined

My drop down button shows abnormally large text and has this weird double underline. I did some googling prior and people were saying to make sure you Material at the root. I've made this adjustment and it didn't seem to fix the issue. Any idea what could be the problem?
?
class FormsPage extends StatefulWidget {
#override
_FormsPageState createState() => _FormsPageState();
}
class _FormsPageState extends State<FormsPage> {
WebViewController _controller;
FormUrls _selectedForm;
#override
Widget build(BuildContext context) {
return Material(
child: WillPopScope(
onWillPop: () async => false,
child: Scaffold(
appBar: AppBar(
title: Text("Forms"),
actions: <Widget>[
Theme(
data: Theme.of(context).copyWith(
canvasColor: MobileColors.lightBlue,
),
child: _buildDropDown(),
),
],
),
drawer: AwesomeDrawer(context, "FormsPage"),
body: _buildWebView(),
),
),
);
}
_buildDropDown() {
return DropdownButton<FormUrls>(
underline: Container(),
value: _selectedForm,
hint: Text(
'Cycle through forms',
style: TextStyle(color: Colors.white),
),
icon: Icon(
Icons.arrow_downward,
color: Colors.white,
),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.black),
onChanged: (newForm) {
setState(() {
_selectedForm = newForm;
});
setState(() {
_controller.loadUrl(_selectedForm.formUrl);
});
},
items: Client.formUrls.map<DropdownMenuItem<FormUrls>>((value) {
return DropdownMenuItem<FormUrls>(
value: value,
child: Text(
value.title,
style: TextStyle(color: Colors.white),
),
);
}).toList(),
);
}
}

Create reusable appBar in flutter

I am trying to create a reusable appBar in my flutter app. The right bar button of the appbar should be controlled from main UI where it is added. I am able to create appBar and use it but I am not able to change the text color of the button on the appbar. Following is my code for creating appBar:
class SocialAppBar extends StatefulWidget implements PreferredSizeWidget {
AppBarConfig appBarConfig;
bool isEnabled = false;
VoidCallback rightButtonClickCallback;
SocialAppBar({#required this.appBarConfig, #required this.rightButtonClickCallback});
#override
State<StatefulWidget> createState() {
return SocialAppBarState();
}
#override
Size get preferredSize => new Size.fromHeight(kToolbarHeight);
}
class SocialAppBarState extends State<SocialAppBar> {
#override
Widget build(BuildContext context) {
return getAppBarWithProfilePic();
}
Widget getAppBarWithProfilePic() {
return AppBar(
brightness: Brightness.light,
backgroundColor: Colors.white,
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
key: const Key("backButton"),
onPressed: () {
Navigator.pop(context);
}),
iconTheme: const IconThemeData(
color: Colors.black54, //change your color here
),
titleSpacing: 0.0,
title: Row(
children: <Widget>[
buildAvatar(),
const SizedBox(
width: 15,
),
Text(widget.appBarConfig.fullName,
style: TextStyle(color: AppColor.appbarTitleSecondaryColor, fontWeight: FontWeight.w400))
],
),
actions: <Widget>[
Container(
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(left: 20, right: 20),
child: InkWell(
child: AutoSizeText(
AppLocalizations.of(context).translate(GlobalString.labelNext),
style: TextStyle(color: widget.isEnabled ? AppColor.blue : AppColor.greyMediumDark, fontSize: 16),
textAlign: TextAlign.center,
),
onTap: widget.rightButtonClickCallback,
))
],
);
}
setNextButtonColor(){
setState(() {
});
}
}
I am using the above appBar like following in my screen:
void initState() {
super.initState();
appBar = SocialAppBar(appBarConfig: appBarConfig, rightButtonClickCallback: nextButtonClick);
//Next button on app bar should be enabled when following textController has any text
_textController.addListener((){
if (_textController.text.length > 0){
appBar.isEnabled = true;
}else {
appBar.isEnabled = false;
}
});
}
#override
Widget build(BuildContext context) {
return BlocBuilder(
bloc: _createPostBloc,
builder: (context, state) {
if (state is CreatePostNextState) {}
return Scaffold(
appBar: this.appBar,
key: _scaffoldKey,
backgroundColor: Colors.white,
body: buildPageView(),
);
},
);
}
I am able to set the Next button enable/disable with the above code but unable to change the color from Gray to Blue.
Regards
reusable AppBar:
Widget appBar(String text, IconButton iconButton) {
return AppBar(
title: Text(
text,
style: AppTheme.screenTitleStyle(),
),
centerTitle: true,
leading: IconButton(icon: iconButton, onPressed: () {}),
backgroundColor: AppTheme.mainThemeColor(),
brightness: Brightness.dark,
);
}
Use this appBar in Activity like this :
appBar: appBar(
"Change Password",
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
},
),
),
Simple fix:
_textController.addListener((){
setState(() {
if (_textController.text.length > 0){
appBar.isEnabled = true;
}else {
appBar.isEnabled = false;
}
});
});