Preserve Selected item in Listview, Flutter - flutter

I have a Listview with 3 List Items, I need to select an item then it should be stays as selected,if click on another the previous selected item should be unselcted, and also change the Container color,but the problem is it's throws errror like this
Error:
The getter 'isSelected' isn't defined for the class 'String'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'isSelected'.
color: physical_status[index].isSelected ? Colors.red[100] : Colors.white,
Code For Listview
final List<String> physical_status = <String>['0', '1', '2'];
bool isSelected = false;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
physical_status[index].isSelected = true;
});
},
child: Container(
width: 100,
height: 100,
color: physical_status[index].isSelected ? Colors.red[100] : Colors.white,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
}

You're trying to access isSelectable property from physical_status list element. But elements are strings, and String doesn't have such property.
You need to either store selectedItems separately, or convert physical_status list to a list of objects instead.
I would take the first approach:
final List<String> physical_status = <String>['0', '1', '2'];
Set<String> physical_status_selected = Set();
bool isSelected = false;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
physical_status_selected.add(physical_status[index]);
});
},
child: Container(
width: 100,
height: 100,
decoration: new BoxDecoration(
color: physical_status_selected.contains(physical_status[index]) ? Colors.red[100] : Colors.white,
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),

You can use list of bool instead of String and also manage which item is currently selected using another variable.
Following code will help you more.
final List<bool> physical_status = <bool>[false, false, false];
int currentSelectedIndex = 0;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: physical_status.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
physical_status[currentSelectedIndex] = false;
currentSelectedIndex = index;
physical_status[index] = true;
});
},
child: Container(
width: 100,
height: 100,
decoration: new BoxDecoration(
color: physical_status[index]
? Colors.red[100]
: Colors.white,
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage("assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
);
}

Change physical_status[index].isSelected to isSelected
Also put color: isSelected ? Colors.red[100] : Colors.white, inside BoxDecoration
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
height: 110,
width: size.width,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
print("clicked");
setState(() {
isSelected = true;
});
},
child: Container(
width: 100,
height: 100,
decoration: new BoxDecoration(
color:
isSelected ? Colors.red[100] : Colors.white,
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
"assets/images/user_avatar.png")),
),
),
),
);
},
),
),
],
),
),
You may also create a class like this.
class Item {
final String physical_status;
final bool isSelected;
Item({this.physical_status, this.isSelected});
}
List<Item> itemList = <Item>[
Item(
physical_status: '1',
isSelected: true),
Item(
physical_status: '2',
isSelected: false),
Item(
physical_status: '3',
isSelected: false),
];

Related

Change the color of an element when another element is selected in the ListView Flutter

