add a method ontap() in my listview in flutter - flutter

for adding a method ontap() in my listview with a custom class that I made for it look of a tile
i tried adding ontap(): but don't recognized it says
here is the code
class _MenuCard extends StatelessWidget {
final String headImageAssetPath;
final IconData icon;
final Color iconBackgroundColor;
final String title;
final String subtitle;
final int heartCount;
_MenuCard({
this.headImageAssetPath,
this.icon,
this.iconBackgroundColor,
this.title,
this.subtitle,
this.heartCount,
});
#override
Widget build(BuildContext context) {
return new Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
child: new Card(
elevation: 10.0,
child: new Column(
children: [
new Image.asset(
headImageAssetPath,
width: double.infinity,
height: 100.0,
fit: BoxFit.cover,
),
new Row(
children: [
new Padding(
padding: const EdgeInsets.all(15.0),
child: new Container(
padding: const EdgeInsets.all(10.0),
decoration: new BoxDecoration(
color: iconBackgroundColor,
borderRadius: new BorderRadius.all(const Radius.circular(15.0)),
),
child: new Icon(
icon,
color: Colors.white,
),
),
),
new Expanded(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Text(
title,
style: const TextStyle(
fontSize: 25.0,
fontFamily: 'mermaid',
),
),
new Text(
subtitle,
style: const TextStyle(
fontSize: 16.0,
fontFamily: 'bebas-neue',
letterSpacing: 1.0,
color: const Color(0xFFAAAAAA),
),
),
],
),
),
new Container(
width: 2.0,
height: 70.0,
decoration: new BoxDecoration(
gradient: new LinearGradient(
colors: [
Colors.white,
Colors.white,
const Color(0xFFAAAAAA),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
),
new Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: new Column(
children: [
new Icon(
Icons.favorite_border,
color: Colors.red,
),
new Text(
'$heartCount',
),
],
),
),
],
),
],
),
),
);
}
}
this code is of class that I use to build my listview in the scaffold of the stateless widget.
and here is how I am building my listview after returning scaffold in body:
the code is below
body: new ListView(
children: [
new _MenuCard(
headImageAssetPath: 'images/img.png',
icon: Icons.fastfood,
iconBackgroundColor: Colors.orange,
title: 'il domacca',
subtitle: "78 5TH AVENUE, NEW YORK",
heartCount: 84
),
new _MenuCard(
headImageAssetPath: 'images/img.png',
icon: Icons.local_dining,
iconBackgroundColor: Colors.red,
title: 'Mc Grady',
subtitle: "79 5TH AVENUE, NEW YORK",
heartCount: 84
),
new _MenuCard(
headImageAssetPath: 'images/img.png',
icon: Icons.fastfood,
iconBackgroundColor: Colors.purpleAccent,
title: 'Sugar & Spice',
subtitle: "80 5TH AVENUE, NEW YORK",
heartCount: 84
),
]
),

You can wrap you custom list item widget inside a GestureDetector which has an onTap callback method you can specify.
Example -
class _MenuCard extends StatelessWidget {
final String headImageAssetPath;
final IconData icon;
final Color iconBackgroundColor;
final String title;
final String subtitle;
final int heartCount;
final VoidCallback onTapCallback; //Add this custom onTap method
_MenuCard({
this.headImageAssetPath,
this.icon,
this.iconBackgroundColor,
this.title,
this.subtitle,
this.heartCount,
this.onTapCallback,
});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTapCallback,
child: new Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
child: //Rest of your code
),
);
}
}
And inside ListView you can specify your custom onTapCallback.
body: new ListView(
children: [
new _MenuCard(
headImageAssetPath: 'images/img.png',
icon: Icons.fastfood,
iconBackgroundColor: Colors.orange,
title: 'il domacca',
subtitle: "78 5TH AVENUE, NEW YORK",
heartCount: 84,
onTapCallback: () {
// Your onTap code goes here
}
),
// Rest of your code
]
)
Besides onTap, the GestureDetector widget also has a lot of other user event callbacks. You can find out more about them here.
Also, the same functionality can also be achieved with the help of the InkWell widget, you will just need to replace GestureDetector with InkWell and the rest of the code will remain same. Documentation for the widget can be found here.
Hope this helps!

