I have created buttons using ListView.builder
, now i want if i tapped on any button than only that button color should change, but when i tap on any button all buttons color are changing.
here is the code
List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
bool pressAttention=false;
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
itemCount: litems.length,
itemBuilder: (BuildContext ctxt, int index) {
return Column(
children: [
Container(
height: 55.0,
width: MediaQuery.of(context).size.width*0.9,
child: new RaisedButton(
child: new Text(litems[index]),
textColor: Colors.white,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: pressAttention ? Colors.green : Colors.grey,
onPressed: () => setState(() => pressAttention = !pressAttention),
),
),
SizedBox20(),
],
);
}),
),
);
}
}
please help if any one know how to do this.
CodePudding user response:
The simplest way to do this is to extract the button logic in a separate widget. However this will not work if you need every pressAttentions
values in the top widget.
Anyway, here is the simplest way:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Material(child: MyApp())));
}
class MyApp extends StatelessWidget {
final List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
@override
Widget build(BuildContext context) {
return SafeArea(
child: ListView.builder(
shrinkWrap: true,
itemCount: litems.length,
itemBuilder: (context, index) {
return MyButton(title: litems[index]);
}
),
);
}
}
class MyButton extends StatefulWidget {
final String title;
const MyButton({
Key? key,
required this.title,
}) : super(key: key);
@override
State<MyButton> createState() => _MyButtonState();
}
class _MyButtonState extends State<MyButton> {
// Default to non pressed
bool pressAttention = false;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
height: 55.0,
width: MediaQuery.of(context).size.width * 0.9,
child: new RaisedButton(
child: new Text(widget.title),
textColor: Colors.white,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: pressAttention ? Colors.green : Colors.grey,
onPressed: () => setState(() => pressAttention = !pressAttention),
),
),
);
}
}
Here is the way if you need to have the list of pressAttentions
:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Material(child: MyApp())));
}
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
// Initialize with the same length as litems and with only falses
late List<bool> pressedAttentions = litems.map((e) => false).toList();
@override
Widget build(BuildContext context) {
return SafeArea(
child: ListView.builder(
shrinkWrap: true,
itemCount: litems.length,
itemBuilder: (context, index) {
final pressAttention = pressedAttentions[index];
return Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
height: 55.0,
width: MediaQuery.of(context).size.width * 0.9,
child: new RaisedButton(
child: new Text(litems[index]),
textColor: Colors.white,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: pressAttention ? Colors.green : Colors.grey,
onPressed: () => setState(() => pressedAttentions[index] = !pressAttention),
),
),
);
}
),
);
}
}
As a bonus, here is if you want only 1 button at a time only to be selected:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: Material(child: MyApp())));
}
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
// Initialize to -1 so that none are selected
// If you want to select the first by default you could change this to 0
int pressedAttentionIndex = -1;
@override
Widget build(BuildContext context) {
return SafeArea(
child: ListView.builder(
shrinkWrap: true,
itemCount: litems.length,
itemBuilder: (context, index) {
final pressAttention = pressedAttentionIndex == index;
return Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Container(
height: 55.0,
width: MediaQuery.of(context).size.width * 0.9,
child: new RaisedButton(
child: new Text(litems[index]),
textColor: Colors.white,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: pressAttention ? Colors.green : Colors.grey,
onPressed: () => setState(() => pressedAttentionIndex = index),
),
),
);
}
),
);
}
}
As a side note: You seem to have issues with your naming:
- DO you camelCase to name attributes (BAD:
litems
, GOOD:lItems
) - DO start your bool variables be
is
orhas
: (BAD:pressAttention
, GOOD:hasPressedAttention
)
CodePudding user response:
Try below code hope its help to you and one thing used ElevatedButton instead of RaisedButton because current flutter version RaisedButton Widget is depricated.
CodePudding user response:
using type int to mark tapped button,
List<String> litems = ["Counter No 1", "Counter No 2", "Counter No 3", "Counter No 4"];
late int tapIndex;
@override
void initState() {
super.initState();
tapIndex = litems.length; // make sure no buttons are clicked in the initial state
}
Widget build(BuildContext context) {
return SafeArea(
child: SingleChildScrollView(
SizedBox(
height: MediaQuery.of(context).size.height,
child: ListView.builder(
shrinkWrap: true,
itemCount: litems.length,
itemBuilder: (BuildContext ctxt, int index) {
return Column(
children: [
Container(
height: 55.0,
width: MediaQuery.of(context).size.width*0.9,
child: new RaisedButton(
child: new Text(litems[index]),
textColor: Colors.white,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: tapIndex == index ? Colors.green : Colors.grey,
onPressed: () => setState(() => tapIndex = index),
),
),
SizedBox20(),
],
);
}),
),
);
}
}