How to add icon property in button widget using class in flutter - flutter

I created a class of RoundedButton and call that class where I want a button. I added all required properties for a button. here is my class
import 'package:flutter/material.dart';
class RoundedButton extends StatelessWidget {
final String text;
final Function press;
final Color color, textColor;
final Icons icon;
const RoundedButton({
Key key,
this.text,
this.press,
this.color = Colors.grey,
this.icon,
this.textColor = Colors.white,
}) : super(key: key);
#override
Widget build(BuildContext context) {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
return Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(30.0),
color: Color(0xff01A0C7),
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: press,
child:Row(
children: <Widget>[
Icon(Icons.icon)),
Text(text,
textAlign: TextAlign.left,
style: style.copyWith(
color: Colors.white, fontWeight: FontWeight.bold)
),
],
)
// child: Text(text,
// textAlign: TextAlign.left,
// style: style.copyWith(
// color: Colors.white, fontWeight: FontWeight.bold)
// ),
),
);
}
}
here it calls look like
RoundedButton(text: "Time out",color: Colors.white,),),
So, when i call this RoundedButton i can change the properties value as required for each button, I want to change icon of buttons too, so my problem is i am not accessing icon variable on Icon(Icons.icon).
Kindly please help how to do this.

Just change the final Icons icon to the final Icon icon
and replace Icon(Icons.icon) with icon
to be like this :
import 'package:flutter/material.dart';
class RoundedButton extends StatelessWidget {
final String text;
final Function press;
final Color color, textColor;
final Icon icon;
const RoundedButton({
Key key,
this.text,
this.press,
this.color = Colors.grey,
this.icon = const Icon(Icons.ac_unit),
this.textColor = Colors.white,
}) : super(key: key);
#override
Widget build(BuildContext context) {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
return Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(30.0),
color: Color(0xff01A0C7),
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: press,
child: Row(
children: <Widget>[
icon,
Text(text,
textAlign: TextAlign.left,
style: style.copyWith(
color: Colors.white, fontWeight: FontWeight.bold)),
],
)
// child: Text(text,
// textAlign: TextAlign.left,
// style: style.copyWith(
// color: Colors.white, fontWeight: FontWeight.bold)
// ),
),
);
}
}

Solution
Just added this statement icon == null ? Container() : icon, on Amin Al-jebbeh solution
import 'package:flutter/material.dart';
//import 'package:attendance_system_app/new.dart';
class RoundedButton extends StatelessWidget {
final String text;
final Function press;
final Color color, textColor;
final Icon icon;
const RoundedButton({
Key key,
this.text,
this.press,
this.color = Colors.grey,
this.icon,
this.textColor = Colors.white,
}) : super(key: key);
#override
Widget build(BuildContext context) {
TextStyle style = TextStyle(fontFamily: 'Montserrat', fontSize: 20.0);
return Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(30.0),
color: Color(0xff01A0C7),
child: MaterialButton(
minWidth: MediaQuery.of(context).size.width,
padding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
onPressed: press,
child:Row(
children: <Widget>[
icon == null ? Container() :
icon,
Text(text,
textAlign: TextAlign.left,
style: style.copyWith(
color: Colors.white, fontWeight: FontWeight.bold)
),
],
)
// child: Text(text,
// textAlign: TextAlign.left,
// style: style.copyWith(
// color: Colors.white, fontWeight: FontWeight.bold)
// ),
),
);
}
}

Related

Flutter - Passing Information to custom Button Widget

