Button List Select - flutter

I have a list of the button in my flutter app like the picture :enter image description here
and I need to select the container who I'm click on it
for example, change the container color

you can use container or button and GestureDetector like below example
import 'package:flutter/material.dart';
class SelectableGridView extends StatefulWidget {
const SelectableGridView({Key? key}) : super(key: key);
#override
State<SelectableGridView> createState() => _SelectableGridViewState();
}
class _SelectableGridViewState extends State<SelectableGridView> {
int selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey,
body: Padding(
padding: const EdgeInsets.all(16.0),
child: GridView.builder(
physics: const ClampingScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 16.0,
mainAxisSpacing: 16.0,
),
itemCount: 18,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () => setState(() {
selectedIndex = index;
}),
child: Container(
color: selectedIndex == index ? Colors.pink : Colors.white,
),
);
},
),
),
);
}
}

TBH I'm not sure what your asking exactly, but this may or may not help you:
GestureDetector
This will let you respond to clicks on whatever it surrounds, so for example
return
GestureDetector(
onTap: (){
//Do something here to respond to a tap on the child Container()
},
child: Container(...) /// Your box
Now you can do something with it.
Hope this is what you were asking about

You can also use InkWell in this following way,
First you have to declare Color in your instances and after that you can use it in your onPress() widget.
Color _colorContainer = Colors.blue;
Now you can use it in your widget as follow:
Ink(
child: InkWell(
child: Container(
width: 200,
height: 200,
color: _colorContainer ,
),
onTap: () {
setState(() {
_colorContainer = _colorContainer == Colors.red ?
Colors.blue :
Colors.red;
});
},
)),

Related

ElevatedButton nested inside GridView.builder not displaying text

I have a CategoryList that I want to return a list of elevated buttons that are built from some JSON data.
The buttons are built however the text does not display inside the buttons. They are drawn in the app when loaded but the text does not appear.
I have tried to modify the style for it but to no avail and I know that the name in print(categories[index].name); is available but it's not being displayed.
The image below illustrates the problem. The top container is a horizontal list of ElevatedButtons but without the text inside displayed. The container beneath that is static to show what is expected.
Has anyone else run into this issue, if so what was your workaround/solution?
class CategoryList extends StatelessWidget {
const CategoryList({Key? key, required this.categories}) : super(key: key);
final List<Category> categories;
#override
Widget build(BuildContext context) {
return GridView.builder(
padding: const EdgeInsets.all(5.0),
scrollDirection: Axis.horizontal,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: categories.length,
itemBuilder: (context, index) {
return Center(
child: ElevatedButton(
onPressed: () {
print(categories[index].id);
print(categories[index].name);
},
child: Text(categories[index].name,
style: TextStyle(
fontStyle: FontStyle
.normal)),
style: ButtonStyle(
shadowColor: MaterialStateProperty.all<Color>(Colors.black),
backgroundColor:
MaterialStateProperty.all<Color>(Colors.deepPurple),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
),
),
);
},
);
}
}
childAspectRatio == 1.5, try to use a bigger value like 10 to see if it changes.
The solution that solved the problem was to use the switch the GridView.Builder for the ListView.builder and then to change the scroll direction to horizontal.
class CategoryList extends StatelessWidget {
const CategoryList({Key? key, required this.categories}) : super(key: key);
final List<Category> categories;
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: categories.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.only(left: 7, right: 7),
child: ElevatedButton(
onPressed: () {},
child: Text(categories[index]
.name),
style: ButtonStyle(
shadowColor: MaterialStateProperty.all<Color>(Colors.black),
backgroundColor:
MaterialStateProperty.all<Color>(Colors.purple),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
),
));
},
);
}
}

How can I implement selecting only one button from group buttons in flutter

I have added a picture of what I plan to implement. It's a group button where you can only select one option at a time. I used a package called "group_button" but it allows multiple selection at a time which isn't what I want.
Recommend an alternative means of achieving this.
Picture of what I plan to implement
Updated 18.02.2022
They removed old constructor GroupButton.radio and GroupButton.checkbox in version 4.4.0 and still don't updated documentation.
Proper solution is set isRadio property of GroupButton to true.
GroupButton(
isRadio: true,
onSelected: (index, isSelected) => print('$index button is selected'),
buttons: ["12:00", "13:00", "14:30", "18:00", "19:00", "21:40"],
)
Old answer:
Never used that package but by looking on they pub.dev page I can see following.
Now you can use even simpler constructors to build your button groups.
Example for a group with a single value selection:
GroupButton.radio(
buttons: ['12:00', '13:00', '14:00'],
onSelected: (i) => debugPrint('Button $i selected'),
)
Link: https://pub.dev/packages/group_button#cant-easier-to-use
A fully working example for this:
class T extends StatefulWidget {
const T({Key? key}) : super(key: key);
#override
_TState createState() => _TState();
}
class _TState extends State<T> {
List<bool> isCardEnabled = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('T'),
),
body: GridView.builder(
padding: const EdgeInsets.all(15),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3,
crossAxisSpacing: 10,
mainAxisSpacing: 10
),
itemCount: 4,
itemBuilder: (BuildContext context, int index){
isCardEnabled.add(false);
return GestureDetector(
onTap: (){
isCardEnabled.replaceRange(0, isCardEnabled.length, [for(int i = 0; i < isCardEnabled.length; i++)false]);
isCardEnabled[index]=true;
setState(() {});
},
child: SizedBox(
height: 40,
width: 90,
child: Card(
color: isCardEnabled[index]?Colors.cyan:Colors.grey.shade200,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8)
),
child: Center(
child: Text('Ability Tag',
style: TextStyle(
color: isCardEnabled[index]?Colors.white:Colors.grey,
fontSize: 18
),
),
),
),
)
);
}),
);
}
}

