Flutter : how to make an entire row clickable - flutter

How do I make the entire row clickable in flutter?. I have the following code wrap in a "GestureDetector". The individual items in the row are clickable but white space around the widget are not.
if ((auth.isLoggedIn)) ...[
GestureDetector(
onTap: () {
auth.signOut();
},
child: buildItem(
Image.asset("assets/images/logoff.png",),
"logout"
),
),
],
This is the "buildItem" method
Widget buildItem(Widget icon, String title) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 15),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
child: Row(
children: <Widget>[
icon,
SizedBox(width: 20.0),
Text(
title,
style: TextStyle(
fontSize: 16.0,
),
),
],
)),
Icon(
Icons.arrow_forward_ios,
size: 20.0,
),
],
),
);
}
This is the output. Each item in the row (icon, text and the >) respond to the tap gesture. However, the white space(e.g between the text and the ">") does not respond to tap
How can I make entire row respond to the tap.

child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
///
},

replace GestureDetector with InkWell works great
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: () {
print("click");
},
child: buildItem(
Image.network("https://picsum.photos/250?image=9",),
"logout"
),
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Widget buildItem(Widget icon, String title) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 15),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
child: Row(
children: <Widget>[
icon,
SizedBox(width: 20.0),
Text(
title,
style: TextStyle(
fontSize: 16.0,
),
),
],
)),
Icon(
Icons.arrow_forward_ios,
size: 20.0,
),
],
),
);
}

row: mainAxisAlignment: MainAxisAlignment.spaceBetween
For space between, the first and the last object will stick to the edge of the container, while leaving the empty unused space in between (if there is other objects, it will distributed it evenly), like shown in the screenshot below:
Hence to solve this, you just have to make sure that there is no empty space between.
One way is to use mainAxisSize: MainAxisSize.max and MainAxisAlignment.start in the Row where you put your icon and text.

Related

Flutter Elevated Button Hover Color

When I use the elevated button class inside the home page, its background color changes when hovering over it (because I am using 'MaterialStateProperty'):
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[50],
body: Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
ElevatedButton( // <----
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.black),
backgroundColor: MaterialStateProperty.all(Colors.blue[200]),
),
onPressed: myFunction,
child: Text("Click Me", style: TextStyle(fontSize: 20)),
),
],
),
),
),
);
}
But when I use my own class that return an elevated button, its background Color doesn't change when hovering over it:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[50],
body: Center(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.center
children: [
ButtonWidget("Click Me", myFunction, fontSize: 20) // <---- My own Class
),
],
),
),
),
);
}
My ButtonWidget Class:
class ButtonWidget extends StatefulWidget {
const ButtonWidget(
this.text,
this.command, {
this.padding = const EdgeInsets.all(10.0),
this.fontSize = 14.0,
Key? key,
}) : super(key: key);
final String text;
final Function command;
final EdgeInsets padding;
final double fontSize;
#override
State<ButtonWidget> createState() => _ButtonWidgetState();
}
class _ButtonWidgetState extends State<Button> {
#override
Widget build(BuildContext context) {
return Padding(
padding: widget.padding,
child: ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.black),
backgroundColor: MaterialStateProperty.all(Colors.blue[200]),
),
onPressed: widget.command(),
child: Text(widget.text, style: TextStyle(fontSize: widget.fontSize)),
),
);
}
}
Why is this hapenning?
For using onHover you need to call it, but in your custom ButtonWidget you use wrong action, change :
onPressed: widget.command(),
to:
onHover: (value) { },
onPressed: widget.command(),
Note: for making onHover work, you should call empty onPressed too.

Evade flutter overflow when using row

