4

我想允许用户从列表中只选择一个选项,如果他一个接一个地选择,那么只有最后一个选项应该被认为是选中的。

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

试过的代码:

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

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

4

1 回答 1

7

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

鉴于此,您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;
              });
            },
          );
        },
      ),
    );
  }
}
于 2019-05-13T15:17:27.453 回答