Can we change the color of the title which is pressed only in flutter

I have a list of title which is in text. I can change the color of title which in pressed but all the title's color changes.Can I change the the pressed titles only?
I have stored intial color this way
Color color = Colors.yellow;
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.posts.length,
itemExtent: 300.0,
itemBuilder: (context, index) {
final item = state.posts[index];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 6.0),
child: GestureDetector(
onTap: () {
setState(() {
color = Colors.black;
});
},
child: Container(
color: Colors.red,
child: Text(
item.title,
style: TextStyle(color: color),
),
),
),
);
},
),
You can create a list of colors with the same length of your titles, and when you press you can use the same index of the titles to change the color.
/// declare outside build function
List<Color> titleColors = [];
if(colors.isEmpty) {
for(String title in titles) {
colors.add(Colors.yellow);
}
}
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.posts.length,
itemExtent: 300.0,
itemBuilder: (context, index) {
final item = state.posts[index];
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 6.0),
child: GestureDetector(
onTap: () {
setState(() {
titleColors[index] = Colors.black;
});
},
child: Container(
color: Colors.red,
child: Text(
item.title,
style: TextStyle(color: titleColors[index]),
),
),
),
);
},
),
I can see several solutions for this.you can create a separate stateful widget for this or you can use state management method(like provider).
Issue is here
setState(() {
color = Colors.black;
});
when we click one button the whole list view is rebuild using the colour we given.For that we need to keep the main widget state stable and change the list view child state.
try this.first create a list item stateful widget.
import 'package:flutter/material.dart';
class ListItem extends StatefulWidget {
const ListItem({Key key,}) : super(key: key);
#override
_ListItemState createState() => _ListItemState();
}
class _ListItemState extends State<ListItem> {
Color color = Colors.yellow;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: GestureDetector(
onTap: () {
setState(() {
color = Colors.black;
});
},
child: Container(
color: Colors.red,
child: Text(
item.title,
style: TextStyle(color: color),
),
),
),
);
}
}
then add this to your list view.
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: state.posts.length,
itemExtent: 300.0,
itemBuilder: (context, index) {
final item = state.posts[index];
return ListItem();
},
);
this will work.You want to pass the item value to that widget.You have to create a constructor variable and pass it to that ListItem widget.

I have created a card list with listview.builder from api. Now i want to change a card color in inkwell tap when one card is tapped

