Reputation: 175
Creating a Screen where I want to perform Flutter-FireBase Searching.But Visibility Toggle is not working as desired.
Desired Toggle Behaviour : When clicked on TextForm field , prefix icon and result card should be visible. Upon Clicking the Prefix Icon(Back Arrow) , Result List (Card) and the prefix icon itself should become invisible and TextField should unfocus .
Actual Behaviour : On clicking the prefix icon , Result set and prefix icon don't disappear , Prefix icon remains there and result set becomes invisible but occupies some space beneath the TextFormField
class AddAppointmentWidget extends StatefulWidget {
@override
_AddAppointmentWidgetState createState() => _AddAppointmentWidgetState();
}
class _AddAppointmentWidgetState extends State<AddAppointmentWidget> {
bool searchbartapped = false;
var queryResultSet = [];
var tempSearchStore = [];
// Search Function
initiateSearch(value) {
//body
}
@override
Widget build(BuildContext context) {
return ListView(
children: [
SizedBox(
height: 15,
),
Padding(
padding: const EdgeInsets.all(18.0),
child: Text('Search',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
flex: 5,
child: TextFormField(
style: TextStyle(color: Color(0xff2a2a2a), fontSize: 18),
keyboardType: TextInputType.name,
onChanged: (value) {
initiateSearch(value);
},
onTap: () {
setState(() {
searchbartapped = true;
});
},
cursorColor: Color(0xff2a2a2a),
cursorWidth: 1.5,
decoration: InputDecoration(
hintText: "Search by Name",
prefixIcon: Visibility(
visible: searchbartapped,
child: IconButton(
icon: Icon(Icons.arrow_back),
color: Colors.black54,
onPressed: () {
setState(() {
searchbartapped = !searchbartapped;
queryResultSet = [];
tempSearchStore = [];
});
FocusScope.of(context).unfocus();
}),
),
)),
),
],
),
),
Visibility(
visible: searchbartapped,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
padding: EdgeInsets.all(5.0),
primary: false,
shrinkWrap: true,
children: tempSearchStore.map((element) {
print(element['name']);
return buildResult(context, element);
}).toList()),
),
),
],
);
}
}
Note The buildResult widget is working perfectly fine. Problem is only with the visibilty toggle
Upvotes: 0
Views: 1191
Reputation: 3584
The issue: When you tap the prefixIcon
:
onPressed
is called, setting searchbartapped
to false
which is what you want.onTap
method of your TextFormField
is also called (since prefixIcon
is inside it), setting searchbartapped
to true
.So what you want is to prevent the second event from happening. I tried to prevent the notification from bubbling up the tree but I couldn't. So what I ended up doing is a bit more manual but works just as well.
Solution: Add a variable (for example hideSearchTapped
) which is set to true when the prefixIcon
is called. Then when the onTap
method of your TextFormField
is called, check this variable:
hideSearchTapped
is true, set it to falsesearchbartapped
as you didHere is a working example:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() async {
runApp(
MaterialApp(
home: Scaffold(
body: new AddAppointmentWidget(),
),
),
);
}
class AddAppointmentWidget extends StatefulWidget {
@override
_AddAppointmentWidgetState createState() => _AddAppointmentWidgetState();
}
class _AddAppointmentWidgetState extends State<AddAppointmentWidget> {
bool searchbartapped = false;
bool hideSearchTapped = false;
var queryResultSet = [];
var tempSearchStore = [];
// Search Function
initiateSearch(value) {
//body
}
@override
Widget build(BuildContext context) {
return ListView(
children: [
SizedBox(
height: 15,
),
Padding(
padding: const EdgeInsets.all(18.0),
child: Text('Search', style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
flex: 5,
child: TextFormField(
style: TextStyle(color: Color(0xff2a2a2a), fontSize: 18),
keyboardType: TextInputType.name,
onChanged: (value) {
initiateSearch(value);
},
onTap: () {
setState(() {
if (hideSearchTapped) {
hideSearchTapped = false;
} else {
searchbartapped = true;
}
});
},
cursorColor: Color(0xff2a2a2a),
cursorWidth: 1.5,
decoration: InputDecoration(
hintText: "Search by Name",
prefixIcon: Visibility(
visible: searchbartapped,
child: IconButton(
icon: Icon(Icons.arrow_back),
color: Colors.black54,
onPressed: () {
hideSearchTapped = true;
searchbartapped = !searchbartapped;
queryResultSet = [];
tempSearchStore = [];
setState(() {
});
FocusScope.of(context).unfocus();
return true;
}),
),
)),
),
],
),
),
Visibility(
visible: searchbartapped,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
padding: EdgeInsets.all(5.0),
primary: false,
shrinkWrap: true,
children: tempSearchStore.map((element) {
print(element['name']);
}).toList()),
),
),
],
);
}
}
Note: you should use lowerCamelCase to name your variable. So searchbartapped
would become searchBarTapped
.
Upvotes: 1