onHover effect doesn't work on TextButton nor InkWell - flutter

I am developing a Flutter website. I have some links that I want to behave as a normal link: with a different color when the user hovers over them. However, I can't manage to make the color change.
I have tried using a TextButton with the onHover property. I have also tried with an Inkwell onHover property and hoverColor. I have wrapped the InkWell with Material and my onTap function is defined. I have also tried by wrapping this on an AnimatedContainer, but nothing seems to work.
Here is my code.
TextStyle? bodyTextStyle = Theme.of(context).textTheme.bodySmall;
InkWell(
color: Colors.transparent,
child: Text(
"data policy",
style: bodyTextStyle,
),
onTap: () => Navigator.of(context).pushNamed(
Navigation(context).routes["data policy"]),
onHover: (isHovering) {
setState(() {
bodyTextStyle = isHovering
? bodyTextStyle?.copyWith(
color: Theme.of(context).colorScheme.outline)
: bodyTextStyle;
});
},
),
I prefer using InkWell rather than TextButton in order to get rid of the shadow around the text that TextButton creates.

You can follow this snippet, hoverColor from InkWell can overlap.
InkWell(
child: SizedBox(
width: 100,
height: 100,
child: Text(
"Text",
style: linkTextStyle,
)),
onTap: () {},
hoverColor: Colors.transparent, //button splash color
onHover: (isHovering) {
linkTextStyle = isHovering
? TextStyle(color: Colors.red)
: TextStyle(color: Colors.cyanAccent);
setState(() {});
},
),
Also You can check MouseRegion, elevation on buttonStyle.

Related

Ignore onTap action on Transparent part of the svg image flutter

Issue is that their are multiple svg images in stack. I need them to trigger only when the user tapped on filled part of the svg. So that, when it ignores on transparent part of the image, it can able to trigger behind svg image.
Stack(
children: [
GestureDetector(
onTap: () => updateSelectedPart(1),
child: SvgPicture.asset(
'assets/images/1.svg',
color: selectedPart == 1
? Colors.red
: Colors.blue,
),
),
GestureDetector(
onTap: () => updateSelectedPart(2),
behavior: HitTestBehavior.translucent,
child: SvgPicture.asset(
'assets/images/2.svg',
color: selectedPart == 2
? Colors.red
: Colors.blue,
),
),
GestureDetector(
onTap: () => updateSelectedPart(3),
behavior: HitTestBehavior.deferToChild,
child: AbsorbPointer(
absorbing: true,
child: SvgPicture.asset(
'assets/images/3.svg',
excludeFromSemantics: true,
clipBehavior: Clip.none,
color: selectedPart == 3
? Colors.red
: Colors.blue,
),
),
),
],
)
Ordering is bottom to top so you will need to adjust (change order in the stack) so that what might overlay another SVGs transparent part gets triggered on an action (click/touch event) not the SVG below it (Above it in this case as its bottom to top)

Error: no named parameter with the name 'color' Flutter

So I'm new to Dart & Flutter and have run across a problem. I'm trying to learn the layout and make subtle UI changes to text & button widgets. Here I'm trying to change the color of the ElevatedButton to blue
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
child: ElevatedButton(
color: Colors.blue,
child: Text('Answer 1'),
onPressed: null,
),
);
}
}
When I run the code I get this error:
Error: no named parameter with the name 'color'
I thought with buttons there were color parameters that you could change. What would be the correct way of implementing this?
You can style ElevatedButton by using the styleFrom
ElevatedButton(
child: const Text('Button'),
onPressed: () {},
style: ElevatedButton.styleFrom(
primary: Colors.purple,
),
or you can use ButtonStyle class
ElevatedButton(
child: const Text('Button'),
onPressed: () {},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red),
),
ElevatedButton(
style: ElevatedButton.styleFrom({
Color primary, // set the background color
Color onPrimary, // foreground
}),
),
In Flutter, Some widget deal with styles and themes for general app theme purposes, because of that it doesn't allow for changing the color directly, but with style parameters:
ElevatedButton(
style: ElevatedButton.styleFrom({
Color primary: Colors.green,
Color onPrimary: Colors.white,
}),
),
For more information please visit Flutter documents ElevatedButton.styeFrom and experiment with different parameters.
Welcome to Flutter.
You can style ElevatedButton by :
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty
.all<Color>(Colors.blue),
foregroundColor: MaterialStateProperty
.all<Color>(Colors.white),
),
child: Text('your text'),
onPressed: null,
),
Update your flutter SDK. That happened as SDK is not updated.
To update your flutter SKD, open CMD from windows and command "flutter upgrade".

