Why i used getX not work in flutter ListView? - flutter

when I tap containter and update selectedIndex equal current index, but it not will update.
class HomeController extends GetxController {
final RxList<PurineTypeModel> dataSource = RxList();
final selectedIndex = 0.obs;
}
Obx(() {
return ListView.builder(
cacheExtent: 30,
scrollDirection: Axis.horizontal,
itemBuilder: (c, index) {
print("refresh?? $index");
return GestureDetector(child: Container(
width: 100,
color: controller.selectedIndex.value == index ? Colors.red : Colors.green,
child: Text(
controller.selectedIndex.string),
), onTap: () {
controller.selectedIndex.value = 1;
},);
},
itemCount: controller.dataSource.length);
})

onTap: () {
controller.selectedIndex.value = index;
},);
setup index element not 1
the controller is initialized how?

You need to wrap the GestureDetector also in an Obx, so like this:
Obx(() {
return ListView.builder(
cacheExtent: 30,
scrollDirection: Axis.horizontal,
itemBuilder: (c, index) {
print("refresh?? $index");
return Obx(() =>
GestureDetector(child: Container(
width: 100,
color: controller.selectedIndex.value == index ? Colors
.red : Colors.green,
child: Text(
controller.selectedIndex.string),
), onTap: () {
controller.selectedIndex.value = 1;
},));
},
itemCount: controller.dataSource.length);
})
Because the outer Obx only observes controller.dataSource.length

Related

Flutter swiper. Go to the first index

I need a Function to make the swiper go to the first index I have
I am using card_swiperpackage
Swiper(
loop: true,
itemCount: 2,
itemBuilder: (context, index) {
return Image.asset(index == 0
? blackImages[imageNumber].imagePath
: blackImages[imageNumber].imagePath1);
},
),
am just using setState for state management
Use a SwiperController
final controller = SwiperController();
.....
Swiper(
controller: controller,
and to move 1st index use , no need to call setState
controller.move(0);
Test snippet
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
controller.move(0);
},
),
body: Column(
children: [
Swiper(
controller: controller,
loop: true,
itemCount: 2,
itemBuilder: (context, index) {
return Container(
color: index.isEven ? Colors.red : Colors.blue,
);
},
),
],
),
);

Limiting the visibility of the selection|ListView

I have a ListView inside a Column:
SizedBox(width: 100, height: 100, child: ListView.builder(
shrinkWrap: true,
itemCount: _listHours.length,
itemBuilder: (context, index) {
return ListTile(
title: Center(child: Text(_listHours[index].toString())),
selected: index == _selectedIndexHours,
dense: true,
selectedTileColor: Colors.indigo.withOpacity(0.6),
onTap: () {
setState(() {
_selectedIndexHours = _listHours[index];
});
},
);
}
),),
When an item is selected, the selection itself is visible by scrolling the entire length of the screen.
You are having a problem similar to this one where the ListTile's decoration renders outside the ListView. There is no solution for this yet but you can implement some workarounds. In this section of code, I set on "null" the ListTile's "onTap" parameter and wrapped it with a GestureDetector widget. Like this:
SizedBox(width: 100, height: 100, child: ListView.builder(
shrinkWrap: true,
itemCount: _listHours.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
_selectedIndexHours = _listHours[index];
});
}
child: ListTile(
title: Center(child: Text(_listHours[index].toString())),
selected: index == _selectedIndexHours,
dense: true,
selectedTileColor: Colors.indigo.withOpacity(0.6),
onTap: null
)
);
}
),
),
I hope this works for you.

Flutter RangeError while when comparing two list