Related

How do I make it so that when I click an icon it opens another page file in flutter

How do I make it so that when I click an icon it opens another page file in flutter? I have this icons which when you click them it redirects you to a url, I want to make it so when you click one specific icon instead of opening a url it opens another page file, acting like a navigator.push...
But when I add an ontap to my taskcard I get an error, I had set the pageUrl = "", but it didn't return anything so I removed the this.required pageUrl and changed to this.pageUrl and now I have this error The parameter 'pageUrl' can't have a value of 'null' because of its type, but the implicit default value is 'null', my code is like this:
import 'dart:ui';
import 'package:url_launcher/url_launcher.dart';
import '';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:schoolmanagement/nav_bar.dart';
class DinningScreen extends StatefulWidget {
const DinningScreen({super.key});
#override
State<DinningScreen> createState() => _DinningState();
}
class _DinningState extends State<DinningScreen> {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: NavBar(),
key: scaffoldKey,
appBar: AppBar(...),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffF6FECE), Color(0xffB6C0C8)],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
tileMode: TileMode.clamp),
),
//Here we set the "Manage your ... box and it's properties"
padding: const EdgeInsets.all(12.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(...),
SizedBox(
height: 20.0,
),
Text(
"Sections",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "SpaceGrotesk",
color: Colors.black),
),
//Here we set the "Shortcuts"
//If you click Teachers it will take you the page where you can see the Teachers -
//names a nd availabity alongs side the subject they teach
//If you click EduPage it takes you to edupage
//If you click Timetable it takes you to the Timetable generator
//If you click Messages it asks you to join a messenger Gc of Students of your class
Row(
children: [
Expanded(
child: TaskCard(
label: "Teachers",
pageUrl: "",
)),
Expanded(
child: TaskCard(
imageUrl: "assets/school-bag.png",
label: "EduPage",
pageUrl: "https://willowcosta.edupage.org",
)),
//This is what I want to change from going to url to another page
Expanded(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
);
},
child: TaskCard(
imageUrl: "assets/timetable.png",
pageUrl: "",
label: "Timetable",
),
)),
Expanded(
child: TaskCard(
imageUrl: "assets/message.png",
pageUrl: "https://www.messenger.com",
label: "Messages",
)),
],
),
//Here we set the tasks that we have
const SizedBox(
height: 20.0,
),
const Text(
"You have 6 tasks for this week",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "SpaceGrotesk",
color: Colors.black),
),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const SizedBox(
height: 100.0,
),
],
),
),
),
The TaskCard definition is here:
class TaskCard extends StatelessWidget {
final String? imageUrl;
final String? label;
final String pageUrl;
const TaskCard(
{Key? key, this.imageUrl, required this.label, required this.pageUrl})
: super(key: key);
//Function to launch the selected url
Future<void> goToWebPage(String urlString) async {
final Uri _url = Uri.parse(urlString);
if (!await launchUrl(_url)) {
throw 'Could not launch $_url';
}
}
#override
Widget build(BuildContext context) {
return Padding(
//Here we set the properties of our Sections (Teachers etc)
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
height: 80.0,
width: 76.1,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.grey, blurRadius: 2.0, spreadRadius: 0.5),
]),
child: IconButton(
onPressed: () async {
if(pageUrl !=""){
await goToWebPage(pageUrl);
}
},
icon: Image.asset(
imageUrl ?? "assets/teacher.png",
height: 75.0,
width: 70.0,
),
),
),
SizedBox(
height: 10.0,
),
Text(
label ?? "",
style: TextStyle(fontSize: 16.0),
)
],
),
);
}
}
The parameter 'pageUrl' can't have a value of 'null' because of its
type, but the implicit default value is 'null'.
Check whether the pageUrl is an empty String. If it is an empty String, don't call goToWebPage.
onPressed: () async {
if(pageUrl !=""){
await goToWebPage(pageUrl);
}
},

How do I make mutiple icons go to different url's