Tell. When I select an item in the list, the item's color changes to green, so I can select all items - all items change color to green. But I need that when another element is selected, the previous element returns to its previous state. That is, so that only one element can burn green, and not all. Tell me how to implement? I will be grateful.
code
class _ListPoynts extends State<ListPoynts> {
final List<bool> _selected = [];
#override
void initState() {
for (var i = 0; i < poynts.length; i++) {
_selected.add(false);
}
super.initState();
}
ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: poynts.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Stack(
alignment: Alignment.topRight,
children: [
Positioned(
child: Container(
width: 176,
alignment: Alignment.bottomCenter,
child: InkWell(
onTap: () {
setState(() {
_selected[index] = !_selected.elementAt(index);
});
},
child: Container(
height: 72,
width: 146,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: _selected[index]
? constants.Colors.greenMiddle
: constants.Colors.greyDark.withOpacity(0.7),
),
I would instead of a list of selected, just have an int. selectedIndex for example. Something like this might work:
class _ListPoynts extends State<ListPoynts> {
int? _selectedIndex;
#override
void initState() {
//no need to do anything here now
super.initState();
}
ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: poynts.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Stack(
alignment: Alignment.topRight,
children: [
Positioned(
child: Container(
width: 176,
alignment: Alignment.bottomCenter,
child: InkWell(
onTap: () {
setState(() {
_selectedIndex = index;
});
},
child: Container(
height: 72,
width: 146,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: _selectedIndex == index
? constants.Colors.greenMiddle
: constants.Colors.greyDark.withOpacity(0.7),
),
Use the one variable to save the selected index item. And use the null if there is no selected index.
class _ListPoynts extends State<ListPoynts> {
int? _selectedIndex; // <-- HERE
#override
Widget build(BuildContext context) {
return ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: poynts.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Stack(
alignment: Alignment.topRight,
children: [
Positioned(
child: Container(
width: 176,
alignment: Alignment.bottomCenter,
child: InkWell(
onTap: () {
setState(() {
if (_selectedIndex == index) { // <-- HERE
_selectedIndex = null;
} else {
_selectedIndex = index;
}
});
},
child: Container(
height: 72,
width: 146,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: _selectedIndex == index
? constants.Colors.greenMiddle
: constants.Colors.greyDark.withOpacity(0.7),
),
),
),
),
),
],
),
);
}
}

Horizontal scrollable container with repeating image as decoration

I am trying to create a horizontal listView with a background that is repeating until the list ends.
Basically recycler view with a wrap_content with repeating background
This is my code now:
class _MyHomePageState extends State<MyHomePage> {
double _offsetY = 0.0;
late ScrollController _scrollController;
_scrollListener() {
setState(() {
_offsetY = _scrollController.offset;
});
}
#override
void initState() {
_scrollController = ScrollController();
_scrollController.addListener(_scrollListener);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/town_background.jpg'),
fit: BoxFit.fitHeight,
repeat: ImageRepeat.repeatX,
alignment: FractionalOffset((_offsetY / 1000), 0),
),
),
child: Flex(direction: Axis.horizontal, children: [
Flexible(
child: ListView.separated(
controller: _scrollController,
itemCount: 40,
separatorBuilder: (_, __) => const Divider(
indent: 30,
),
itemBuilder: (_, index) => const Icon(Icons.person, size: 50),
scrollDirection: Axis.horizontal,
),
),
]),
),
);
}
}
Listview scrolls with the background but it never repeats.
*alignment offset is for parallax effect.
try:
repeat: ImageRepeat.repeat,
or try :
Positioned.fill(child:
Container(
width: double.infinity,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/town_background.jpg'),
fit: BoxFit.fitHeight,
repeat: ImageRepeat.repeatX,
alignment: FractionalOffset((_offsetY / 1000), 0),
),
),
child: Flex(direction: Axis.horizontal, children: [
Flexible(
child: ListView.separated(
controller: _scrollController,
itemCount: 40,
separatorBuilder: (_, __) => const Divider(
indent: 30,
),
itemBuilder: (_, index) => const Icon(Icons.person, size: 50),
scrollDirection: Axis.horizontal,
),
),
]),
),)

How to Implement a manual carousel slider in Flutter?

I am creating a product image carousel which contains pictures of shoes where the user can change the image to be viewed by selecting a different color.
The user can manually scroll through the images without an issue,however when I try to manually change the displayed carousel image, only the indicator changes, but the image remains on the first image.
class DetailsPage extends StatefulWidget {
final String url;
final String title;
final int index;
DetailsPage({this.url, this.title, this.index});
#override
_DetailsPageState createState() => _DetailsPageState();
}
class _DetailsPageState extends State<DetailsPage> {
List imgList = [
'https://i.dlpng.com/static/png/6838599_preview.png',
'https://www.manelsanchez.pt/uploads/media/images/nike-air-force-max-ii-blue-fury-18.jpg',
'https://www.vippng.com/png/detail/30-302339_nike-women-running-shoes-png-image-transparent-background.png',
];
int _current = 0;
String selected = "grey";
List<T> map<T>(List list, Function handler) {
List<T> result = [];
for (var i = 0; i < list.length; i++) {
result.add(handler(i, list[i]));
}
return result;
}
final CarouselController _buttonCarouselController = CarouselController();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).canvasColor,
appBar: AppBar(
title: Center(
child: Text(
'Details',
style: TextStyle(
fontFamily: 'OpenSansLight',
fontSize: 26,
color: Theme.of(context).textTheme.headline1.color),
),
),
body: ListView(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
//Carousel Slider
CarouselSlider.builder(
options: CarouselOptions(
carouselController: _buttonCarouselController,
height: 200.0,
enlargeCenterPage: true,
enlargeStrategy: CenterPageEnlargeStrategy.height,
initialPage: 0,
reverse: false,
autoPlay: false,
enableInfiniteScroll: false,
scrollDirection: Axis.horizontal,
onPageChanged: (index, fn) {
setState(() {
_current = index;
});
}),
itemCount: imgList.length,
itemBuilder: (BuildContext context, int index) =>
Builder(builder: (BuildContext context) {
return Image.network(
imgList[index],
fit: BoxFit.contain,
);
}),
),
SizedBox(height: 10),
//Indicator to show current index of images
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(imgList, (index, url) {
return Container(
width: 30.0,
height: 2.0,
margin: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 4.0),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
color: _current == index
? Colors.deepPurple
: Colors.grey,
),
);
}),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 30,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Color',
style: TextStyle(
fontFamily: 'OpenSansLight',
fontSize: 24)),
],
),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: width,
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: imgList.length,
itemBuilder: (BuildContext context, int index) {
//Color selector from images to manually control the carousel
return GestureDetector(
onTap: () {
setState(() {
selected = imgList[index];
_current = index;
_buttonCarouselController
.animateToPage(_current);
print('I HAVE SELECTED $selected');
});
},
child: ColorTicker(
image: imgList[index],
selected: selected == imgList[index],
),
);
},
),
),
),
],
),
);
Color Ticker Widget
class ColorTicker extends StatelessWidget {
final image;
final bool selected;
ColorTicker({this.image, this.selected});
#override
Widget build(BuildContext context) {
print(selected);
return Container(
margin: EdgeInsets.all(5),
width: 100,
height: 100,
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.scaleDown, image: NetworkImage(image)),
shape: BoxShape.circle,
border: selected
? Border.all(color: Colors.deepPurple, width: 3)
: Border.all(color: Colors.grey[500])),
// color: color.withOpacity(0.7)),
child: selected
? Center(child: Icon(Icons.check, size: 40, color: Colors.deepPurple))
: Container(),
);
}
}
I've tried all I could from the documentation : https://pub.dev/packages/carousel_slider/example
But I kept getting an error
Unhandled Exception: NoSuchMethodError: The getter 'options' was called on null
I am almost embarassed at my mistake.
In the configuration of the slider, I placed the controller in the wrong place.
I put the controller inside the Carousel options instead of under CarouselSlider
CarouselSlider(
carouselController: _buttonCarouselController,
options: CarouselOptions(
... ))
It now works :)