Hello I have 2 list and I want to use these in ListViewBuilder.
List's:
List times = ['08:30', '09:00', '09:30', '10:00', '13:00'];
List obj = [true,false,true];
I tried this:
ListView.builder(
controller: scrollController,
shrinkWrap: true,
itemCount: times.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
setState(() {
selected = index;
debugPrint(tarih[index]);
});
},
child: Container(
color: obj[index] ? Colors.yellow : Colors.red,
height: 30,
width: 12,
child: Text(times[index]),
),
),
);
},
),
Here is the error:
I know what cause's this error. Because of obj.length does not match with times.length
But I still want to create the other Containers.
How do I solve this?
Many ways you can avoid this here min(int,int) method used lowest integer find
obj[min(index,obj.length-1)] ? Colors.yellow : Colors.red,
widget may like this
ListView.builder(
// controller: scrollController,
shrinkWrap: true,
itemCount: times.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {
setState(() {
selected = index;
// debugPrint(tarih[index]);
});
},
child: Container(
color: obj[min(index,obj.length-1)] ? Colors.yellow : Colors.red,
height: 30,
width: 12,
child: Text(times[index]),
),
),
);
},
)
You try to achieve dartpad live
class _MyAppState extends State<MyApp> {
int selected = 0;
#override
void initState() {
super.initState();
}
List times = ['08:30', '09:00', '09:30', '10:00', '13:00'];
List obj = [];
#override
Widget build(BuildContext context) {
var column = Column(
children: [
Container(
height: 200,
child: Row(
children: [
Expanded(
child: Image.network(
"https://upload.wikimedia.org/wikipedia/commons/thumb/3/3c/Salto_del_Angel-Canaima-Venezuela08.JPG/1200px-Salto_del_Angel-Canaima-Venezuela08.JPG",
// fit: BoxFit.cover,
fit: BoxFit.fitWidth,
),
),
],
),
)
],
);
obj = List.generate(times.length, (index) => false);
var children2 = [
ListView.builder(
// controller: scrollController,
shrinkWrap: true,
itemCount: times.length,
itemBuilder: (BuildContext context, int index) {
if (selected == index)
obj[index] = true;
else
obj[index] = false;
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: selected != index
? () {
setState(() {
selected = index;
print(selected);
// debugPrint(tarih[index]);
});
}
: null,
child: Container(
color: obj[index]
? Colors.yellow
: Colors.red,
height: 30,
width: 12,
child: Text(times[index]),
),
),
);
},
),
DropdownButton(
items: [
DropdownMenuItem(
child: Text("1"),
value: "1",
onTap: () {},
)
],
onChanged: (values) {
// _dropdown1=values;
})
];
return MaterialApp(
// theme: theme(),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children2,
)),
);
}
}
Well there might be other ways to do so, what I did was, just to copy the obj list items as many as there are items in times list in order. And if the number is not equal just add remaining number at last.
List times = [
'08:30',
'09:00',
'09:30',
'10:00',
'13:00',
'13:00',
'13:00',
'13:00',
'13:00',
];
List obj = [true, false, true];
#override
Widget build(BuildContext context) {
// Remaining length of times list after we copy
int remaining = times.length % obj.length;
//Exact Number of times to copy obj
int exactNumber = (times.length - remaining) ~/ obj.length;
List shallowList = [];
// Using for loop copy the list as many as exactNumber
for (int i = 0; i < exactNumber; i++) {
shallowList += obj;
}
// Add add remaining subList
// Then we have obj list with same length as times
List finalShallowList = [...shallowList, ...obj.sublist(0, remaining)];
// Create Separate Index for obj that we can reset
return Scaffold(
body: Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: times.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {},
child: Container(
// Loop over finalShallowList instead of obj
color: finalShallowList[index] ? Colors.yellow : Colors.red,
height: 30,
width: 12,
child: Text(times[index]),
),
),
);
},
),
),
);

How to have a tap change only a single item in a ListView?