I want to change a card color when a card is tapped. I made all functioanlities. I set inkwell too for tapping. Everything is ready but i am confused how to change a specific card color when it is tapped. Tried with bool to change a card color. But when i tapped a card all card color is changing. this not i want . I want only one card color should change when it is tapped.
isPressed ? Colors.blueAccent : Colors.white,
InkWell(
onTap: () {
setState(() {
isPressed = !isPressed;
});
in listview.builder i can fetch data in card from api.
ListView.builder(
itemCount: widget.notification == null
? 0
: widget.notification.length,
itemBuilder: (context, index) {
return
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
color: isPressed ? Colors.blueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.all(16.0),
child: InkWell(
onTap: () {
setState(() {
isPressed = !isPressed;
});
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new DetailPage()));
},
child: Column(
children: <Widget>[
Row(
children: [
SizedBox(
width: 20,
),
Text(
'Status',
style: TextStyle(
fontWeight: FontWeight.bold),
),
SizedBox(
width: 67,
),
Text(widget.notification[index]["data"]
["message"]
.toString()),
],
),
You can try this example.
Copy paste the code
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 5,
itemBuilder: (context, index) {
return MyCard(isPressed: false);
});
}
}
class MyCard extends StatefulWidget {
final bool isPressed;
const MyCard({Key key, this.isPressed}) : super(key: key);
#override
_MyCardState createState() => _MyCardState();
}
class _MyCardState extends State<MyCard> {
bool _isPressed;
#override
void initState() {
_isPressed = widget.isPressed;
super.initState();
}
#override
Widget build(BuildContext context) {
return Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
color: _isPressed ? Colors.blueAccent : Colors.white,
child: InkWell(
onTap: () {
setState(() {
_isPressed = !_isPressed;
});
},
child: Container(
height: 50,
),
),
);
}
}

How to change image view in flutter?

I trying to change view from grid to list view.
I used StaggeredGridView for first view but after click change view button it should change into vertical list view .just like instagram gallery view.
Piece of code:
view changing button:
InkWell(
child:view
?Image.asset('assets/icons/view_by1.png')
:Image.asset('assets/icons/view_by3.png'),
onTap: (){
setState(() {
view = !view;
});
}
)
widget for changing view:
Widget sliverGridWidget(BuildContext context, List<Photos> listPhotoDetail){
return StaggeredGridView.countBuilder(
padding: const EdgeInsets.all(8.0),
crossAxisCount: view?2:6, //if view true make it vertical view otherwise grid view
itemCount: listPhotoDetail.length,
itemBuilder: (context, index){
return InkWell(
onLongPress: (){
setState(() {
enable = true;
});
},
child: Container(
decoration: BoxDecoration(
color:Colors.grey[100],
image: DecorationImage(
image: NetworkImage(listPhotoDetail[index].photoDetail.image.fileUrl),
fit: BoxFit.cover
)
),
child:enable? Stack(
children: <Widget>[
Positioned(
bottom: 5,
right: 3,
child: InkWell(
child: listPhotoDetail[index].isSelected
?Image.asset('assets/icons/selected.png')
:Image.asset('assets/icons/select_on_image.png'),
onTap: (){
setState(() {
listPhotoDetail[index].isSelected = !listPhotoDetail[index].isSelected;
count= listPhotoDetail[index].isSelected ?count+1:count-1;
if(listPhotoDetail[index].isSelected){
selectedPhotostList.add(
Photos(
photoDetail:listPhotoDetail[index].photoDetail ,
// contact:contactList[index].contact ,
isSelected:listPhotoDetail[index].isSelected)
);
} else{
selectedPhotostList.removeAt(index);
}
// listPhotoDetail[index].isSelected = ! listPhotoDetail[index].isSelected;
// count = listPhotoDetail[index].isSelected ?count+1:count-1;
});
},
)
)
],
)
:Container()
),
);
},
staggeredTileBuilder: (index)
=> StaggeredTile.count(2, 2), //Make size as you want.
mainAxisSpacing: 8.0,
crossAxisSpacing:8.0,
);
}
}
this does not give me satisfied view
means i have total14 images
and gridview looks perfect and shows all 14 images but when pressed changing view button, it
shows only 3 to 4 images as listview.
see :
Here short video
you can take help of this to solve your problem, click on the floating action button to change the view.
import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
void main(){
runApp(MaterialApp(home: Example01()));
}
List<Widget> _tiles = const <Widget>[
const _Example01Tile(Colors.green, Icons.widgets),
const _Example01Tile(Colors.lightBlue, Icons.wifi),
const _Example01Tile(Colors.amber, Icons.panorama_wide_angle),
const _Example01Tile(Colors.brown, Icons.map),
const _Example01Tile(Colors.deepOrange, Icons.send),
const _Example01Tile(Colors.indigo, Icons.airline_seat_flat),
const _Example01Tile(Colors.red, Icons.bluetooth),
const _Example01Tile(Colors.pink, Icons.battery_alert),
const _Example01Tile(Colors.purple, Icons.desktop_windows),
const _Example01Tile(Colors.blue, Icons.radio),
const _Example01Tile(Colors.pink, Icons.radio),
const _Example01Tile(Colors.yellow, Icons.radio),
const _Example01Tile(Colors.brown, Icons.map),
const _Example01Tile(Colors.deepOrange, Icons.send),
const _Example01Tile(Colors.indigo, Icons.airline_seat_flat),
];
class Example01 extends StatefulWidget {
#override
_Example01State createState() => _Example01State();
}
class _Example01State extends State<Example01> {
bool isList= false;
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Example 01'),
),
body: new Padding(
padding: const EdgeInsets.only(top: 12.0),
child: new StaggeredGridView.countBuilder(
crossAxisCount: 6,
itemCount: _tiles.length,
itemBuilder: (context,i){
return _tiles[i];
},
staggeredTileBuilder: (i)=> isList ?StaggeredTile.count(6,1):StaggeredTile.count(2,2),
mainAxisSpacing: 1.0,
crossAxisSpacing: 1.0,
padding: const EdgeInsets.all(4.0),
)),
floatingActionButton: FloatingActionButton(
child: isList ?Icon(Icons.grid_on):Icon(Icons.list),
onPressed:(){
setState(() {
isList = !isList;
});
},
),
);
}
}
class _Example01Tile extends StatelessWidget {
const _Example01Tile(this.backgroundColor, this.iconData);
final Color backgroundColor;
final IconData iconData;
#override
Widget build(BuildContext context) {
return new Card(
color: backgroundColor,
child: new InkWell(
onTap: () {},
child: new Center(
child: new Padding(
padding: const EdgeInsets.all(4.0),
child: new Icon(
iconData,
color: Colors.white,
),
),
),
),
);
}
}