GestureDetector on tap is not triggring on alll the screen - flutter

i am learning flutter and i just created an app that will update a counter variable when the user clicks on any part of the screen except the AppBar. However, the GestureDetector does not detect any clicks on the4 screen except for those on the text itself
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("i am a title"),
backgroundColor: Colors.teal,
leading: const Icon(
Icons.home,
color: Colors.white,
),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const [
Expanded(
child: Clicks(),
),
],
),
),
),
);
}
}
class Clicks extends StatefulWidget {
const Clicks({super.key});
#override
State<Clicks> createState() => _ClicksState();
}
class _ClicksState extends State<Clicks> {
int count = 0;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => setState(
() {
count++;
},
),
child: Center(
child: Text("total number of clicking on scren is $count "),
),
);
}
}

The GestureDetector will detect any gestures for it's child - in this case the Text widget.
If you want to detect everything, wrap the entrie Scaffold with a GestureDector.
In this case, you'll have to refactor your code:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Clicks();
}
}
class Clicks extends StatefulWidget {
const Clicks({super.key});
#override
State<Clicks> createState() => _ClicksState();
}
class _ClicksState extends State<Clicks> {
int count = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("i am a title"),
backgroundColor: Colors.teal,
leading: const Icon(
Icons.home,
color: Colors.white,
),
),
body: GestureDetector(
onTap: () {
setState(() {
count++;
});
},
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: Text("clicked a total of $count times"),
),
],
),
),
),
),
);
}
}

Try with below changes :
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => setState(
() {
count++;
},
),
child: Center(
child: Text("total number of clicking on scren is $count "),
),
);

Related

Unable to navigate from GetX Dialog to another screen

I have follow dialog box. When I click 'Next' I want it to navigate to GamePage() screen. But unfortunately it doesn't work.
Following is the GamePage Widget
class GamePage extends StatelessWidget {
final homeCtrl = Get.find<HomeController>();
GamePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF8fb1ca),
body: SafeArea(
child: ListView(
children: [
Padding(
padding: EdgeInsets.all(3.0.wp),
child: Row(
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(Icons.arrow_back),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 4.0.wp),
child: Column(
children: [
SizedBox(
height: 2.0.wp,
),
Center(
child: Text(
'What ${homeCtrl.currentWord.first.wordtype} is this?',
style: TextStyle(
fontSize: 18.0.sp,
color: Colors.grey[800],
),
),
),
SizedBox(height: 10.0.wp),
WordsWidget(currentWord: homeCtrl.currentWord.first),
],
),
),
],
),
),
);
}
}
Following is the Word Widget being called from GamePage Widget
class WordsWidget extends StatelessWidget {
final currentWord;
WordsWidget({Key? key, this.currentWord}) : super(key: key);
final homeCtrl = Get.find<HomeController>();
#override
Widget build(BuildContext context) {
// var currentWord = homeCtrl.nextWord();
var shuffleword = [].obs;
shuffleword.addAll(homeCtrl.shuffleWord(currentWord.word));
TextToSpeech tts = TextToSpeech();
String language = 'en-US';
tts.setLanguage(language);
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print('pressed here');
Get.defaultDialog(
title: 'Go to next page',
content: Container(
child: Column(
children: [
Text('You are about to move to another screen'),
ElevatedButton.icon(
onPressed: () {
Get.to(() => GamePage());
},
icon: Icon(
Icons.arrow_right,
),
label: Text('Go'))
],
),
));
},
child: Text('Open Dialog')),
],
);
}
}
Get.back() is working but not Get.to
Try
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return const GamePage();
},
),
);
},
child: Text("Next Word"),
)
Try this code -
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_memory/next_page.dart';
import 'package:image_picker/image_picker.dart';
void main() {
//check getMaterialApp is used
runApp(const GetMaterialApp(
title: 'Temp',
home: const MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Image Picker'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
print('pressed here');
Get.defaultDialog(
title: 'Go to next page',
content: Container(
child: Column(
children: [
Text('You are about to move to another screen'),
ElevatedButton.icon(
onPressed: () {
Get.to(() => NextPage());
},
icon: Icon(
Icons.arrow_right,
),
label: Text('Go'))
],
),
));
},
child: Text('Open Dialog')),
),
);
}
}
and next page is -
import 'package:flutter/material.dart';
class NextPage extends StatefulWidget {
const NextPage({ Key? key }) : super(key: key);
#override
State<NextPage> createState() => _NextPageState();
}
class _NextPageState extends State<NextPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Next Page'),
),
body: Container(
child: Center(
child: Text("this is next page"),
),
),
);
}
}
And yes, you need to insure that you are using 'GetMaterialApp'.
If you want to use GetX navigation system, you should wrap your application in a GetMaterialApp instead of MaterialApp.
So in your main use this:
class GetxApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetMaterialApp(
home: HomePage(),
);
}
}
Instead of this:
class NormalApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}