I'm using a ListView.builder() to display text items from a dynamic list. The text is displayed on Card() widgets. I'd like tapping the text to change its appearance to and from strikeout. I've tried declaring these variables, outside Build():
bool isStrikeout = false;
TextStyle _strikeout =
TextStyle(fontSize: 16, decoration: TextDecoration.lineThrough);
TextStyle _normal = TextStyle(fontSize: 16);
and then, within the Build() method:
body: ListView.builder(
itemCount: someList.length,
itemBuilder: (ctx, index) {
return Card(
elevation: 8,
child: ListTile(
title: InkWell(
onTap: () {
setState(() {
isStrikeout = !isStrikeout;
});
},
child: Container(
padding: const EdgeInsets.all(8),
child: Text(
someList[index].text,
style: isStrikeout ? _strikeout : _normal,
),
// more code here
The problem, of course, is that a user tapping any Card's text will toggle strikeout on and off for all Cards' texts. I only want it to happen for the tapped Card's text.
You need to use List of bool.
Definition
List<bool> strikeList = [];
Initialize
strikeList = List.generate(someList.length, (index)=>false);
Usage
body: ListView.builder(
itemCount: someList.length,
itemBuilder: (ctx, index) {
return Card(
elevation: 8,
child: ListTile(
title: InkWell(
onTap: () {
setState(() {
bool temp = !strikeList[index];
strikeList.removeAt(index);
strikeList.insert(index, temp);
});
},
child: Container(
padding: const EdgeInsets.all(8),
child: Text(
someList[index].text,
style: strikeList[index] ? _strikeout : _normal,
),
// more code here
You try this way
int _selectedIndex = 0;
_onSelected(int index) {
setState(() => _selectedIndex = index);
}
InkWell(
onTap:() => _onSelected(index),
)
Text(
someList[index].text,
style: _selectedIndex == index ? _strikeout : _normal,
),

How to change the color of a container in a row having multiple containers in Flutter

I know this question has been asked before, and here's the link to that question:
How do i change the color and text of Container at onTap event in FLUTTER
However in my case I have around 50 containers in a row, so using the provided solution would be extremely lengthy.
Is there any shortcut using UniqueKeys()??
Try this:
class _TestState extends State<Test> {
int selected = 0;
List<Widget> _containerList() {
return List.generate(50, (index) {
return GestureDetector(
onTap: () {
setState(() {
selected = index;
});
},
child: Container(
height: 200,
width: 200,
color: selected == index ? Colors.blue : Colors.transparent,
child: Text("$index"),
),
);
}).toList();
}
#override
Widget build(BuildContext context) {
return Column(
children: _containerList(),
);
}
}
OR
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 50,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
setState(() {
selected = index;
});
},
child: Container(
height: 200,
width: 200,
color: selected == index ? Colors.blue : Colors.transparent,
child: Text("$index"),
),
);
}
)
OR
Wrap(children: _containerList(),)
You can do something like this..
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
onRefresh: () async {
//write your code here to update the list*********
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
setState(() { _selectedIndex = index; });
},
child: Text(
'Line $index',
style: TextStyle(
color: _selectedIndex == index ? Colors.red : Colors.black,
)
),
);
}
)
),
);
}
}
List<String> _selectedIndexs = [];ListView.separated(
padding: EdgeInsets.zero,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
final _isSelected = _selectedIndexs.contains(index);
return GestureDetector(
onTap: () {
setState(() {
if (_isSelected) {
_selectedIndexs.remove(index);
} else {
_selectedIndexs.add(index);
}
print(_selectedIndexs);
});
},
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 25, vertical: 10),
decoration: BoxDecoration(
color: _isSelected
? ContainerColors.selectedBgColor
: priorityChipBg,
borderRadius: BorderRadii.radius8px,
border: Border.all(
color: _isSelected
? BorderColor.bordersecondaryBlue
: chipBorderColor)),
child: Text(
requestPriority[index],
style: _isSelected
? AppFonts.mediumTextBB.copyWith(
color: TextColors.themeColor,
fontSize: 14,
fontWeight: FontWeight.w900)
: chipTextStyle,
),
),
);
},
separatorBuilder: (BuildContext context, int index) {
return const SizedBox(
width: 20,
);
},
itemCount: 3,
),
),