I'm trying to make a Custom Button Widget to reuse it in my code.
Within my page I'm calling the button like this:
import 'package:app/components/MyCustomButton.dart';
[...]
const MyCustomButton(
title: 'Title of the button',
type: 'primary'
),
the complete Source of MyCustomButton is below. The Issue I'm having is when displaying Text that was defined in the MyCustomButton.dart file the button works perfectly fine. Now I don't want to display static text but instead text that I am passing from the screen file (e.g.: title variable)
When changing the static text
FROM TO
-------------------------------------------------------------------------------
const Text( -> const Text(
'Login', -> title,
style: TextStyle( -> style: TextStyle(
color: Colors.white, -> color: Colors.white,
fontSize: 20, -> fontSize: 20,
fontWeight: FontWeight.bold, -> fontWeight: FontWeight.bold,
), -> ),
), -> ),
from 'Login' to title (which I want to pass) the ide throws "Not a constant expression" at me, even if I'm changing it to const title. I'm thankful for any explaination on what I'm missing here and what I'm doing wrong.
Thanks a lot!
import 'package:flutter/material.dart';
class MyCustomButton extends StatelessWidget{
final String title;
final String type;
const MyCustomButton({
super.key,
required this.title,
required this.type,
});
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.fromLTRB(35, 15, 35, 15),
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: const BoxDecoration(
color: Color.fromRGBO(112, 143, 164, 1),
borderRadius: BorderRadius.all(Radius.circular(4)),
),
child: const Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
);
}
}
have you tried removing const from "const Text"?
child: Text(
title,
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
You are using super.key . Instead use Key? key.
Also,remove const keyword in your my page.
class MyCustomButton extends StatelessWidget {
final String title;
final String type;
const MyCustomButton({
Key? key,
required this.title,
required this.type,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.fromLTRB(35, 15, 35, 15),
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: const Color.fromRGBO(112, 143, 164, 1),
borderRadius: BorderRadius.circular(4),
),
child: Text(
title,
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
);
}
}
Buuton
class MyCustomButton extends StatelessWidget {
final Function() onTap;
final String title;
final String type;
const MyCustomButton({
super.key,
required this.title,
required this.type,
required this.onTap,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.fromLTRB(35, 15, 35, 15),
margin: const EdgeInsets.symmetric(horizontal: 20),
decoration: const BoxDecoration(
color: Color.fromRGBO(112, 143, 164, 1),
borderRadius: BorderRadius.all(Radius.circular(4)),
),
child: const Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
);
}
}
Calling
MyCustomButton(title: "title", type: "type", onTap: (){print("object");}),

Flutter 3: Invalid constant value. on onPressed value from another file, component

I'm very new to flutter I started Yesterday it seems easy but am stuck on using a component I created for CustomButtons
Here is my code.
CustomButtons components
import 'package:flutter/material.dart';
class CustomButton extends StatelessWidget {
const CustomButton({
Key? key,
required this.child,
this.outlineColor = Colors.transparent,
this.bgColor = const Color.fromARGB(39, 59, 148, 240),
this.btnVPadding = 14.0,
required this.onPressed,
this.buttonType = '',
}) : super(key: key);
final Widget child;
final Color outlineColor;
final Color bgColor;
final double btnVPadding;
final VoidCallback? onPressed;
final String buttonType;
#override
Widget build(BuildContext context) {
if (buttonType == 'OutlinedButton') {
return OutlinedButton(
style: OutlinedButton.styleFrom(
backgroundColor: bgColor,
padding: EdgeInsets.symmetric(vertical: btnVPadding),
side: BorderSide(
color: outlineColor,
),
),
onPressed: onPressed,
child: child,
);
}
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: bgColor,
padding: EdgeInsets.symmetric(vertical: btnVPadding),
elevation: 0,
),
onPressed: onPressed,
child: child,
);
}
}
And I call this class here..
import 'package:flutter/material.dart';
import 'package:util_app/components/buttons/button.dart';
class SignUp extends StatelessWidget {
const SignUp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Manage your Utilities"),
centerTitle: true,
elevation: 2.0,
),
body: _buildContent(),
);
}
Widget _buildContent() {
return Container(
color: const Color.fromARGB(255, 255, 255, 255),
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const <Widget>[
Text(
"Sign In",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 8.0),
CustomButton(
buttonType: '',
// the problem is here..
onPressed: () {},
child: Text(
"LOGIN",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
)
// button test
],
),
);
}
}
I get this error message
Invalid constant value.dart(invalid_constant)
The values in a const list literal must be constants.
Try removing the keyword 'const' from the list literal.dartnon_constant_list_element
I search and found this answer but it didn't help I tried most of the solutions provided but still nothing.
You can't use children: const <Widget>[ because CustomButton onPressed: () {}, will trigger on runtime. Remove this const from SignUp class Column
class SignUp extends StatelessWidget {
const SignUp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Manage your Utilities"),
centerTitle: true,
elevation: 2.0,
),
body: _buildContent(),
);
}
Widget _buildContent() {
return Container(
color: const Color.fromARGB(255, 255, 255, 255),
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
"Sign In",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32.0,
fontWeight: FontWeight.w600,
),
),
SizedBox(height: 8.0),
CustomButton(
buttonType: '',
onPressed: () {},
child: Text(
"LOGIN",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
)
// button test
],
),
);
}
}

Flutter : Persist Data