The operator '[]' isn't defined for the type 'Type'. Try defining the operator '[]'

I have a home screen where at the top I declared a listview, with scrolldirection taking information from a list.dart file. This horizontal scrolling screen brings me 5 images and a text in each of them. I would like to insert an onpress directing to other screens according to the information passed in this list. Example: Chat, direct to chat.screen.
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height * 4 / 7,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xff40dedf), Color(0xff0fb2ea)],
),
),
),
Positioned(
top: 100,
left: 20,
child: Container(
height: 100,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categoryData.length,
itemBuilder: (context, index) {
bool isSelected = true;
if (index == 0) {
isSelected = true;
}
Navigator.push<dynamic>(
context,
MaterialPageRoute<dynamic>(
builder: (BuildContext
context) =>
HomeList[index].navigateScreen,
),
);
return Row(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: 65,
height: 65,
decoration: BoxDecoration(
color: isSelected
? Colors.transparent
: Colors.transparent,
borderRadius:
BorderRadius.circular(16),
border: Border.all(
color: Colors.white,
width: 1,
),
boxShadow: isSelected
? [
BoxShadow(
color: Color(0x14000000),
blurRadius: 10)
]
: null),
child: Center(
child: Image.asset(categoryData[index].imageUrl),
),
),
SizedBox(
height: 10,
),
Text(
categoryData[index].name,
style: TextStyle(color: Colors.white, fontSize: 15),
),
],
),
SizedBox(
width: 20,
)
],
);
},
),
),
),
Homelist
import 'package:flutter/material.dart';
import 'package:projeto/pages/chat.screen.dart';
class HomeList {
HomeList({
this.navigateScreen,
this.imagePath = '',
});
Widget navigateScreen;
String imagePath;
static List<HomeList> homeList = [
HomeList(
imagePath: 'assets/page1/usuario.png',
navigateScreen: ChatScreen(),
),
HomeList(
imagePath: 'assets/page1/entregas.png',
navigateScreen: ChatScreen(),
),
HomeList(
imagePath: 'assets/page1/msg.png',
navigateScreen: ChatScreen(),
),
HomeList(
imagePath: 'assets/page1/configurações.png',
navigateScreen: ChatScreen(),
),
HomeList(
imagePath: 'assets/page1/sair.png',
navigateScreen: ChatScreen(),
),
];
}
from what i understand, you want to transform the data in your HomeList file to a listview where clicking on one of its items takes you to its related page, you could use a ListView.builder with an itemBuilder and itemCount, the code below shows how you can achieve a listView where items are images with text in them and an onTap function:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return GestureDetector(
child: Stack(
children: <Widget>[
Image.asset(
homeList[index].imagePath,
),
Positioned(child: Text())
],
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => homeList[index].navigateScreen),
),
);
},
itemCount: homeList.length,
),
);
}
}

