Reputation: 153
How can I change the color of the CARD widget if one of the gridview items is clicked and then the CARD changes color? But you can only choose one item. How do I make it?
Widget listDenomPulsa(AsyncSnapshot <List<Payload>> snapshot) {
return GridView.builder(
shrinkWrap: false,
scrollDirection: Axis.vertical,
itemCount: snapshot.data.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width / (MediaQuery.of(context).size.height / 3),
),
itemBuilder: (BuildContext context, int index) {
bool _selectItem = false;
return GestureDetector(
onTap: () {
setState(() {
_selectItem = true;
});
},
child: Card(
color: _selectItem ? Colors.blue:Colors.amber,
child: Container(
height: SizeConfig.heightMultiplier * 3,
child: Padding(
padding: EdgeInsets.all(SizeConfig.heightMultiplier * 3),
child: Text(
snapshot.data[index].desc,
style: AppTheme.styleSubTitleBlackSmall,
),
),
),
),
);
}
);
}
Upvotes: 4
Views: 9006
Reputation: 2481
This is my code, I use Visibility widget to select item
Init
bool _isLoading = true;
bool _isSelectionMode = false;
int _totalImage = 0;
List<AssetEntity>? _entities;
final Set<int> _listSelected = {};
Code
@override
Widget build(BuildContext context) {
if (_isLoading) {
return const Center(child: CircularProgressIndicator.adaptive());
} else {
if (_totalImage == -1) {
return const Center(child: Text("Permission is not accessible."));
}
if (_totalImage == 0) {
return const Center(child: Text("No image/video on device"));
} else {
return GridView.builder(
itemCount: _entities!.length,
shrinkWrap: false,
scrollDirection: Axis.vertical,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
/*mainAxisSpacing: 1,
crossAxisSpacing: 1,*/
),
itemBuilder: (BuildContext context, int index) {
final AssetEntity entity = _entities![index];
return Material(
child: InkWell(
onTap: () {
if (_isSelectionMode) {
setState(() {
developer.log('${_listSelected.contains(index)}',
name: 'Click');
if (_listSelected.contains(index)) {
_listSelected.remove(index);
} else {
_listSelected.add(index);
}
});
}
},
onLongPress: () {
if (_isSelectionMode) return;
_isSelectionMode = true;
setState(() {
developer.log('${_listSelected.contains(index)}',
name: 'Click');
if (_listSelected.contains(index)) {
_listSelected.remove(index);
} else {
_listSelected.add(index);
}
});
},
child: Card(
child: Stack(
alignment: AlignmentDirectional.center,
fit: StackFit.expand,
children: [
AssetEntityImage(entity, fit: BoxFit.cover),
Visibility(
visible: _listSelected.contains(index),
child: const Icon(
Icons.check_circle,
color: Colors.green,
),
),
],
),
),
),
);
},
findChildIndexCallback: (Key key) {
// Re-use elements.
if (key is ValueKey<int>) {
return key.value;
}
return null;
},
);
}
}
}
Upvotes: 0
Reputation: 14043
This would work perfectly. Check the code below:
class MyGridView extends StatefulWidget {
@override
_MyGridViewState createState() => _MyGridViewState();
}
class _MyGridViewState extends State<MyGridView> {
// Set an int with value -1 since no card has been selected
int selectedCard = -1;
@override
Widget build(BuildContext context) {
return GridView.builder(
shrinkWrap: false,
scrollDirection: Axis.vertical,
itemCount: 10,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 3),
),
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () {
setState(() {
// Ontap of each card, set the defined int to the grid view index
selectedCard = index;
});
},
child: Card(
// Check if the index is equal to the selected Card integer
color: selectedCard == index ? Colors.blue : Colors.amber,
child: Container(
height: 200,
width: 200,
child: Center(
child: Text(
'$index',
style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
),
);
});
}
}
Output:
Upvotes: 10