Related
I am listing records from Firebase Firestore with ListView.builder. I convert the incoming records to Model and list them.
I made a search option and I'm trying to make a filtering system for it. I want to filter by nameSurname search, city and district value.
I wrote a code like this:
StreamBuilder(
stream: db
.collection("NeedClothesPeople")
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
final searchText = searchController.text.trim().toLowerCase();
final List<NeedClothesPeopleModel> data = snapshot.data!.docs
.map((e) => NeedClothesPeopleModel.fromDocument(e))
.where((e) =>
searchText.isEmpty ||
e.nameSurname!.toLowerCase().contains(searchText) &&
selectedCity.isEmpty ||
e.city == selectedCity && selectedDistrict.isEmpty ||
e.district == selectedDistrict) // filter
.toList();
return Column(
children: [
const SizedBox(height: 10),
SizedBox(
width: MediaQuery.of(context).size.width * 0.95,
child: TextFormField(
controller: searchController,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
filterModalBottomSheet(context);
},
),
contentPadding: const EdgeInsets.only(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
),
onChanged: (value) {
setState(() {});
},
),
),
SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.8,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: data.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(Icons.person),
title: Text(data[index].nameSurname.toString()),
subtitle: Text(
"${data[index].city} / ${data[index].district}",
),
trailing: IconButton(
icon: const Icon(Icons.info),
onPressed: () {
Get.to(const NeedClothesPeopleDetailPage(),
arguments: data[index]);
print(data[index].nameSurname);
},
),
),
);
},
),
),
],
);
}
},
),
void filterModalBottomSheet(BuildContext context) {
showModalBottomSheet(
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50),
),
),
context: context,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return SizedBox(
height: MediaQuery.of(context).size.height * 0.5,
child: Padding(
padding: const EdgeInsets.only(left: 8, right: 8),
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.04,
),
Row(
children: [
const Expanded(
flex: 1,
child: Text(
"İl:",
style: TextStyle(fontSize: 19),
),
),
Expanded(
flex: 9,
child: DropdownButtonFormField(
hint: const Text("İl seçiniz"),
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.location_city,
color: Color(0xFFCB3126),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: const BorderSide(
color: Color(0xFFCB3126),
),
),
),
items: citys
.map(
(e) => DropdownMenuItem<String>(
value: e.value,
child: e.child,
),
)
.toList(),
onChanged: (value) {
setState(() {
selectedCity = value.toString();
});
},
),
),
],
),
const SizedBox(height: 20),
Row(
children: [
const Expanded(
flex: 1,
child: Text(
"İlçe:",
style: TextStyle(fontSize: 19),
),
),
Expanded(
flex: 9,
child: DropdownButtonFormField(
key: getCityKey(),
hint: selectedCity == ""
? const Text("Önce il seçiniz")
: const Text("İlçe seçiniz"),
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.location_city,
color: Color(0xFFCB3126),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: const BorderSide(
color: Color(0xFFCB3126),
),
),
),
items: districtsItem(),
onChanged: (value) {
setState(() {
selectedDistrict = value.toString();
});
},
),
),
],
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFCB3126),
),
child: const Text(
"Filtrele",
style: TextStyle(fontSize: 20),
),
onPressed: () {
setState(() {
filterActive = true;
Navigator.pop(context);
print(filterActive);
});
},
),
),
),
const SizedBox(height: 10),
],
),
),
);
},
);
},
);
}
The problem is this: When I call it by typing in TextFormField, the records in ListView.builder are changing. However, when filtering is done, the records do not change on the screen.
Why could this be? How can I solve the problem? Thanks.
im so confuse why my sliverappbar doesnt collapse when i'm scrolling listviewbuilder
so what i want is Appbar will colapse but the bottom is pinned, also when im scrolling to up the appbar will show'n
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
pinned: true,
snap: true,
floating: true,
expandedHeight: 150,
centerTitle: true,
title: Text('mama'),
bottom: AppBar(
title: Container(
height: 45,
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter a search term'),
),
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
height: MediaQuery.of(context).size.height,
child: StreamBuilder<ListsetorModel>(
stream: con.resListsetor.stream,
builder: (_, snapshot) {
if (snapshot.hasData) {
if (snapshot.data!.result == null) {
return Center(
child: Text('Data kosong '),
);
} else {
return Scrollbar(
thickness: 5,
child: ListView.builder(
itemCount: snapshot.data!.result!.length,
itemBuilder: (context, index) {
var formatDate = DateFormat('yyyy-MM-dd ')
.format(snapshot
.data!.result![index].createdAt!
.toLocal());
Result list =
snapshot.data!.result![index];
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DetailTransaksi(
kode: list.kode)));
},
child: Container(
child: Card(
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(9.0),
),
child: Container(
child: Padding(
padding:
const EdgeInsets.all(20.0),
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
"Order ${list.kode}",
style: TextStyle(
fontWeight:
FontWeight
.bold),
),
Text(formatDate),
],
),
),
Divider(),
Text(
"Please help us to confirm \nto get 10% discount code for next order."),
SizedBox(
height: 10,
),
Container(
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Container(
width: 96,
height: 36,
color: Color(
0xff85d057),
child: TextButton(
child: Row(
children: [
SizedBox(
width: 5,
),
Text(
"Qr Code",
style: TextStyle(
color: Colors
.white),
),
SizedBox(
height: 20,
width: 20,
child: Image
.asset(
'assets/images/qrscan.png'),
)
],
),
onPressed: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Qrcode(
data: list.kode!,
)));
},
),
),
)
],
),
),
],
),
),
),
),
),
);
}),
);
}
}
return Center(child: CircularProgressIndicator());
}),
);
},
),
),
],
),
),
);
}
so i want the sliverappbar collapse when im scroll thi listview, i tried adding physics neverscrollable on listview builder it doesn't work properly
so the answer is by adding in NestedScrollview
floatHeaderSlivers: true,
and remove snap: true inside sliverappbar
Please refer to below code
class AnimatedAppBar extends StatefulWidget {
const AnimatedAppBar({Key key}) : super(key: key);
#override
_AnimatedAppBarState createState() => _AnimatedAppBarState();
}
class _AnimatedAppBarState extends State<AnimatedAppBar>
with TickerProviderStateMixin {
final TextEditingController stateController = TextEditingController();
final FocusNode stateFocus = FocusNode();
var animation;
var controller;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innnerBoxIsScrolled) {
if (innnerBoxIsScrolled) {
/* Animation */
controller = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
animation = Tween(
begin: 0.0,
end: 1.0,
).animate(controller);
/* Animation */
controller.forward();
}
return <Widget>[
SliverAppBar(
expandedHeight: 120.0,
floating: false,
pinned: true,
backgroundColor: Colors.grey,
automaticallyImplyLeading: false,
titleSpacing: 0.0,
toolbarHeight: 90.0,
centerTitle: false,
elevation: 0.0,
leadingWidth: 0.0,
title: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (innnerBoxIsScrolled != null &&
innnerBoxIsScrolled == true)
FadeTransition(
opacity: animation,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 10.0,
),
Text(
"Search",
style: TextStyle(
color: Colors.black,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
autovalidateMode:
AutovalidateMode.onUserInteraction,
/* autovalidate is disabled */
controller: stateController,
inputFormatters: [
FilteringTextInputFormatter.deny(
RegExp(r"\s\s")),
FilteringTextInputFormatter.deny(RegExp(
r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])')),
],
keyboardType: TextInputType.text,
maxLength: 160,
onChanged: (val) {},
maxLines: 1,
validator: (value) {},
focusNode: stateFocus,
autofocus: false,
decoration: InputDecoration(
errorMaxLines: 3,
counterText: "",
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
disabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
),
),
errorBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
)),
focusedErrorBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
),
),
hintText: "Search" ?? "",
),
),
),
SizedBox(
height: 6.0,
)
],
),
),
],
),
// bottom: PreferredSize(
// preferredSize: Size.fromHeight(5.0),
// child: Text(''),
// ),
flexibleSpace: FlexibleSpaceBar(
background: Container(
width: MediaQuery.of(context).size.width,
child: Stack(
alignment: Alignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 10.0,
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: 8.0,
),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
"Search",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24.0,
),
),
CircleAvatar(
backgroundImage: NetworkImage(
"https://images.ctfassets.net/hrltx12pl8hq/2TRIFRwcjrTuNprkTQHVxs/088159eb8e811aaac789c24701d7fdb1/LP_image.jpg?fit=fill&w=632&h=354&fm=webp"), //NetworkImage
radius: 16.0,
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
autovalidateMode:
AutovalidateMode.onUserInteraction,
/* autovalidate is disabled */
controller: stateController,
inputFormatters: [
FilteringTextInputFormatter.deny(
RegExp(r"\s\s")),
FilteringTextInputFormatter.deny(RegExp(
r'(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])')),
],
keyboardType: TextInputType.text,
maxLength: 160,
onChanged: (val) {},
maxLines: 1,
validator: (value) {},
focusNode: stateFocus,
autofocus: false,
decoration: InputDecoration(
errorMaxLines: 3,
counterText: "",
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
disabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Color(0xffE5E5E5),
),
),
border: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
),
),
errorBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
)),
focusedErrorBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(4)),
borderSide: BorderSide(
width: 1,
color: Colors.red,
),
),
hintText: "Search" ?? "",
),
),
),
],
),
],
),
),
),
),
];
},
body: Builder(
builder: (BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemCount: 100,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value: $index"),
);
},
)
],
),
);
},
),
),
),
);
}
}
Nested Scroll with Tab Bar
class NestedScrollWithTabs extends StatefulWidget {
const NestedScrollWithTabs({Key key}) : super(key: key);
#override
_NestedScrollWithTabsState createState() => _NestedScrollWithTabsState();
}
class _NestedScrollWithTabsState extends State<NestedScrollWithTabs>
with TickerProviderStateMixin {
var animation;
var controller;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: DefaultTabController(
length: 2,
child: NestedScrollView(
physics: NeverScrollableScrollPhysics(),
headerSliverBuilder: (headerCtx, innnerBoxIsScrolled) {
if (innnerBoxIsScrolled) {
/* Animation */
controller = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
animation = Tween(
begin: 0.0,
end: 1.0,
).animate(controller);
/* Animation */
controller.forward();
}
return <Widget>[
SliverAppBar(
expandedHeight: ScreenUtil().setHeight(185.0),
floating: false,
pinned: true,
backgroundColor: Colors.white,
automaticallyImplyLeading: false,
titleSpacing: 0.0,
centerTitle: true,
elevation: 0.0,
leadingWidth: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (innnerBoxIsScrolled != null &&
innnerBoxIsScrolled == true)
FadeTransition(
opacity: animation,
child: Text(
"Title",
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
),
],
),
flexibleSpace: FlexibleSpaceBar(
background: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Image.network(
"https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
"",
fit: BoxFit.fitWidth,
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
filterQuality: FilterQuality.low,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null) return child;
return Container(
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
color: Colors.grey,
);
},
errorBuilder: (context, error, stackTrace) {
return SizedBox(
height: ScreenUtil().setHeight(126.0),
width: ScreenUtil().screenWidth,
child: Container(
width: ScreenUtil().screenWidth,
),
);
},
),
Positioned(
top: ScreenUtil().setHeight(92.0),
// left: ScreenUtil().setWidth(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CircleAvatar(
backgroundColor: Colors.transparent,
radius: 30.0,
child: ClipRRect(
borderRadius: BorderRadius.circular(
45.0,
),
child: Image.network(
"https://images.pexels.com/photos/10181294/pexels-photo-10181294.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" ??
"",
fit: BoxFit.fill,
height: ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
filterQuality: FilterQuality.low,
loadingBuilder: (BuildContext context,
Widget child,
ImageChunkEvent loadingProgress) {
if (loadingProgress == null)
return child;
return Container(
height:
ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
color: Colors.grey,
);
},
errorBuilder:
(context, error, stackTrace) {
return SizedBox(
height:
ScreenUtil().setHeight(72.0),
width: ScreenUtil().screenWidth,
child: Container(
width: ScreenUtil().screenWidth,
),
);
},
),
),
),
Text("Name"),
Text("Place"),
],
),
),
],
),
],
),
),
),
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
headerCtx),
sliver: SliverPersistentHeader(
delegate: SliverAppBarDelegate(TabBar(
labelColor: Colors.blue,
unselectedLabelColor: Colors.black,
labelStyle: TextStyle(
fontSize: 15.0,
),
unselectedLabelStyle: TextStyle(
fontSize: 15.0,
),
labelPadding: EdgeInsets.zero,
indicatorColor: Colors.blue,
indicatorPadding: EdgeInsets.zero,
physics: NeverScrollableScrollPhysics(),
tabs: [
Tab(
text: "Tab 1",
),
Tab(
text: "Tab 2",
),
],
)),
pinned: false,
),
),
];
},
body: TabBarView(
children: [
/* Tab 1 */
Container(
color: Colors.white,
child: ListView.builder(
itemCount: 100,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value: $index"),
);
},
),
),
/* Tab 2 */
Container(
color: Colors.white,
child: ListView.builder(
itemCount: 10,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Text("Index value of Tab 2: $index"),
);
},
),
),
],
),
),
),
),
);
}
}
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
SliverAppBarDelegate(this.tabBars);
final TabBar tabBars;
#override
double get minExtent => 60.0;
#override
double get maxExtent => 60.0;
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
// shinkOffsetPerValue.value = shrinkOffset;
return new Container(
color: Colors.white,
child: Column(
children: [
tabBars,
],
),
);
}
#override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return false;
}
}
I have a form builder application, I have stateless widgets which get added to list view, each widget has a delete icon, I want to delete the widget and update the list view.
one of the code widget code is this
class HeaderTextWidget extends StatelessWidget {
final VoidCallback onDelete;
HeaderTextWidget({Key key, this.onDelete}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 12.0),
decoration: BoxDecoration(
color: Colors.blueGrey,
borderRadius: BorderRadius.only(
topRight: Radius.circular(15.0),
topLeft: Radius.circular(15.0),
),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(6.0),
child: Text(
'Header',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
),
Card(
elevation: 5.0,
color: Colors.blueGrey.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(15.0),
topRight: Radius.circular(15.0),
),
),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 10.0, 8.0, 10.0),
child: TextField(
textCapitalization: TextCapitalization.words,
keyboardType: TextInputType.text,
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
decoration: InputDecoration(
hintText: 'untitled header',
hintStyle: TextStyle(
color: Colors.grey,
fontStyle: FontStyle.italic,
fontSize: 14.0,
),
),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(8.0, 4.0, 8.0, 20.0),
child: TextField(
textCapitalization: TextCapitalization.words,
keyboardType: TextInputType.text,
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.normal,
),
decoration: InputDecoration(
hintText: 'Description (optional)',
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 14.0,
),
),
),
),
Divider(
indent: 4.0,
endIndent: 4.0,
thickness: 2.0,
),
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(
icon: Icon(Icons.content_copy),
iconSize: 24.0,
color: Colors.blue,
onPressed: () {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('COpy'),
),
);
},
),
IconButton(
icon: Icon(Icons.delete),
iconSize: 24.0,
color: Colors.red,
onPressed: this.onDelete,
),
VerticalDivider(
thickness: 2.0,
endIndent: 6.0,
indent: 4.0,
),
Padding(
padding: const EdgeInsets.only(right: 12.0),
child: SwitchWidget(),
),
],
),
),
],
),
),
],
),
);
}
}
This is my Listview builder
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
FormBuilder(
key: widget.fbKey,
autovalidate: true,
child: Expanded(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
itemCount: widget.data.widgets.length,
controller: _scrollController,
itemBuilder: (context, index) {
return widget.data.widgets[index];
},
),
),
)),
],
),
);
This is how the widget is being added the view is getting changed from selected the widget to List view builder page, when clicked on that particular icon. Where should be the delete function be added, in the List view or in the widget itself ?
Scaffold(
appBar: AppBar(
title: Text('Form Widgets'),
),
body: LayoutBuilder(
builder:
(BuildContext context, BoxConstraints viewPointConstrainsts) {
return SingleChildScrollView(
padding: EdgeInsets.all(12.0),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewPointConstrainsts.maxHeight,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FormWidget(
key: UniqueKey(),
iconData: Icons.title,
widgetTxT: 'Header',
onTap: () {
setState(() {
widget.data.widgets.add(HeaderTextWidget());
widget.pickWidgetsView = false;
});
},
),
Try the following approach:
Store only the data, not the Widget itself in the list
List<DataModel> data = []
Create list view item using createListViewItem() which should return widget as the following
ListView.builder(
itemCount: widget.dataList.length,
controller: _scrollController,
itemBuilder: (context, index) {
return createListViewItem(index);
},
),
Now inside createListViewItem(index) you can create data as per widget.dataList[index] and delete the list item on click of delete icon
setState(){
widget.dataList.deleteAt(index);
}
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DropdownButton(
items: _Mothe.map(
(String dropdownMenuItem) {
return DropdownMenuItem<String>(
value: dropdownMenuItem,
child: Text(dropdownMenuItem),
);
},
).toList(),
onChanged: (String? value) {
setState(
() {
name == value!;
},
);
},
value: name,
isExpanded: true,
icon: SizedBox(),
),
],
),
);
}
I'm having trouble placing my search bar in the AppBar,
right now my searchBar is below my AppBar, I tried use another Container into my AppBar but without success.
My code:
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home:Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100.0),
child: AppBar(
iconTheme: IconThemeData(color: Color.fromRGBO(9, 133, 46, 100)),
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.shopping_cart,
color: Color.fromRGBO(9, 133, 46, 100),
),
onPressed: (){
print('klikniete');
},
),
],
),
),
body: Builder(
builder: (context) => Container(
child: FutureBuilder(
future: fetchOrders(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (_ordersForDisplay.length == null) {
return Container(
child: Center(child: Text("Ładowanie...")),
);
} else {
return ListView.builder(
itemCount: _ordersForDisplay.length + 1,
itemBuilder: (BuildContext context, int index) {
return index == 0 ? _searchBar() : _listItem(index - 1);
},
);
}
},
),
),
),
)
);
}
_searchBar() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
decoration: InputDecoration(
hintText: 'Wyszukaj po mieście...'
),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_ordersForDisplay = _orders.where((note) {
var noteTitle = note.city.toLowerCase();
return noteTitle.contains(text);
}).toList();
});
},
),
);
}
_listItem(index) {
return GestureDetector(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (context) => DetailPage(item: _ordersForDisplay[index])),
),
child: Card(
child: Padding(
padding: const EdgeInsets.only(
top: 32.0, bottom: 32.0, left: 16.0, right: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
_ordersForDisplay[index].firstName,
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
Text(
_ordersForDisplay[index].lastName,
style: TextStyle(
color: Colors.grey.shade600
),
),
],
),
),
),
);
}
}
i'm put searchBar into my appBar by use title: _searchBar, next I remove
return index == 0 ? _searchBar() : _listItem(index - 1); and paste only return _listItem(index, context), but right now i have error: RangeError (index): Invalid value: Only valid value is 0: 1
Are you expecting to this
OR this?
Code:
class CustomSearchBarDemo extends StatefulWidget {
#override
_CustomSearchBarDemoState createState() => _CustomSearchBarDemoState();
}
class _CustomSearchBarDemoState extends State<CustomSearchBarDemo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.white,
title: Text("Search",style: TextStyle(color: Colors.black),),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
// padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey[300],
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Material(
color: Colors.grey[300],
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.search,color: Colors.grey),
Expanded(
child: TextField(
// textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(
hintText: ' Search by name or address',
),
onChanged: (value) {
},
),
),
InkWell(
child: Icon(Icons.mic,color: Colors.grey,),
onTap: () {
},
)
],
),
),
)
) ,
),
),
);
}
}
OR
class CustomSearchBarDemo extends StatefulWidget {
#override
_CustomSearchBarDemoState createState() => _CustomSearchBarDemoState();
}
class _CustomSearchBarDemoState extends State<CustomSearchBarDemo> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:
PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
padding: const EdgeInsets.only(top:20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey[300],
),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Material(
color: Colors.grey[300],
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.search,color: Colors.grey),
Expanded(
child: TextField(
// textAlign: TextAlign.center,
decoration: InputDecoration.collapsed(
hintText: ' Search by name or address',
),
onChanged: (value) {
},
),
),
InkWell(
child: Icon(Icons.mic,color: Colors.grey,),
onTap: () {
},
)
],
),
),
)
) ,
),
);
}
}
You can basically add any widget in the title property of appbar.
AppBar(
title: TextField(
autofocus: true,
decoration: InputDecoration(
hintText: " Search...",
border: InputBorder.none,
suffixIcon: IconButton(icon:Icon(Icons.search), onPressed: () {
},)
),
style: TextStyle(color: Colors.white, fontSize: 14.0),
),
iconTheme: IconThemeData(color: Color.fromRGBO(9, 133, 46, 100)),
backgroundColor: Colors.white,
actions: <Widget>[
IconButton(
icon: Icon(
Icons.shopping_cart,
color: Color.fromRGBO(9, 133, 46, 100),
),
onPressed: (){
print('klikniete');
},
),
],
),
I've tried to create form to input something from textfield to database using rest service, it worked just fine from the first try, but it got error the next time I tried, the error said there was something wrong with the GlobalkKey, so it's maybe around here.
class _DeliveryRecieverState extends State<DeliveryReciever> {
List datas;
File imagePath;
bool validasi = false;
String namaPenerima;
final _keyFormReceiver = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
datas = this.datas;
print(datas);
return DefaultTabController(
length: 1,
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
bottom: TabBar(
tabs: <Widget>[
Tab(
icon: Icon(Icons.local_shipping),
text: "Bukti Delivery",
),
],
),
elevation: 0.1,
// backgroundColor: Colors.cyan[800],
flexibleSpace: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF17ead9), Color(0xFF6078ea)]),
),
),
title: Text(
"Delivery",
style: TextStyle(
fontFamily: "Popins-Bold",
fontSize: ScreenUtil.getInstance().setSp(46),
letterSpacing: .6,
fontWeight: FontWeight.bold,
),
),
actions: <Widget>[
],
),
body: TabBarView(
children: <Widget>[
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(
left: 15.0, right: 15.0, top: 15.0, bottom: 15.0),
child: Column(
children: <Widget>[
Container(
width: double.infinity,
height: ScreenUtil.getInstance().setHeight(470),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8.0),
boxShadow: [
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, 15.0),
blurRadius: 15.0),
BoxShadow(
color: Colors.black12,
offset: Offset(0.0, -10.0),
blurRadius: 10.0)
]),
child: Padding(
padding: EdgeInsets.only(
left: 16.0, right: 16.0, top: 16.0),
child: Form(
key: _keyFormReceiver,
autovalidate: validasi,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Nama Penerima",
style: TextStyle(
fontSize:
ScreenUtil.getInstance().setSp(30),
fontFamily: "Poppins-Bold",
letterSpacing: .6),
),
SizedBox(
height:
ScreenUtil.getInstance().setHeight(30),
),
TextFormField(
validator: validasiReceivername,
onSaved: (String nama) {
namaPenerima = nama;
},
decoration: InputDecoration(
hintText: "Nama Penerima",
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 12.0)),
),
SizedBox(
height:
ScreenUtil.getInstance().setHeight(50),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: RaisedButton(
elevation: 7.0,
color: Colors.green,
padding: EdgeInsets.all(20.0),
child: Text("LANJUT"),
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(10)),
onPressed: () {
parseData();
},
),
),
],
),
],
),
)),
),
],
),
),
),
],
),
bottomNavigationBar: Container(
height: 55.0,
child: BottomAppBar(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF17ead9), Color(0xFF6078ea)]),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
icon: Icon(Icons.home, color: Colors.white),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => halamanUtama()),
);
},
),
IconButton(
icon: Icon(Icons.nature_people, color: Colors.white),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UpcomingDelivery()),
);
},
),
IconButton(
icon: Icon(Icons.local_shipping, color: Colors.white),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ListDelivery()),
);
},
),
],
),
),
),
),
));
}
String validasiReceivername(String value) {
if (value.length == 0) {
//Toast.show("Password more than 4 ", context,duration: Toast.LENGTH_SHORT, gravity: Toast.CENTER);
return "Nama penerima tidak boleh kosong.";
} else {
return null;
}
}
void parseData() async {
if (_keyFormReceiver.currentState.validate()) {
_keyFormReceiver.currentState.save();
_keyFormReceiver.currentState.reset();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CustomerSignatureProof(
created_name: widget.created_name,
wmsorders_id: widget.wmsorders_id,
imagePath: widget.imagePath,
imageName: widget.imageName,
receiverName: namaPenerima,
upcoming_id: widget.upcoming_id,
upcoming_sku: widget.upcoming_sku,
upcoming_sak: widget.upcoming_sak,
upcoming_qty: widget.upcoming_qty,
upcoming_shipstatid: widget.upcoming_shipstatid,
upcoming_picname: widget.upcoming_picname,
upcoming_pictelp: widget.upcoming_pictelp,
upcoming_ordermultipleid: widget.upcoming_ordermultipleid,
upcoming_orderdetid: widget.upcoming_orderdetid,
upcoming_coordinatorid: widget.upcoming_coordinatorid,
upcoming_shipmentid: widget.upcoming_shipmentid)));
}
}
}
Here is the error in terminal,
Have anybody face the same probles as me, please give your guidance..