How do i print the value which is coming from modal bottom sheet to the main scaffold body in dart+flutter

ive created a text and icon button, onpressing that icon
modal bottom sheet gets generated, in that
and ive created a separate dart file with text field and a submit button
when giving an input on text field and after clicking on submit button the given input string will be printed below
atlast i called the function in first dart file
but i want the text to be printed on the main scaffold page.
Below is the main code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:practice1/StatefulModalbtn.dart';
void main() {
runApp(Modalbtn());
}
class Modalbtn extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Modal Bottom Test'),
),
body: Column(
children: <Widget>[Mymodal()],
),
),
);
}
}
class Mymodal extends StatelessWidget {
const Mymodal({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
'Press the icon to select the Tractor model',
style: TextStyle(fontSize: 15),
),
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: <Widget>[StatefulModalbtn()],
),
);
});
},
icon: Icon(Icons.add),
iconSize: 20,
)
],
),
);
}
}
and below code is for creating a text field and submit button
import 'package:flutter/material.dart';
class StatefulModalbtn extends StatefulWidget {
const StatefulModalbtn({Key? key}) : super(key: key);
#override
_StatefulModalbtnState createState() => _StatefulModalbtnState();
}
class _StatefulModalbtnState extends State<StatefulModalbtn> {
TextEditingController textController = TextEditingController();
String displayText = "";
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: textController,
maxLines: null,
),
ElevatedButton(
onPressed: () {
setState(() {
displayText = textController.text;
});
},
child: Text('Submit')),
Text(
displayText,
style: TextStyle(fontSize: 20),
),
],
);
}
}
and below is the output link
this is the output im achieving but i want the "Hello World" to be printed on top/main screen, right after the + add icon screen
How should i solve this ??
I just slightly edited your code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'main1.dart';
void main() {
runApp(MaterialApp(
home: Modalbtn(),
));
}
class Modalbtn extends StatefulWidget {
#override
_ModalbtnState createState() => _ModalbtnState();
}
class _ModalbtnState extends State<Modalbtn> {
String value = "0";
// Pass this method to the child page.
void _update(String newValue) {
setState(() => value = newValue);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
IconButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
child: Column(
children: [StatefulModalbtn(update: _update)],
),
);
});
},
icon: Icon(Icons.add),
iconSize: 20,
),
Text(
value,
style: TextStyle(fontSize: 40),
),
],
),
),
);
}
}
and the child class is
import 'package:flutter/material.dart';
class StatefulModalbtn extends StatelessWidget {
final ValueChanged<String> update;
StatefulModalbtn({required this.update});
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => update("100"), // Passing value to the parent widget.
child: Text('Update (in child)'),
);
}
}

Expandable button overflowing top of container