I want to add a new element after my horizontal listview how can I add it

This is the projected picture that shows how I am able to add an element.
Below is my code in which I want to add an element so that if my list is not present it also shows the element and if it present then the element is the last element.
I have tried this in some different ways.
Can anyone please help me?
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'alllist.dart';
List<Alllist> _alllist = [];
List<Alllist> get alllist => _alllist;
class EduCategory extends StatefulWidget{
final String listcategory;
final int intp;
EduCategory({this.listcategory,this.intp});
#override
EduCategoryState createState() {
return new EduCategoryState();
}
}
class EduCategoryState extends State<EduCategory> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return Container(child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
widget.listcategory,
style: TextStyle(fontWeight: FontWeight.bold),
),
new Row(
children: <Widget>[
new Icon(Icons.play_arrow),
new Text("Watch All", style: TextStyle(fontWeight: FontWeight.bold))
],
)
],
),
Expanded(
child: new Padding(
padding: const EdgeInsets.only(top: 8.0),
child:new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('all list').where("listcategory",isEqualTo: widget.listcategory).snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text("no");
if (snapshot.data.documents.length == 0) return InkWell(
child: Stack(
children: <Widget>[
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
border: Border.all(color: Colors.blueGrey),
borderRadius: BorderRadius.circular(5.0),
image: new DecorationImage(
fit: BoxFit.fill,
image: new AssetImage("assets/Plus.png")),
),
margin: const EdgeInsets.symmetric(horizontal: 20.0),
// child: Text(name),
),
Padding(padding: EdgeInsets.only(top: 80.0,left: 20.0),
child: Text("Add Lession",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blueGrey),),
),
],
),
onTap: (){},
);
return new ListView(
scrollDirection: Axis.horizontal,
children: buildGrid(snapshot.data.documents)
);;
}
),
))
],
),
);
}
List<Widget> buildGrid(List<DocumentSnapshot> documents) {
List<Widget> _gridItems = [];
_alllist.clear();
for (DocumentSnapshot document in documents) {
_alllist.add(Alllist.fromDocument(document));
}
for (Alllist alllist in _alllist) {
_gridItems.add(buildGridItem(alllist));
}
return _gridItems;
}
Widget buildGridItem(Alllist alllist,) {
return widget.intp==0?
InkWell(
child: Stack(
children: <Widget>[
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.blue,width: 4.0,style: BorderStyle.solid),
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
alllist.imageUrl)),
),
margin: const EdgeInsets.symmetric(horizontal: 20.0),
// child: Text(name),
),
Padding(padding: EdgeInsets.only(top: 80.0,left: 10.0),
child: Text(alllist.title,style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blueGrey),),
),
],
),
onTap: (){},
):new Row(
children: <Widget>[
InkWell(
child: Stack(
children: <Widget>[
new Container(
width: 80.0,
height: 80.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(5.0),
image: new DecorationImage(
fit: BoxFit.fill,
image: new NetworkImage(
alllist.imageUrl)),
),
margin: const EdgeInsets.symmetric(horizontal: 20.0),
// child: Text(name),
),
Padding(padding: EdgeInsets.only(top: 80.0,left: 10.0),
child: Text(alllist.title,style: TextStyle(fontWeight: FontWeight.bold,color: Colors.blueGrey),),
),
],
),
onTap: (){},
)
]
);
}
}
You can use the ListView.builder with itemCount as snapshot.data.documents.length + 1.
Code sample:
new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance.collection('all list').where("listcategory",isEqualTo: widget.listcategory).snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text("no");
var documentsLength = snapshot.data.documents.length;
ListView.builder(itemCount: documentsLength + 1, // +1 for last element
itemBuilder: (context, index) {
if (index == documentsLength) {
//last view which have plus button
} else {
return buildGridItem((Alllist.fromDocument(snapshot.data.documents[index]))
}
});
})
I think that you have to just add condition in itemBuilder checkout in below code;
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final List<int> items=[1,2,3,4,5,6];
#override
Widget build(BuildContext context) {
final title = 'Mixed List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Container(
height: 100.0,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: items.length + 1 ,
itemBuilder: (context, index) {
if(index < items.length )
{ return Container(
color: Colors.blue,
width: 100.0,
padding: EdgeInsets.all(8.0),
child: new Center(
child: new Text(index.toString()),
),
);
}
else {
return new Container(
color: Colors.blue,
width: 100.0,
child: new Center(
child: new Text(index.toString() + "differnt"),
),
);
}
},
),
),
),
);
}
}