[this is on desktop,not web or android]
I have following code, which creates a split screen (one side of screen has shortcuts to content and other side shows that content) it also acts somewhat as drawer since it can be closed or opened.
the left pane i reduce in one of two cases, when user clicks arrow button, or when the window side is less then 700. but if i try to take right edge of the screen and move very fast to reduce the size of whole window, the row will overflow and i will get an error.
So far i tryed using several things to achive this layout :
Using Flexible and setting fit and flex properties, (same issue as now since parent of them was again a row)
way that i am showing you now.
Also i could try to limit the size of screen lets say min value is 640 x 480 and that would also somewhat prevent error from happening.
I am just wondering is there another way to achieve this layout .
I also tryed several packages from pub.dev and ALL of them have same overflow error in their implementation .(easy_sidemenu,side_menu_navigation, etc)
my code
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: MyHomePage(
title: "My home",
),
);
}
}
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
ConsumerState<MyHomePage> createState() => _MyHomePageState();
}
final List<bool> isSelected = [false, false, false];
class _MyHomePageState extends ConsumerState<MyHomePage> {
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(
elevation: 0,
toolbarHeight: 35,
centerTitle: true,
title: Text(widget.title),
),
body: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 500),
width: width > 700 ? 250 : 50,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.symmetric(vertical: 5),
children: [
TextButton(
onPressed: () {},
child: Row(
children: [
Icon(
Icons.home,
color: Theme.of(context).colorScheme.secondary,
size: 30,
),
const Flexible(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text(
"Home",
maxLines: 1,
style:
TextStyle(overflow: TextOverflow.clip),
),
),
),
],
),
),
]),
),
const SizedBox(
height: 5,
),
TextButton(
onPressed: () {},
child: Row(
children: const [
Icon(
Icons.settings,
size: 30,
),
Flexible(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text(
"Settings",
maxLines: 1,
style: TextStyle(overflow: TextOverflow.clip),
),
),
),
],
),
),
],
),
),
IconButton(onPressed: () {}, icon: const Icon(Icons.arrow_back)),
Expanded(
child: Container(
color: Colors.red,
)),
],
),
);
}
}

How to remove the space under the elevated button at the bottom of the screen?

import 'package:flutter/material.dart';
class AddPlaceScreen extends StatefulWidget {
static const routeName = '/add-place';
#override
_AddPlaceScreenState createState() => _AddPlaceScreenState();
}
class _AddPlaceScreenState extends State<AddPlaceScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add new Place data'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('User Inputs'),
ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.add),
label: Text('Add Place'),
),
],
),
);
}
}
Here I am getting a space under the elevated button located at the bottom of the page please provide any solution to remove it.
Please refer below code
Add this piece of code inside ElevatedButton.icon Widget
style: ButtonStyle(
tapTargetSize: MaterialTapTargetSize
.shrinkWrap, /* Please add this to avoid padding */
),
class AddPlaceScreen extends StatefulWidget {
static const routeName = '/add-place';
#override
_AddPlaceScreenState createState() => _AddPlaceScreenState();
}
class _AddPlaceScreenState extends State<AddPlaceScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add new Place data'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('User Inputs'),
ElevatedButton.icon(
style: ButtonStyle(
tapTargetSize: MaterialTapTargetSize
.shrinkWrap, /* Please add this to avoid padding */
),
onPressed: () {},
icon: Icon(Icons.add),
label: Text('Add Place'),
),
],
),
);
}
}
Try below code hope its help to you. you can used BottomSheet also here
Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('User Inputs'),
],
),
),
bottomSheet: Container(
width: double.infinity,
child: ElevatedButton.icon(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
),
),
onPressed: () {
// Add your button press function here
print('Button Pressed');
},
icon: Icon(
Icons.add,
),
label: Text(
'Add Place',
),
),
),
);
Your result screen->
To achieve this, remove the drop shadow and extra margin around the ElevatedButton.
For this set the elevation to 0, which removes the drop shadow.
To get rid of that extra margin around the button, use the material tab target size and set it to MaterialTapTargetSize.shrinkWrap. The MaterialTapTargetSize basically ensures that you have a bigger space you can hit with your finger and if we shrink that by setting it to .shrinkWrap, you get rid of the extra margin.
Add this code inside the ElevatedButton:
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
elevation: 0,
So by setting this here, the button now really sits on the end of the screen.