I'm trying to make an expandable button, a bit like the expandable fab, except it's not a fab as it is not floating. This is the expandable fab for perspective:
What I'm trying to achieve though is to have a self contained button that expands above it with a menu. Self contained is in bold because I'd like the widget to be used easily without having to modify the parents structure.
So if you copy paste the code below in dartpad you'll see a yellow bar at the bottom. However if you uncomment the lines which are commented, which represents the menu expanding, you'll see that the bottom bar is pushed to the top.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: [
Expanded(child: Container(color: Colors.purple)),
MyWidget(),
]
),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SizedOverflowBox(
size: Size(double.infinity, 100),
child: Stack(
children: [
Container(color: Colors.amber, height: 100),
// Transform.translate(
// offset: Offset(0, -400),
// child: Container(color: Colors.lightBlue, height: 400, width: 80),
// ),
]
)
);
}
}
So my questions are:
How do I achieve the required result where the bottom bar does not move and a menu above it (light blue container); modifying only MyWidget and not MyApp ?
Why in the current code the bar is pushed above ?
Overlay and OverlayEntry can help to achieve this:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
children: [
Expanded(child: Container(color: Colors.purple)),
MyWidget(),
]
),
),
),
);
}
}
class MyWidget extends StatelessWidget {
OverlayEntry? _overlayEntry;
_hideMenu() {
_overlayEntry?.remove();
}
_showMenu(BuildContext context) {
final overlay = Overlay.of(context);
_overlayEntry = OverlayEntry(
builder: (ctx) => Stack(
children: [
GestureDetector(
onTap: () => _hideMenu(),
child: Container(color: Colors.grey.withAlpha(100)),
),
Positioned(
bottom: 100,
left: 50,
child: Container(color: Colors.pink, height: 200, width: 50,),
),
],
)
);
overlay?.insert(_overlayEntry!);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => _showMenu(context),
child: Container(color: Colors.amber, height: 100)
);
}
}
Try this, run this code in dartpad.
It contains one parent, three child which can be called using the menu buttons,
The FloatingActionButton.extended used in this code can be replaced by any custom Widget, you can give onTap methods for clicks,
I have used simple widgets, Let me know wether you were looking for something like that, or something different.
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'I am Parent'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool showButtons = false;
var index = 0;
List<Widget> childList = [Child1(), Child2(), Child3()];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: childList[index],
),
floatingActionButton: Column(
mainAxisSize: MainAxisSize.min,
children: [
Visibility(
visible: showButtons,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FloatingActionButton.extended(
heroTag: 'btn1',
onPressed: () {
setState(() {
index = 0;
});
},
label: Text(
"Sub Btn1",
style: TextStyle(color: Colors.black),
),
elevation: 3,
backgroundColor: Colors.yellowAccent,
),
Padding(
padding: EdgeInsets.only(top: 3),
child: FloatingActionButton.extended(
heroTag: 'btn1',
onPressed: () {
setState(() {
index = 1;
});
},
label: Text(
"Sub Btn2",
style: TextStyle(color: Colors.black),
),
elevation: 3,
backgroundColor: Colors.yellowAccent,
)),
Padding(
padding: EdgeInsets.only(top: 3),
child: FloatingActionButton.extended(
heroTag: 'btn3',
onPressed: () {
setState(() {
index = 2;
});
},
label: Text(
"Sub Btn3",
style: TextStyle(color: Colors.black),
),
elevation: 3,
backgroundColor: Colors.yellowAccent,
))
],
),
),
RaisedButton(
onPressed: () {
setState(() {
showButtons = !showButtons;
});
},
child: Text("Self Contained"),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
color: Colors.yellow,
),
],
) // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class Child1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("I am Child 1"),
);
}
}
class Child2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("I am Child 2"),
);
}
}
class Child3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("I am Child 3"),
);
}
}

Alert box with multi select chip in flutter