Flutter how to change SVG after onTap with Gesture Detector

Wanna implement same functionality that is done here with images:
Flutter how to change image after onTap with Gesture Detector
Im using this package:
https://pub.dev/packages/flutter_svg/example
Even though I'm able to do this in IconButton, I need this in GestureDetector, not in IconButton, so just to be clear, need help how to implement SVG into GestureDetector not IconButton!
I'm able to get SVG rendered on the screen but can't figure it out how to implement it in GestureDetector, to render SVG on screen, Im doing it like this:
Expanded svgTest({double blackKeyWidth}) {
return Expanded(
child: Container(
child: IconButton(
icon: SvgPicture.asset(
'assets/images/1.svg',
fit: BoxFit.fill,
allowDrawingOutsideViewBox: true,
width: 500,
),
onPressed: null //do something,
),
),
);
}
Cant figure out how to implement SVG in GestureDetector, it can't go in as Image and Gesture Detector doesn't accept icon, or Im not doing it right.
Thank
If you want to change the image on the onTap method of the iconButton then you should have to change the path of the image in onTap method using setState
String imagePath = "assets/images/1.svg";
Expanded svgTest({double blackKeyWidth}) {
return Expanded(
child: Container(
child: IconButton(
icon: SvgPicture.asset(
'${imagePath}',
fit: BoxFit.fill,
allowDrawingOutsideViewBox: true,
width: 500,
),
onPressed: (){
setState(() {
imagePath = "assets/images/2.svg";
});
},
),
),
);
}
EDITED: (For Gesture Detector You Can Simply Wrap the SVG in it)
Replace the iconbutton with the GestureDetector and Add its onTap and onTapUp methods too.
GestureDetector(
onTap: () {
setState(() {
imagePath = "assets/images/2.svg";
});
},
onTapUp: (TapUpDetails tapUpDetails) {
setState(() {
imagePath = "assets/images/1.svg";
});
},
child: SvgPicture.asset(
'${imagePath}',
//fit: BoxFit.fill,
//allowDrawingOutsideViewBox: true,
//width: 500,
),
),
For More About GestureDetector and Flutter SVG Click Here

flutter how to change the color of a button on a click