Building a UI interface for my flutter project with List view

I am trying to code the UI for a flutter interface and it was going all well until I added the "ListView" widget. I tried to compile the code and it said that build completed successfully. But when I ran it, the Virtual Android screen loaded a bit, then it turned pitch black. I tried several times but to no avail. Pls can anyone help me with this code:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(
Icons.play_arrow,
size: 50.0,
), //Icon
), //Floatingactionbutton
), //Padding
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(
Icons.pause,
size: 50.0,
), //Icon
), //Floatingactionbutton
), //Padding
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(
Icons.mic,
size: 50.0,
), //Icon
), //FloatingactionButton
), //Padding
ListView(
padding: const EdgeInsets.all(5.0),
children: <Widget>[
Container(
height: 30.0,
color: Colors.amber[600],
child: const Center(
child: Text(
'Entry A',
), //Text
), //Center
), //Container
Container(
height: 30.0,
color: Colors.amber[500],
child: const Center(
child: Text(
'Entry B',
), //Text
), //Center
), //Container
Container(
height: 30.0,
color: Colors.amber[100],
child: const Center(
child: Text(
'Entry C',
), //Text
), //Center
), //Container
], //End of Widget tree
), //ListView
], //End of submain Widget Tree
), //Row
], //End of Main Widget Tree
), //Column
), //Main Center
); //Scaffold
}
}
P.S: I just started Flutter, so some things might seem unecessary
Based in this post
Try adding the ListView inside a Container
Updated:
Now this code should work. The problem is, you added ListView inside the Row not in Column
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key,this.title}) : super(key: key);
final String? title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(
Icons.play_arrow,
size: 50.0,
), //Icon
), //Floatingactionbutton
), //Padding
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(
Icons.pause,
size: 50.0,
), //Icon
), //Floatingactionbutton
), //Padding
Padding(
padding: const EdgeInsets.only(top: 50.0),
child: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(
Icons.mic,
size: 50.0,
), //Icon
), //FloatingactionButton
), //Padding
], //End of submain Widget Tree
), //Row
Expanded(
child: ListView(
children: <Widget>[
Container(
height: 10.0,
color: Colors.amber[600],
child: const Center(
child: Text(
'Entry A',
), //Text
), //Center
), //Container
Container(
height: 10.0,
color: Colors.amber[500],
child: const Center(
child: Text(
'Entry B',
), //Text
), //Center
), //Container
Container(
height: 10.0,
color: Colors.amber[100],
child: const Center(
child: Text(
'Entry C',
), //Text
), //Center
), //Container
], //End of Widget tree
), //ListView,
)
], //End of Main Widget Tree
),
); //Scaffold
}
}

Create a new card when FAB is clicked

I need create a card, when the FAB is clicked, like a list or just create a card into Column, like this image:
enter image description here
Here's one way:
import 'package:flutter/material.dart';
void main() async {
runApp(MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()));
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Widget> cardWidget = [];
buildCard() {
setState(() {
cardWidget.add(
Card(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(),
),
Padding(
padding: EdgeInsets.all(20.0),
child: TextFormField(),
),
RaisedButton(
onPressed: () {},
padding: EdgeInsets.only(left: 20.0, right: 20.0, top: 10.0, bottom: 10.0),
color: Colors.green,
child: Text(
'Criar',
style: TextStyle(
color: Colors.white
),
),
)
],
),
)
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[900],
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.blue[900]
),
floatingActionButton: FloatingActionButton(
onPressed: buildCard,
backgroundColor: Colors.green,
child: Icon(
Icons.add,
color: Colors.white,
),
),
body: Column(
children: cardWidget.map((data) {
return data;
}).toList()
),
);
}
}
This method may not be the best way for you so I encourage you to try something new on your own!