在 Flutter 中点击另一个项目 ListView 后如何取消选择已经选择的项目?

How to deselect the already selected item after tap on another item ListView in Flutter?

我想允许用户 select 列表中只有一个选项,如果他 select 一个接一个,那么只有最后一个选项应该被视为 selected。

在当前代码中,用户可以从列表中select多个我想避免的选项。

尝试过的代码:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Test App',
      theme: new ThemeData(
        primarySwatch: Colors.red,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<int> indexList = new List();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Selected ${indexList.length}  ' + indexList.toString()),
      ),
      body: new ListView.builder(
        itemCount: 3,    
        itemBuilder: (context, index) {
          return new CustomWidget(  
            index: index,
            callback: () {
              if (indexList.isNotEmpty) {
                indexList.clear();
              } 

            },
          );
        },
      ),
    );
  }
}

class CustomWidget extends StatefulWidget {
  final int index;
  final VoidCallback callback;

  const CustomWidget({Key key, this.index, this.callback}) : super(key: key);

  @override
  _CustomWidgetState createState() => new _CustomWidgetState();
}


class _CustomWidgetState extends State<CustomWidget> {
  bool selected = false;
  CustomWidget lastSelectedWidget;

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: () {
          setState(() {
            lastSelectedWidget = widget;
            print(lastSelectedWidget.key);
            selected = !selected;
          });
          widget.callback();
      },
      child: new Container(
        margin: new EdgeInsets.all(5.0),
        child: new ListTile(
          title: new Text("Title ${widget.index}"),
          subtitle: new Text("Description ${widget.index}"),
        ),
        decoration: selected
            ? new BoxDecoration(color: Colors.black38, border: new Border.all(color: Colors.black))
            : new BoxDecoration(),
      ),
    );
  }
}

我正在实现一种列表样式的单选按钮。

您不能将定义选择哪个 CustomWidget 的责任分配给自己的 CustomWidgetCustomWidget 一定不知道其他 CustomWidget 的存在,也不知道他们持有的信息。

鉴于此,您的 CustomWidget 应该是这样的:

class CustomWidget extends StatefulWidget {
  final int index;
  final bool isSelected;
  final VoidCallback onSelect;

  const CustomWidget({
    Key key,
    @required this.index,
    @required this.isSelected,
    @required this.onSelect,
  })  : assert(index != null),
        assert(isSelected != null),
        assert(onSelect != null),
        super(key: key);

  @override
  _CustomWidgetState createState() => _CustomWidgetState();
}

class _CustomWidgetState extends State<CustomWidget> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.onSelect,
      child: Container(
        margin: EdgeInsets.all(5.0),
        child: ListTile(
          title: Text("Title ${widget.index}"),
          subtitle: Text("Description ${widget.index}"),
        ),
        decoration: widget.isSelected
            ? BoxDecoration(color: Colors.black38, border: Border.all(color: Colors.black))
            : BoxDecoration(),
      ),
    );
  }
}

以及使用 CustomWidget 的小部件:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int currentSelectedIndex;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Selected index is $currentSelectedIndex'),
      ),
      body: ListView.builder(
        itemCount: 3,
        itemBuilder: (context, index) {
          return CustomWidget(
            index: index,
            isSelected: currentSelectedIndex == index,
            onSelect: () {
              setState(() {
                currentSelectedIndex = index;
              });
            },
          );
        },
      ),
    );
  }
}