I am trying to change the color of the button when I click on it. Can you help me because I really can't do it. Thank you.
Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new MaterialButton(
child: new Text("1"),
color: Colors.greenAccent,
splashColor: Colors.red,
onPressed: (){
test=0;
test=1;
},
),
new MaterialButton(
child: new Text("2"),
color: Colors.greenAccent,
onPressed: (){
test=0;
test=2;
},
Try like this
Color mySplashColor=Colors.blue; //define in build function or state class
splashColors: mySplashColor,
onPressed(){
setState(){
splashColors=Colors.red;
}
}
The way to do it is by using state. The first thing you should do is to transform your widget into a stateful widget.
After that you set a state variable of type Color called buttonColor to have the default value of "Colors.greenAccent". You then set your MaterialButton color property to this variable.
The only thing to do now is to use () => setState(() => buttonColor = Colors.red ) as the button onPressed property.

How do I remove Flutter IconButton big padding?

I want to have a row of IconButtons, all next to each other, but there seems to be pretty big padding between the actual icon, and the IconButton limits. I've already set the padding on the button to 0.
This is my component, pretty straightforward:
class ActionButtons extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.lightBlue,
margin: const EdgeInsets.all(0.0),
padding: const EdgeInsets.all(0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
IconButton(
icon: new Icon(ScanrIcons.reg),
alignment: Alignment.center,
padding: new EdgeInsets.all(0.0),
onPressed: () {},
),
IconButton(
icon: new Icon(Icons.volume_up),
alignment: Alignment.center,
padding: new EdgeInsets.all(0.0),
onPressed: () {},
)
],
),
);
}
}
I want to get rid of most of the light blue space, have my icons start earlier on the left, and closer to each other, but I can't find the way to resize the IconButton itself.
I'm almost sure this space is taken by the button itself, 'cause if I change their alignments to centerRight and centerLeft they look like this:
Making the actual icons smaller doesn't help either, the button is still big:
thanks for the help
Simply pass an empty BoxConstrains to the constraints property and a padding of zero.
IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
)
You have to pass the empty constrains because, by default, the IconButton widget assumes a minimum size of 48px.
Two ways to workaround this issue.
Still Use IconButton
Wrap the IconButton inside a Container which has a width.
For example:
Container(
padding: const EdgeInsets.all(0.0),
width: 30.0, // you can adjust the width as you need
child: IconButton(
),
),
Use GestureDetector instead of IconButton
You can also use GestureDetector instead of IconButton, recommended by Shyju Madathil.
GestureDetector( onTap: () {}, child: Icon(Icons.volume_up) )
It's not so much that there's a padding there. IconButton is a Material Design widget which follows the spec that tappable objects need to be at least 48px on each side. You can click into the IconButton implementation from any IDEs.
You can also semi-trivially take the icon_button.dart source-code and make your own IconButton that doesn't follow the Material Design specs since the whole file is just composing other widgets and is just 200 lines that are mostly comments.
Wrapping the IconButton in a container simply wont work, instead use ClipRRect and add a material Widget with an Inkwell, just make sure to give the ClipRRect widget enough border Radius 😉.
ClipRRect(
borderRadius: BorderRadius.circular(50),
child : Material(
child : InkWell(
child : Padding(
padding : const EdgeInsets.all(5),
child : Icon(
Icons.favorite_border,
),
),
onTap : () {},
),
),
)
Instead of removing a padding around an IconButton you could simply use an Icon and wrap it with a GestureDetector or InkWell as
GestureDetector(
ontap:(){}
child:Icon(...)
);
Incase you want the ripple/Ink splash effect as the IconButton provides on click wrap it with an InkWell
InkWell(
splashColor: Colors.red,
child:Icon(...)
ontap:(){}
)
though the Ink thrown on the Icon in second approach wont be so accurate as for the IconButton, you may need to do some custom implementation for that.
Here's a solution to get rid of any extra padding, using InkWell in place of IconButton:
Widget backButtonContainer = InkWell(
child: Container(
child: const Icon(
Icons.arrow_upward,
color: Colors.white,
size: 35.0,
),
),
onTap: () {
Navigator.of(_context).pop();
});
I was facing a similar issue trying to render an Icon at the location the user touches the screen. Unfortunately, the Icon class wraps your chosen icon in a SizedBox.
Reading a little of the Icon class source it turns out that each Icon can be treated as text:
Widget iconWidget = RichText(
overflow: TextOverflow.visible,
textDirection: textDirection,
text: TextSpan(
text: String.fromCharCode(icon.codePoint),
style: TextStyle(
inherit: false,
color: iconColor,
fontSize: iconSize,
fontFamily: icon.fontFamily,
package: icon.fontPackage,
),
),
);
So, for instance, if I want to render Icons.details to indicate where my user just pointed, without any margin, I can do something like this:
Widget _pointer = Text(
String.fromCharCode(Icons.details.codePoint),
style: TextStyle(
fontFamily: Icons.details.fontFamily,
package: Icons.details.fontPackage,
fontSize: 24.0,
color: Colors.black
),
);
Dart/Flutter source code is remarkably approachable, I highly recommend digging in a little!
A better solution is to use Transform.scale like this:
Transform.scale(
scale: 0.5, // set your value here
child: IconButton(icon: Icon(Icons.smartphone), onPressed: () {}),
)
You can use ListTile it gives you a default space between text and Icons that would fit your needs
ListTile(
leading: Icon(Icons.add), //Here Is The Icon You Want To Use
title: Text('GFG title',textScaleFactor: 1.5,), //Here Is The Text Also
trailing: Icon(Icons.done),
),
I like the following way:
InkWell(
borderRadius: BorderRadius.circular(50),
onTap: () {},
child: Container(
padding: const EdgeInsets.all(8),
child: const Icon(Icons.favorite, color: Colors.red),
),
),
enter image description here
To show splash effect (ripple), use InkResponse:
InkResponse(
Icon(Icons.volume_up),
onTap: ...,
)
If needed, change icons size or add padding:
InkResponse(
child: Padding(
padding: ...,
child: Icon(Icons.volume_up, size: ...),
),
onTap: ...,
)