繁体   English   中英

如何在 Flutter 中为选定的 ListTile 添加样式?

[英]How to add styling to selected ListTile in Flutter?

我有多个列表图块,我想为选定的一个添加一些样式。 为了设置所选图块的颜色,我使用了ListTileTheme因此无论选择哪个图块都将获得ListTileTheme定义的颜色。

ListTileTheme(
  selectedTileColor: Colors.white,
  child: ...
),

我还想在ListTile左上角和左下角设置边框半径,为此我使用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,
  ),
),

这很好用,如下图所示:

在此处输入图像描述

但我必须手动将其添加到特定的列表磁贴中。 与定义一次的选定图块颜色不同,它会自动应用于选定属性为真的任何图块,如何以类似的方式设置ClipRRect ,以便选择的图块在左上角和左下角接收边框半径?

为了给选定的列表磁贴添加样式,我使用了ListView.builder ,添加了所有菜单项以显示在地图的列表磁贴中。

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,
    }
];

然后使用ListView.builder循环遍历它们。

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函数确保单击的菜单项将selected属性设置为 true。 正如所发布的那样,选定的瓷砖颜色设置为 true,无论哪个瓷砖为白色,都从ClipRRect获取圆角半径。

您可以使用此代码:

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,
               ),
             ),
         ),
       ],
     ),
   );
 }

}

希望它的帮助! 但这不是一个好的解决方案。你应该使用构建器

你可能犯了和我一样的错误,并且没有研究 ListTile 的所有属性。 ListTile 有几个有用的属性,例如shapeselectedTileColor可以解决您的问题。

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),
    );
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM