Expansion tile widget color on tap - flutter

When pressed on an ExpansionTile, I want to remove the color of the a press.
Widget:
ExpansionTile(
//..
)

It is possible to remove most color effects from the expansion tile. However, this is not achievable from the parameters available in the constructor. Wrapping the ExpansionTile in a Theme is required.
The code below removes the splash, hovering, highlighting and divider colors from the ExpansionTile.
class CustomExpansionTile extends StatelessWidget {
const CustomExpansionTile({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Theme(
data: ThemeData(
/// Prevents to splash effect when clicking.
splashColor: Colors.transparent,
/// Prevents the mouse cursor to highlight the tile when hovering on web.
hoverColor: Colors.transparent,
/// Hides the highlight color when the tile is pressed.
highlightColor: Colors.transparent,
/// Makes the top and bottom dividers invisible when expanded.
dividerColor: Colors.transparent,
/// Make background transparent.
expansionTileTheme: const ExpansionTileThemeData(
backgroundColor: Colors.transparent,
collapsedBackgroundColor: Colors.transparent,
),
),
child: const ExpansionTile(
title: Text("Title"),
children: [Text("Expanded")],
),
);
}
}

To remove the color on an ExpansionTile when it's pressed, you can set the backgroundColor property of the ExpansionTile to Colors.transparent.
ExpansionTile(
backgroundColor: Colors.transparent,
title: Text('Expansion Tile'),
children: [
.............
],
),

Related

Set default icon theme to cupertino flutter appbar

The app that im building requires me to have an AppBar with a leading back button. However I prefer the cupertino back button(iOS-style) for the leading icon instead of the default back button for android. I am aware that I can manually change the leading button of each AppBar by using an iconButton but i was wondering if there is any easy way to do this like a theme. Any help appreciated.
Instead of using MaterialApp as your root widget you can use CupertinoApp to do the same, assuming that the above changing of the AppBar is needed for each screen in your app. This will automatically set the icon as you require
Here is a simple example to help you
Root Widget or starting point of the app
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 CupertinoApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
Then using a CupertinoPageScaffold where you want the CupertinoNavigationBar (I mean your appbar with ios icons) with the chevron icon like ios
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
// Try removing opacity to observe the lack of a blur effect and of sliding content.
automaticallyImplyLeading: true // This will decide if the leading icon comes in by default
backgroundColor: CupertinoColors.systemGrey.withOpacity(0.5),
middle: const Text('Sample Code'),
),
child: Column(
children: <Widget>[
Container(height: 50, color: CupertinoColors.systemRed),
Container(height: 50, color: CupertinoColors.systemGreen),
Container(height: 50, color: CupertinoColors.systemBlue),
Container(height: 50, color: CupertinoColors.systemYellow),
],
),
);
Facing a relatively similar problem I used the builder property, which it should work with any App like :
CupertinoApp(
builder: (_, child) => IconTheme(
data: IconThemeData(
size: 15,
color: const Color(0xffffffff),
),
child: child,
),
)
My problem was with the default icon color and size but you can use AppBarTheme or any similar widget to achieve what you want.
This may help you override default value with majority of the lacking theme delegates when working with the cupertino family (It's not yet mature like the material but I can see the constant and rapid effort and the future of it).

Scrollable ListView bleeds background color to adjacent widgets

I'm looking to create a simple layout using a scrollable ListView, with an immovable header tile. I've placed the header tile and ListView into a Column, so the Header can be above the ListView without scrolling off the screen. However, when scrolling the ListView, my header tile seems to take on the color of whatever ListView tiles are scrolling "under" it.
On startup, the app looks like this:
However if we scroll half a tile down, the green color of the list tiles appears to push out the red from the header. The text from the green tiles does not have the same problem, and is properly occluded by the header tile
Minimal code for reconstruction
void main() => runApp(MyTestApp2());
class MyTestApp2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("AppBar Header"),
),
body: Column(children: <Widget>[
ListTile(
title: Center(child: Text("This Header Should be Red")),
tileColor: Colors.redAccent,
),
Expanded(child: ListView(
children: List.generate(20, (int index) => "List Item $index")
.map((n) => ListTile(
title: Text(n.toString()),
tileColor: Colors.lightGreen))
.toList(),
)),
])),
);
}
}
What is happening here? I could probably achieve this layout using different Widgets, but I would like to know Why is this color bleed effect occurring? How does it fit with the box layout model Flutter uses?
EDIT: The immediate problem can be solved by wrapping the red ListTile in a Container widget, and setting the color property to be red on that container, like this:
Container(
color: Colors.redAccent,
child: ListTile(....
However I would still like to know what is going on in terms of the layout algorithm in the original code, if anybody knows. Shouldn't the existence of the header tile prevent our listview from pushing its elements into the area owned by the red ListTile?
Please try wrapping listTile with Material widget
I do not know why but the tileColor is keeping alive under the widgets while scrolling down the color of the tile went under the widgets above.
Wrapping the listTile with Material should fix that for some reason.
Material(
child: ListTile(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
tileColor:const Color.fromARGB(255, 247, 247, 247),
leading: Icon(
Icons.monetization_on_outlined,
color: Theme.of(context).primaryColor,
size: 50,
),
title: Text(
"Some Strings",
),
subtitle: Text("Some Strings"),
onLongPress: () {},
onTap: () {},
),
)

AppBar reusable in different pages and route on different page effect

I cannot solve two issues with my reusable appbar.
Appbar has not the same width of the page.
Appbar shorter then page width
Text and Icons seems not centered vertically. It looks like the appbar had a border! (if i Move alignment I can seed the border. See picture 2.
see white icon on the right
When I cange page, It seems that an Appbar Is under The reusable Appbar. See picture 3.
Appbar under reusable Appbar
In every page I use this code to call the Appbar:
Widget build(BuildContext context) {
return Scaffold(
//backgroundColor: Colors.white,
appBar: AppBar(
title: ReusableBar(),
),
This is the code of the reusable AppBar:
class ReusableBar extends StatelessWidget implements PreferredSizeWidget{
#override
Widget build(BuildContext context) {
//number = number + displayedText;
return AppBar(
//elevation: 0.0,
centerTitle: true,
automaticallyImplyLeading: false,
titleSpacing: 0.0,
title: Text(getTranslated(context, 'total_click:') + "$_appbarcounter"),
actions: <Widget>[
IconButton(
alignment: Alignment(0.0, -4.0),
icon: Icon(
Icons.save,
color: Colors.white,
),
onPressed: () {
// do something
//TODO AGGIUNGERE FUNZIONE AL PULSANTE SAVE CON PAGINA DI SALVATAGGIO
},
)
],
// leading: GestureDetector(
// onTap: () { /* Write listener code here */ },
// child: Icon(
// Icons.menu, // add custom icons also
// ),
// ),
);
}
If you put your ReusableBar in the title property of AppBar it is wrapping an appbar inside another one. Like you mentionned in your comment you should implement your custom appbar like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: ReusableBar(),
);
}
Doing like this you only declare one appbar, which should solve your issue.

How to change the color of the back button in a CupertinoNavigationBar in Flutter

I would like to change the color of the back button in my flutter app.
Here is what I have at the moment: Screenshoot
I would like to change the color from light blu to white. I have searched online but found nothing. Here is my code (note my button is create automatically)
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
heroTag: 'menupage',
transitionBetweenRoutes: false,
middle: Text(
'Menu Page',
style: kSendButtonTextStyle,
),
),
Many thanks in advance !
I resolved with setting the CupertinoTextThemeData...
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return CupertinoApp(
theme: CupertinoThemeData(
primaryColor:
Colors.white, //change color of the BOTTOM navbar icons when selected
textTheme: CupertinoTextThemeData(
primaryColor:
Colors.white, //change color of the TOP navbar icon
Thanks Lucas for pointing me in the right direction
Example
actionsForegroundColor: Colors.white in CupertinoNavigationBar
Do it
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(actionsForegroundColor: Colors.white,
heroTag: 'menupage',
transitionBetweenRoutes: false,
middle: Text(
'Menu Page',
style: TextStyle(),
),
), child: Text(''),
);

Flutter - System bar colors with SafeArea

I am trying to add SafeArea widget for the flutter app with colorized system bars but somehow they are always turning black.
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: kSurfaceColor,
statusBarIconBrightness: Brightness.dark,
statusBarColor: Colors.red, // Note RED here
),
);
return SafeArea(
child: Scaffold(
backgroundColor: kWhiteColor,
appBar: _buildAppBar(context), // Title and Avatar are built here
body: _buildBody(), // This function just returns blank Container for now
floatingActionButton: _buildFAB(context),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
),
);
}
This is what I see
If I wrap SafeArea inside a Container with color property set to white, it works but system bar icons also turn white
Building on #david-carrilho's answer, I created this simple widget
import 'package:flutter/material.dart';
class ColoredSafeArea extends StatelessWidget {
final Widget child;
final Color color;
const ColoredSafeArea({Key key, #required this.child, this.color})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: color ?? Theme.of(context).colorScheme.primaryVariant,
child: SafeArea(
child: child,
),
);
}
}
Then wherever I would use a SafeArea, I use my little wrapper widget ColoredSafeArea.
class MyExampleView extends StatelessWidget {
const MyExampleView({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ColoredSafeArea(
child: Center(
child: Text('Nice color bar'),
),
);
}
}
The reason why this works is because it creates a container behind your content with the specified color, then SafeArea simply adds the necessary padding based on the device.
Container(
color ...
),
child: SafeArea(
child: Scaffold(
body:
AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: ...
I know this is an old question, but after reading the documentation I came up with a more complete solution.
My answer considers the following:
Don't wrap Scaffolds into SafeAreas;
[iOS] paint your Scaffold the right Color;
[Android] set the System Bars programmatically.
1. Proper use of SafeArea
SafeArea is a widget that performs a MediaQuery to add some proper padding to your application. This should happen inside the body of your Scaffold application. Something like this will lead to code that won't unexpectedly break later on:
return Scaffold(
// ...
body: SafeArea( // your SafeArea should stay here
child: YourWidget(),
),
);
2. iOS Notch
As other answers said already, you just have to paint your Scaffold so that you'll get the color you want. Your Scaffold should include a backgroundColor property (and your AppBar too, if you have one).
return Scaffold(
// ...
backgroundColor: yourColor, // the RED you need
appBar: AppBar( // if any
backgroundColor: yourColor, // maybe RED here, also
// a system overlay option is included here, too, see 3.
// ...
),
body: SafeArea( // your SafeArea should stay here
child: YourWidget(),
),
);
3. Android SystemUI
As OP did, you need SystemChrome.setSystemUIOverlayStyle() to address Android-related system bar paints.
However, the documentation says that this method should be called programmatically whenever a new page / a new route is being popped or pushed, if you have different Route colors.
Suppose you have a 2.0 Router; then, you would write its build method as it follows:
Widget build(BuildContext context) {
Color overlayColor = ... your color ...;
final systemBarColors = SystemUiOverlayStyle(
systemNavigationBarColor: overlayColor,
statusBarColor: overlayColor,
);
SystemChrome.setSystemUIOverlayStyle(systemBarColors);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: systemBarColors,
child: Navigator(
key: navigatorKey,
pages: _stack,
onPopPage: _onPopPage,
),
);
}
This will ensure that every time a new page is popped or pushed, i.e. the build method of our Router is called, the Android system bar and status bar are properly painted.
For your case just wrapping SafeArea() to the top widget that will be DISPLAYED on the screen(example: your 'Today' text widget) should avoid the black color on system bar.
Full example.
Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SafeArea(
child: Text('Today'),
),
Text('Tomorrow')
]
);
This worked for me!
Replace your Overlay style with below code it will work
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.dark.copyWith(statusBarColor: Colors.white));
set only main class
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
statusBarIconBrightness: Brightness.light,
statusBarColor: HexColor(HexColor.primarycolor), // Note RED here
),
);
my Example code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:loader_overlay/loader_overlay.dart';
import 'HexColor.dart';
class CityListActiviy extends StatefulWidget {
// Initially password is obscure
#override
State<CityListActiviy> createState() => _CityListActiviyState();
}
class _CityListActiviyState extends State<CityListActiviy> {
TextEditingController userid_Controller = new TextEditingController();
bool userid_validate = false;
final String requiredNumber = '123456';
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
systemNavigationBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
statusBarIconBrightness: Brightness.light,
statusBarColor: HexColor(HexColor.primarycolor), // Note RED here
),
);
return MaterialApp(
debugShowCheckedModeBanner: true,
home: LoaderOverlay(
child:SafeArea(
child: Scaffold(
backgroundColor: HexColor(HexColor.gray_activity_background),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Stack(
children: [
Container(
height: 60,
padding: new EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: HexColor(HexColor.white),
),
width: MediaQuery.of(context).size.width,
child: Text("Select Your Location",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.grey,
fontFamily: 'montserrat_medium',
decoration: TextDecoration.none,
))),
],
)
]),
)),
)
),
);
}
}