I have my app which has some icons, the problem is that I set the icons as extensions/parents of one icon, so when I set an icon to go to a url all other icons go to that url too. But that is not what I want, I want each icon to go to a separate url.
The code for the extended icons is:
`
Row(
children: [
Expanded(
child: TaskCard(
label: "Teachers",
)),
Expanded(
child: TaskCard(
imageUrl: "assets/school-bag.png",
label: "EduPage",
pageUrl: "https://willowcosta.edupage.org",
)),
`
error displayed:
and the code for the parent icon is:
SizedBox(
height: 20.0,
),
Text(
"Sections",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "SpaceGrotesk",
color: Colors.black),
),
//Here we set the "Shortcuts"
//If you click Teachers it will take you the page where you can see the Teachers -
//names a nd availabity alongs side the subject they teach
//If you click EduPage it takes you to edupage
//If you click Timetable it takes you to the Timetable generator
//If you click Messages it asks you to join a messenger Gc of Students of your class
Row(
children: [
Expanded(
child: TaskCard(
label: "Teachers",
)),
Expanded(
child: TaskCard(
imageUrl: "assets/school-bag.png",
label: "EduPage",
pageUrl: "https://willowcosta.edupage.org",
)),
Expanded(
child: TaskCard(
imageUrl: "assets/timetable.png",
label: "Timetable",
)),
Expanded(
child: TaskCard(
imageUrl: "assets/message.png",
label: "Messages",
)),
],
),
//Here we set the tasks that we have
const SizedBox(
height: 20.0,
),
const Text(
"You have 6 tasks for this week",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontFamily: "SpaceGrotesk",
color: Colors.black),
),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const TaskContainer(),
const SizedBox(
height: 100.0,
),
],
),
),
),
bottomSheet: const BottomSheetCard(),
);
}
}
//hier the first class ends
class TaskCard extends StatelessWidget {
final String? imageUrl;
final String? label;
const TaskCard({Key? key, this.imageUrl, this.label}) : super(key: key);
//Function to launch the selected url
Future<void> goToWebPage(String urlString) async {
final Uri _url = Uri.parse(urlString);
if (!await launchUrl(_url)) {
throw 'Could not launch $_url';
}
}
#override
Widget build(BuildContext context) {
return Padding(
//Here we set the properties of our Sections (Teachers etc)
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
height: 80.0,
width: 76.1,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.grey, blurRadius: 2.0, spreadRadius: 0.5),
]),
child: IconButton(
onPressed: () async {
await goToWebPage(pageUrl);
},
icon: Image.asset(
imageUrl ?? "assets/teacher.png",
height: 75.0,
width: 70.0,
),
),
),
SizedBox(
height: 10.0,
),
Text(
label ?? "",
style: TextStyle(fontSize: 16.0),
)
],
),
);
}
}
error 2 displayed:
My app looks like this:
I want each icon to take me to a different website
In your parent icon you can define new string variable in constructor and name it pageUrl like two other variable imageUrl, label, now use it lie this:
onPressed: () async {
await goToWebPage(pageUrl);
},
then pass it like this:
Expanded(
child: TaskCard(
imageUrl: "assets/school-bag.png",
label: "EduPage",
pageUrl: "https://willowcosta.edupage.org",
),
),
Full Example of TaskCard calss:
class TaskCard extends StatelessWidget {
final String imageUrl;
final String label;
final String pageUrl;//<-- add this
const TaskCard(
{Key? key,
required this.imageUrl,
required this.label,
required this.pageUrl})//<-- add this
: super(key: key);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
height: 80.0,
width: 76.1,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.0),
boxShadow: [
BoxShadow(
color: Colors.grey, blurRadius: 2.0, spreadRadius: 0.5),
]),
child: IconButton(
onPressed: () async {
await goToWebPage(pageUrl);//<-- add this
},
icon: Image.asset(
imageUrl ?? "assets/teacher.png",
height: 75.0,
width: 70.0,
),
),
),
SizedBox(
height: 10.0,
),
Text(
label ?? "",
style: TextStyle(fontSize: 16.0),
)
],
),
);
}
}

Make a list tile button turn grey when clicked

