Reputation: 5565
I have multiple List Tiles and I want to add a few styles to the one which is selected. To set the color of the selected tile, I have used ListTileTheme
so whichever tile gets selected will get the color defined in ListTileTheme
.
ListTileTheme(
selectedTileColor: Colors.white,
child: ...
),
I also want to set border radius on top left and bottom left of ListTile
, for this purpose I am using ClipRRect
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32),
bottomLeft: Radius.circular(32),
),
child: ListTile(
leading: Icon(Icons.people),
title: Text('Teams'),
onTap: () {},
selected: true,
),
),
This works well as can be seen in the image below:
but I had to manually add it to a particular list tile. Unlike selected tile color which was defined once and it got applied automatically on any tile where the selected property is true, how to set ClipRRect
too in similar fashion so that whichever tile gets selected receives border radius on top left and bottom left?
Upvotes: 12
Views: 31502
Reputation: 2561
You have probably done the same mistake as i did and did not study all properties of ListTile. ListTile has several useful properties like shape
or selectedTileColor
that can solve your problems.
import 'package:flutter/material.dart';
class SideMenuItem extends StatelessWidget {
final String title;
final IconData icon;
final GestureTapCallback onTap;
final bool active;
const SideMenuItem({required this.title, required this.icon, required this.onTap, required this.active, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
var borderRadius = const BorderRadius.only(topRight: Radius.circular(32), bottomRight: Radius.circular(32));
return ListTile(
shape: RoundedRectangleBorder(borderRadius: borderRadius),
selectedTileColor: Colors.orange[100],
selected: active,
onTap: () {},
leading: Icon(icon),
title: Text(title),
);
}
}
Upvotes: 20
Reputation: 5565
To add styling to selected List Tile, I used ListView.builder
, added all the menu items to display in list tile in a Map.
final List<Map<String, dynamic>> _menuItem = [
{
"title": "Home",
"icon": Icon(Icons.home),
"selected": false,
},
{
"title": "Teams",
"icon": Icon(Icons.people),
"selected": true,
},
{
"title": "Ideas",
"icon": Icon(Icons.lightbulb),
"selected": false,
}
];
and then using ListView.builder
to loop through them.
ListView.builder(
itemCount: _menuItem.length,
itemBuilder: (context, index) {
return ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(32),
bottomLeft: Radius.circular(32),
),
child: ListTile(
leading: _menuItem[index]['icon'],
title: Text(_menuItem[index]['title']),
selected: _menuItem[index]['selected'],
onTap: () {
if (!_menuItem[index]['selected'])
changeSelectedMenu(index);
},
),
);
},
)
changeSelectedMenu
function ensures that the clicked menu item gets the selected
property set to true. As posted in question, selected tile color is set to true and whichever tile is white gets the rounded radius from ClipRRect
.
Upvotes: 7
Reputation: 11
you can use this code:
class MyListTile extends StatefulWidget {
@override
_MyListTileState createState() => _MyListTileState();
}
class _MyListTileState extends State<MyListTile> {
int index ;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.cyanAccent,
body: ListView(
children: [
ClipRRect(
borderRadius: index != null && index == 0?BorderRadius.only(
topLeft: Radius.circular(32),
bottomLeft: Radius.circular(32),
):BorderRadius.only(
topLeft: Radius.circular(0),
bottomLeft: Radius.circular(0),
),
child:Container(
color: index != null && index == 0?Colors.white:null,
child: ListTile(
focusColor: Colors.white,
leading: Icon(Icons.people),
title: Text('Teams'),
onTap: () {
setState(() {
index = 0;
});
},
selected: index != null && index == 0?true:false,
),
),
),
ClipRRect(
borderRadius: index != null && index == 1?BorderRadius.only(
topLeft: Radius.circular(32),
bottomLeft: Radius.circular(32),
):BorderRadius.only(
topLeft: Radius.circular(0),
bottomLeft: Radius.circular(0),
),
child:Container(
color: index != null && index == 1?Colors.white:null,
child: ListTile(
leading: Icon(Icons.people),
title: Text('Teams'),
onTap: () {
setState(() {
index = 1;
});
},
selected: index != null && index == 1,
),
),
),
ClipRRect(
borderRadius: index != null && index == 2?BorderRadius.only(
topLeft: Radius.circular(32),
bottomLeft: Radius.circular(32),
):BorderRadius.only(
topLeft: Radius.circular(0),
bottomLeft: Radius.circular(0),
),
child:Container(
color: index != null && index == 2?Colors.white:null,
child: ListTile(
leading: Icon(Icons.people),
title: Text('Teams'),
onTap: () {
setState(() {
index = 2;
});
},
selected: index != null && index == 2,
),
),
),
ClipRRect(
borderRadius: index != null && index == 3?BorderRadius.only(
topLeft: Radius.circular(32),
bottomLeft: Radius.circular(32),
):BorderRadius.only(
topLeft: Radius.circular(0),
bottomLeft: Radius.circular(0),
),
child:Container(
color: index != null && index == 3?Colors.white:null,
child: ListTile(
leading: Icon(Icons.people),
title: Text('Teams'),
onTap: () {
setState(() {
index = 3;
});
},
selected: index != null && index == 3,
),
),
),
],
),
);
}
}
hope its help! but that's not good solution .you should use builder
Upvotes: 1