I am building an online shop. I have a counter[-]0[+] next to every product on the home page. I am able to add and remove products to the cart but when I switch to a different screen, my counter on the home page is reset back to 0. I would like to keep that data persistent. what would be the best way to achieve this?
cart_counter.dart
import 'package:flutter/material.dart';
import '../providers/cart.dart';
import 'package:provider/provider.dart';
import '../providers/products.dart';
class CartCounter extends StatefulWidget {
const CartCounter({Key? key}) : super(key: key);
#override
_CartCounterState createState() => _CartCounterState();
}
class _CartCounterState extends State<CartCounter> {
int numOfItems = 0;
#override
Widget build(BuildContext context) {
final product = Provider.of<Product>(context, listen: false);
final cart = Provider.of<Cart>(context, listen: false);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CounterButton(
icon: Icons.remove,
onPress: () {
if (numOfItems > 0) {
setState(() {
numOfItems--;
});
cart.removeSingleItem(product.id);
}
},
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 13.0),
child: Text(
numOfItems.toString(),
style: const TextStyle(
fontSize: 20.0,
),
),
),
CounterButton(
icon: Icons.add,
onPress: () {
setState(() {
numOfItems++;
cart.addItem(
product.id,
product.price,
product.title,
);
});
},
),
],
);
}
}
class CounterButton extends StatelessWidget {
final IconData icon;
final void Function() onPress;
const CounterButton({
Key? key,
required this.icon,
required this.onPress,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return SizedBox(
width: 60.0,
height: 45.0,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
elevation: 2,
backgroundColor: Theme.of(context).primaryColor,
primary: Theme.of(context).primaryColor,
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
onPressed: onPress,
child: Icon(
icon,
color: Colors.white,
size: 30.0,
),
),
);
}
}
product_item.dart
import 'package:flutter/material.dart';
import 'cart_counter.dart';
class ProductItem extends StatelessWidget {
final String id;
final String title;
final double price;
final String image;
const ProductItem(this.id, this.title, this.price, this.image, {Key? key})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: Card(
elevation: 2.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Column(
children: [
Row(
children: [
Container(
height: 50,
width: 70.0,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
color: Theme.of(context).primaryColor,
),
child: Center(
child: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
color: Colors.white,
),
),
),
),
],
),
Image.asset(image),
const SizedBox(
height: 10.0,
),
Text(
price.toStringAsFixed(2),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
const SizedBox(
height: 10.0,
),
const CartCounter(),
const SizedBox(
height: 20.0,
),
],
),
),
);
}
}
Use Shared Preferences or Secure Storage to store the values.
See this answer to a similar question.

How to get value from a list of values in flutter