How can I make individual buttons turn grey when I click on approve?
The screenshot is below
Below is the List Tile widget code
Widget pendingList({
required String title,
required String subtitle,
required String leading,
onTap,
}) {
return Row(
children: [
Expanded(
flex: 6,
child: Card(
child: ListTile(
leading: Container(
padding: const EdgeInsets.only(left: 15.0),
alignment: Alignment.center,
height: 50,
width: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
image: DecorationImage(
image: NetworkImage(
'therul'),
fit: BoxFit.cover,
),
),
),
title: Text(
title,
style: TextStyle(
fontSize: BtnFnt2,
fontWeight: FontWeight.w600,
),
),
subtitle: Text(
subtitle,
style: TextStyle(
fontSize: littleTexts,
),
),
),
),
),
Expanded(
flex: 2,
child: Bounce(
duration: const Duration(milliseconds: 100),
onPressed: onTap,
child: Container(
padding: const EdgeInsets.all(15.0),
color: appOrange,
child: Text(
'Approve',
style: TextStyle(
color: white,
fontWeight: FontWeight.w500,
),
),
),
),
),
],
);
}
How can I make individual buttons turn grey when I click on approve?
Any idea will be appreciated. Kindly refer to the screenshot and assist if you can.
One way, is to make the card into a stateful widget, like (simplified)
class ColorCard extends StatefulWidget {
const ColorCard({
Key? key,
}) : super(key: key);
#override
State<ColorCard> createState() => _ColorCardState();
}
class _ColorCardState extends State<ColorCard> {
Color col = Colors.white;
#override
Widget build(BuildContext context) {
return Card(
color: col,
child: ListTile(
title: const Text('title'),
subtitle: const Text('subtitle'),
trailing: ElevatedButton(
onPressed: () {
setState(() => col = Colors.grey);
},
child: const Text('click'),
),
),
);
}
}
Alternatively the color could be based on a value stored in an object that extends or 'mixin'-s ChangeNotifier if you want more comprehensive integration.

Flutter: How to center text with dynamic length?

Hello I have created a custom appbar where the title of appbar will come from API which can any of the length so How can I center it.
code of custom appbar,
class CustomAppBar extends PreferredSize {
final String title;
final double height;
CustomAppBar({
#required this.title,
this.height = kToolbarHeight,
});
#override
Size get preferredSize => Size.fromHeight(height);
#override
Widget build(BuildContext context) {
final headline6 = Theme.of(context).textTheme.headline6;
return Container(
width: double.infinity,
height: 99,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
AppColors.veryDarkBlue,
AppColors.blueWhale,
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [
0.3,0.8
],
),
),
padding: EdgeInsets.only(
top: 27,
left: 19,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
InkWell(
child: Icon(
Icons.arrow_back_ios_rounded,
color: Colors.white,
size: 20.sdpHeight,
),
onTap: () => Navigator.pop(context),
),
Expanded(
child: Center(
child: Text(
title, //<--- I want to align this
style: headline6.copyWith(
color: Colors.white,
fontSize: 16,
),
),
),
),
],
)
);
}
}
how it looks,
in second screen shot it has little more gap on left then it should be so How I can fix it?
add something to take up the space from right just as your icon
children: [
InkWell(
child: Icon(
Icons.arrow_back_ios_rounded,
color: Colors.white,
size: 20.sdpHeight,
),
onTap: () => Navigator.pop(context),
),
Expanded(
child: Center(
child: Text(
title, //<--- I want to align this
style: headline6.copyWith(
color: Colors.white,
fontSize: 16,
),
),
),
),
SizedBox(width:40.0),
],

How to reduce the white space beside the drawer icon in Flutter?