I have a multiselect chip in my app , but when since the data in the AlertDialog depends dynamically, it will be 1 or 100, so I have added SingleChildScrollView over the alert Dialog to give scrolling if there are more entries , but when I added SingleChildScrollView my alert box goes to top of the screen like this, I want it to align in center,
If I removed the SingleChildScrollView then It will come like this which I wanted. but If there are lot of entries I cant select because It cant cover the entire data?
Is there any way where I can align it to center of screen with scroll enabled?
Thanks
showDialog(
context: context,
builder: (BuildContext context) {
return SingleChildScrollView(
child: AlertDialog(
title: Text("choose items"),
content: MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
listSelectedItem = selectedList;
});
},
),
actions: <Widget>[
FlatButton(
child: Text("CANCEL"),
onPressed: () {
setState(() {
dropdownSelected = null;
listSelectedItem.clear();
});
Navigator.of(context).pop();
}),
In AlertDialog's content use Container and constraints, and in Container's child wrap SingleChildScrollView then wrap MultiSelectChip
code snippet
return AlertDialog(
title: Text("Report Video"),
content: Container(
constraints: BoxConstraints(
maxHeight: 100.0,
),
child: SingleChildScrollView(
child: MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
selectedReportList = selectedList;
});
},
),
),
),
actions: <Widget>[
FlatButton(
child: Text("Report"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
})
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> {
List<String> reportList = [
"Not relevant",
"Illegal",
"Spam",
"Offensive",
"Uncivil",
"a123",
"b234",
"c2314",
"aaaa",
"a",
"1Not relevant",
"2Illegal",
"3Spam",
"4Offensive",
"5Uncivil",
"6a123",
"7b234",
"8c2314",
"9aaaa",
"0a",
"Not relevant",
"Illegal",
"Spam",
"Offensive",
"Uncivil",
"a123",
"b234",
"c2314",
"aaaa",
"a",
"1Not relevant",
"2Illegal",
"3Spam",
"4Offensive",
"5Uncivil",
"6a123",
"7b234",
"8c2314",
"9aaaa",
"0a",
];
List<String> selectedReportList = List();
_showReportDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
//Here we will build the content of the dialog
return AlertDialog(
title: Text("Report Video"),
content: Container(
constraints: BoxConstraints(
maxHeight: 100.0,
),
child: SingleChildScrollView(
child: MultiSelectChip(
reportList,
onSelectionChanged: (selectedList) {
setState(() {
selectedReportList = selectedList;
});
},
),
),
),
actions: <Widget>[
FlatButton(
child: Text("Report"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("Report"),
onPressed: () => _showReportDialog(),
),
Text(selectedReportList.join(" , ")),
],
),
),
);
}
}
class MultiSelectChip extends StatefulWidget {
final List<String> reportList;
final Function(List<String>) onSelectionChanged;
MultiSelectChip(this.reportList, {this.onSelectionChanged});
#override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
// String selectedChoice = "";
List<String> selectedChoices = List();
_buildChoiceList() {
List<Widget> choices = List();
widget.reportList.forEach((item) {
choices.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text(item),
selected: selectedChoices.contains(item),
onSelected: (selected) {
setState(() {
selectedChoices.contains(item)
? selectedChoices.remove(item)
: selectedChoices.add(item);
widget.onSelectionChanged(selectedChoices);
});
},
),
));
});
return choices;
}
#override
Widget build(BuildContext context) {
return Wrap(
children: _buildChoiceList(),
);
}
}

How to intercept flutter back-button when keyboard is shown

I want to intercept the back-button of the soft keyboard in flutter. So when I want to close the keyboard by pressing the back-button I want an additional function to be called.
How can I do that?
Keyboard Back button
you can use the keyboard_visibility package to achieve this.
Working Example
the following code displays a SnackBar once the keyboard is dismissed.
import 'package:flutter/material.dart';
import 'package:keyboard_visibility/keyboard_visibility.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GlobalKey<ScaffoldState> _key;
#override
void initState() {
super.initState();
_key = GlobalKey<ScaffoldState>();
KeyboardVisibilityNotification().addNewListener(
onHide: () {
_key.currentState.showSnackBar(
SnackBar(
content: Text("Keyboard closed"),
),
);
},
);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _key,
body: Center(
child: TextField(),
),
),
);
}
}
you can use the https://pub.dev/packages/flutter_keyboard_visibility package to achieve this.
import 'package:flutter/material.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_keyboard_visibility_example/keyboard_dismiss_demo.dart';
import 'package:flutter_keyboard_visibility_example/provider_demo.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
const App({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Demo(),
);
}
}
class Demo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return KeyboardDismissOnTap(
child: Scaffold(
appBar: AppBar(
title: Text('Keyboard Visibility Example'),
),
body: Center(
child: Padding(
padding: EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ProviderDemo()),
);
},
child: Text('Provider Demo'),
),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => KeyboardDismissDemo()),
);
},
child: Text('KeyboardDismiss Demo'),
),
Spacer(),
TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: 'Input box for keyboard test',
),
),
Container(height: 60.0),
KeyboardVisibilityBuilder(builder: (context, visible) {
return Text(
'The keyboard is: ${visible ? 'VISIBLE' : 'NOT VISIBLE'}',
);
}),
Spacer(),
],
),
),
),
),
);
}
}