I have three containers with different information(Strings and Icon) in each and that I want to put in a column.
I want to get the value of the clicked one and want to change the color of the container when clicked, how can I do that, please?
Also, I want to get the value of the strings selected
I think it's simple but I seem not to find a way to do that.
This is my Container widget:
class VisitTypeFees extends StatelessWidget {
const VisitTypeFees({
Key key,
this.onSelected = false,
this.title,
this.subTitle,
this.amount,
this.icon,
}) : super(key: key);
final bool onSelected;
final String title, subTitle, amount;
final IconData icon;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Container(
height: getProportionateScreenHeight(65),
width: SizeConfig.screenWidth - 20,
padding: EdgeInsets.symmetric(
horizontal: getProportionateScreenWidth(10),
vertical: getProportionateScreenWidth(7.5),
),
decoration: BoxDecoration(
color: onSelected ? kSecondaryColor : Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [kDefaultShadow]
),
child: Row(
children: [
Container(
height: getProportionateScreenHeight(50),
width: getProportionateScreenHeight(50),
decoration: BoxDecoration(
color: onSelected
? Colors.white
: kPrimaryLightColor.withOpacity(0.6),
borderRadius: BorderRadius.circular(10)),
child: Icon(
icon,
color: onSelected ? kSecondaryColor : kPrimaryColor,
),
),
SizedBox(
width: getProportionateScreenWidth(7.5),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
style: TextStyle(
color: onSelected ? Colors.white : Colors.black,
fontSize: getProportionateScreenWidth(15),
fontWeight: FontWeight.w600),
),
Text(
subTitle,
style: TextStyle(
color: onSelected ? Colors.white : kTextColor,
fontSize: getProportionateScreenWidth(12),
fontWeight: FontWeight.w500),
),
],
),
Spacer(),
Text(
amount,
style: TextStyle(
color: onSelected ? Colors.white : kPrimaryColor,
fontSize: getProportionateScreenWidth(15),
fontWeight: FontWeight.bold),
),
],
),
),
);
}
}
At first, you need to convert your widget to a StatefulWidget. Then, you need to wrap with InkWell widget for each Text and Icon widget. And they will all have isSelected properties themselves.
It will look like this:
class VisitTypeFees extends StatefulWidget {
const VisitTypeFees({
Key key,
this.onSelected = false,
this.title,
this.subTitle,
this.amount,
this.icon,
}) : super(key: key);
final bool onSelected;
final String title, subTitle, amount;
final IconData icon;
#override
_VisitTypeFeesState createState() => _VisitTypeFeesState();
}
class _VisitTypeFeesState extends State<VisitTypeFees> {
bool iconSelected;
bool firstTextSelected;
bool seccondTextSelected;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Container(
height: getProportionateScreenHeight(65),
width: SizeConfig.screenWidth - 20,
padding: EdgeInsets.symmetric(
horizontal: getProportionateScreenWidth(10),
vertical: getProportionateScreenWidth(7.5),
),
decoration: BoxDecoration(
color: widget.onSelected ? kSecondaryColor : Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [kDefaultShadow]),
child: Row(
children: [
InkWell(
onTap: () {
// icon selected!
setState(() {
iconSelected = true;
firstTextSelected = false;
seccondTextSelected = false;
});
},
child: Container(
height: getProportionateScreenHeight(50),
width: getProportionateScreenHeight(50),
decoration: BoxDecoration(
color: widget.onSelected
? Colors.white
: kPrimaryLightColor.withOpacity(0.6),
borderRadius: BorderRadius.circular(10)),
child: Icon(
widget.icon,
color: widget.onSelected ? kSecondaryColor : kPrimaryColor,
),
),
),
SizedBox(
width: getProportionateScreenWidth(7.5),
),
InkWell(
onTap: () {
// first text - title and subtitle selected!
setState(() {
iconSelected = false;
firstTextSelected = true;
seccondTextSelected = false;
});
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
widget.title,
style: TextStyle(
color: widget.onSelected ? Colors.white : Colors.black,
fontSize: getProportionateScreenWidth(15),
fontWeight: FontWeight.w600),
),
Text(
widget.subTitle,
style: TextStyle(
color: widget.onSelected ? Colors.white : kTextColor,
fontSize: getProportionateScreenWidth(12),
fontWeight: FontWeight.w500),
),
],
),
),
Spacer(),
InkWell(
onTap: () {
// second text - amount selected.
setState(() {
iconSelected = false;
firstTextSelected = false;
seccondTextSelected = true;
});
},
child: Text(
widget.amount,
style: TextStyle(
color: widget.onSelected ? Colors.white : kPrimaryColor,
fontSize: getProportionateScreenWidth(15),
fontWeight: FontWeight.bold),
),
),
],
),
),
);
}
}

Is there a way to change the Text color inside of a FlatButton when highlightColor of the button is changed?

I want to change the color of Text widgets text inside of a FlatButton when the FlatButtons highlight color changes. Higlight color of a FlatButton is changed when the user is pressing the button for a long time. Here is the example code of the button that I have:
class DefaultButton extends StatelessWidget {
const DefaultButton({
Key key,
this.text,
this.press,
this.buttonColor = primaryColor,
}) : super(key: key);
final String text;
final Function press;
final Color buttonColor;
#override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
height: 50,
child: FlatButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightColor: Colors.yellow,
color: buttonColor,
onPressed: press,
child: Text(
text,
style: TextStyle(
fontFamily: primaryFontFamily,
fontWeight: FontWeight.w400,
fontSize: 20,
color: primaryColor,
),
),
),
);
}
}
What is the best way to achieve this?
Thank you!
Don't know exactly how you use this FlatButton as Muhammad correctly point but the straightest solution is to use a boolean
FlatButton(
color: !pressed ? Colors.blue : Colors.amber,
onPressed: null,
onLongPress: () {
setState(() {
pressed = !pressed;
});
},
child: Text(
'text',
textAlign: TextAlign.left,
style: TextStyle(
color: pressed ? Colors.blue : Colors.amber,
fontWeight: FontWeight.w600,
fontSize: 14.0,
height: 1.2,
),
),
),
Then manage your state as you wish Bloc, StreamBuilder choose your poison