In my flutter project, I have set one custom drawer.
Here's code for custom drawer-
class AppDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
double defaultScreenWidth = 400.0;
double defaultScreenHeight = 810.0;
ScreenUtil.instance = ScreenUtil(
width: defaultScreenWidth,
height: defaultScreenHeight,
allowFontScaling: true,
)..init(context);
return SizedBox(
width: MediaQuery.of(context).size.width * 0.70,
child: Drawer(
child: Container(
color: Colors.black87,
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
SizedBox(height: ScreenUtil.instance.setHeight(30),),
_createDrawerItem(
icon: Icons.keyboard_arrow_right,
text: 'English to Bangla',
onTap: () =>
Navigator.pushReplacementNamed(context, Routes.englishToBangla)),
Padding(
padding: EdgeInsets.only(left:ScreenUtil.instance.setWidth(20), right: ScreenUtil.instance.setWidth(20)),
child: Divider(
height: ScreenUtil.instance.setHeight(10),
color: Colors.grey,
),
),
],
),
),
),
);
}
Widget _createHeader() {
return DrawerHeader(
margin: EdgeInsets.zero,
padding: EdgeInsets.zero,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: AssetImage('path/to/header_background.png'))),
child: Stack(children: <Widget>[
Positioned(
bottom: 12.0,
left: 16.0,
child: Text("Flutter Step-by-Step",
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w500))),
]));
}
Widget _createDrawerItem(
{IconData icon, String text, GestureTapCallback onTap}) {
return ListTile(
title: Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10)),
child: Row(
children: <Widget>[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.teal
),
child: Icon(icon, color: Colors.white,)
),
Padding(
padding: EdgeInsets.only(left: ScreenUtil.instance.setWidth(10)),
child: Text(text, style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: ScreenUtil.instance.setSp(14) ),),
)
],
),
),
onTap: onTap,
);
}
}
Here's code for the toolBar which is shown beside the drawer icon-
class SearchAppBar extends StatefulWidget implements PreferredSizeWidget {
final PatternCallback onPatternSelected;
SearchAppBar(this.onPatternSelected, {Key key})
: preferredSize = Size.fromHeight(90),
super(key: key);
#override
final Size preferredSize; // default is 56.0
#override
_SearchAppBarState createState() => _SearchAppBarState();
}
class _SearchAppBarState extends State<SearchAppBar> {
TextEditingController _searchTextController = TextEditingController();
#override
Widget build(BuildContext context) {
double defaultScreenWidth = 400.0;
double defaultScreenHeight = 810.0;
ScreenUtil.instance = ScreenUtil(
width: defaultScreenWidth,
height: defaultScreenHeight,
allowFontScaling: true,
)..init(context);
return Container(
color: Colors.white,
child: Row(
children: <Widget>[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
),
child: Theme(
data:
Theme.of(context).copyWith(primaryColor: Color(0xFFff9900)),
child: TextFormField(
autofocus: false,
style: TextStyle(fontSize: ScreenUtil.instance.setSp(18)),
keyboardType: TextInputType.text,
controller: _searchTextController,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Search for any word you want',
hintStyle:
TextStyle(fontSize: ScreenUtil.instance.setSp(16)),
contentPadding: EdgeInsets.symmetric(
vertical: 14,
horizontal: 10),
),
onChanged: (String value) {
widget.onPatternSelected(value);
},
),
),
),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(0),
),
child: InkWell(onTap: (){
if(_searchTextController.text.isNotEmpty) {
Navigator.of(context).push(MaterialPageRoute(builder: (context)=>WordDetailScreen(_searchTextController.text.toLowerCase())));
}
},
child: Icon(Icons.search, color: Colors.blue,))),
SizedBox(width: 15)
],
),
);
}
}
And then, in the class where I want to use this drawer, I have called inside Scaffold like below-
drawer: AppDrawer()
But the problem is this causing a white space beside the drawer icon like below image-
And I am having no idea from where this extra padding or margin is happening. So, I need a solution to reduce this extra white space beside the drawer icon.
You can use Transform.translate to move the search bar to the left:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(builder: (context) {
return IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
);
}),
title: Transform.translate(
offset: Offset(-30.0, 0.0),
child: Text('this is the title') // here you can put the search bar
),
),
drawer: Drawer(
),
);
}
Just add a property called "titleSpacing" in your AppBar Tag,
Sample
appBar: AppBar(
titleSpacing: 0, //Add this line to your code
title: Text(widget.title),
leading: Icon(Icons.android),
),