单选按钮不会更改 Flutter 中的选择

Posted

技术标签:

【中文标题】单选按钮不会更改 Flutter 中的选择【英文标题】:Radio button not changing the selection in Flutter 【发布时间】:2021-01-02 20:12:32 【问题描述】:

我正在创建动态单选按钮并设法显示它。但是,当我点击它时,它不会改变选择。我可以看到 onchanged 事件被触发,我得到了输出,但我认为 SetState 没有按预期工作。

这里是代码。

class FruitsList 
  String name;
  int index;
  FruitsList(this.name, this.index);


int  _selectedRadioIndex = 1;

// Default Radio Button Item
  String radioItem = 'Mango';
 
  // Group Value for Radio Button.
  int id = 1;
 
  List<FruitsList> fList = [
    FruitsList(
      index: 1,
      name: "Mango",
    ),
    FruitsList(
      index: 2,
      name: "Apple",
    ),
    FruitsList(
      index: 3,
      name: "Banana",
    ),
    FruitsList(
      index: 4,
      name: "Cheery",
    ),
  ];
Column(
              children: 
                fList.map((data) => RadioListTile(
                  title: Text("$data.name"),
                  groupValue: id,
                  value: data.index,
                  onChanged: (val) 
                    setState(() 
                      radioItem = data.name ;
                      id = data.index;
                      print(id);
                      print(radioItem);
                      print(val);
                      _selectedRadioIndex = val;
                    );
                  , 
                )).toList(),
            ),

我做错了什么?

更新

正如春湖君所建议的那样。

我试过下面的代码。

showDialog(
  context: context,
  builder: (context) 
      return StatefulBuilder(
      builder: (context, setState) 
  Column(
              children:            
                fList.map((data) => RadioListTile(
                  title: Text("$data.name"),
                  groupValue: id,//_selected,//id,
                  value: data.index,
                  onChanged: (val) 
                    setState(() 
                      radioItem = data.name ;
                      id = data.index;
                      print(id);
                      print(radioItem);
                      print(val);
                      _selectedRadioIndex = val;
                    );
                  , 
                )).toList(),
            );
  
  );
  ,
  );

但它在这些地方给出错误。

showDialog(
  context: context,
  builder: (context) 

'showDialog' must have a method body because '_ApointmentPriceState' isn't abstract.
Try making '_ApointmentPriceState' abstract, or adding a body to 'showDialog'.

【问题讨论】:

您的代码运行良好。如果您在 AlertDialog 中执行此操作。你可以使用StatefulBuilder,看这个***.com/questions/51962272/… 感谢您的评论。所以,我到底需要把这个放在哪里。 return AlertDialog( content: StatefulBuilder( // 你需要这个,注意下面的参数:builder: (BuildContext context, StateSetter setState) 对不起。您的原始代码是否使用 AlertDialog?你能发布你的复制原始代码吗?在我的测试下。它工作正常。所以我猜你在 AlertDialog 中显示数据。如果您的原始代码不使用 AlertDialog,我将需要重现代码。 您可以从这里找到完整的代码。 ***.com/questions/63895921/… 【参考方案1】:

您将组值设置为 id 但在 setState 中您正在更改 _selectedRadioIndex,请像这样更改您的代码:


RadioListTile(
                  title: Text("$data.name"),
                  groupValue: _selectedRadioIndex,//_selected,//id,
                  value: data.index,
                  onChanged: (val) 
                    setState(() 
                      radioItem = data.name ;
                      id = data.index;
                      print(id);
                      print(radioItem);
                      print(val);
                      _selectedRadioIndex = val;
                    );

【讨论】:

感谢您的回答。我也尝试使用 groupValue: id 和 _selectedRadioIndex。两种方式都行不通。 这应该可以,错误一定在其他地方,您需要发布更多代码。 可以从这个问题***.com/questions/63895921/…看到完整的代码【参考方案2】:
    import 'package:flutter/material.dart';

    void main() 
      runApp(MyApp());
    

    class MyApp extends StatelessWidget 
      @override
      Widget build(BuildContext context) 
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      
    

    class MyHomePage extends StatefulWidget 
      MyHomePage(Key key, this.title) : super(key: key);
      
    final String title;

  

    @override
      _MyHomePageState createState() => _MyHomePageState();
    

class _MyHomePageState extends State<MyHomePage> 

  var _selectedRadioIndex = 1;

  @override
  Widget build(BuildContext context) 

String radioItem = 'Mango';
int id = 1;

List<FruitsList> fList = [
  FruitsList(
    index: 1,
    name: "Mango",
  ),
  FruitsList(
    index: 2,
    name: "Apple",
  ),
  FruitsList(
    index: 3,
    name: "Banana",
  ),
  FruitsList(
    index: 4,
    name: "Cheery",
  ),
];
return Scaffold(
  appBar: AppBar(
    title: Text(widget.title),
  ),
  body: Center(
    child: Column(
      children:
      fList.map((data) => RadioListTile(
        title: Text("$data.name"),
        groupValue: _selectedRadioIndex,
        value: data.index,
        onChanged: (val) 
          setState(() 
            _selectedRadioIndex = val;
            radioItem = data.name ;
            id = data.index;
            print(id);
            print(radioItem);
            print(val);

          );
        ,
      )).toList(),

    ),
    ),
  
);
  


class FruitsList 
  String name;
  int index;
  FruitsList(this.name, this.index);

【讨论】:

让我试试你的解决方案。 我收到了这个错误。没有为类型定义 getter '_selectedRadioIndex'【参考方案3】:

您可以在下面复制粘贴运行完整代码 您可以用StatefulBuilder 包裹Row 并使用List&lt;int&gt; _selectedRadioIndexListCardNo 来控制 代码sn-p

List<int> _selectedRadioIndexList = [];
int CardNo = -1;
...
_selectedRadioIndexList.add(0);
CardNo = CardNo + 1;
int thisCardNo = CardNo;
... 
_selectedRadioIndexList[thisCardNo] = val;  


StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) 
            return Row(
              children: fList
                  .map((data) => Container(
                    width: 100,
                    child: RadioListTile(
                          title: Text("$data.name"),
                          groupValue: id,
                          value: data.index,
                          onChanged: (val) 
                            setState(() 
                              radioItem = data.name;
                              id = data.index;
                              print(id);
                              print(radioItem);
                              print(val);
                              _selectedRadioIndex = val;
                            );
                          ,
                        ),
                  ))
                  .toList(),
            );
          )

工作演示

完整代码

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class FruitsList 
  String name;
  int index;
  FruitsList(this.name, this.index);


class Price extends StatefulWidget 
  @override
  _PriceState createState() => _PriceState();


class _PriceState extends State<Price> 
  static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final _scaffoldKey = GlobalKey<ScaffoldState>();
  int currentIndex = 0;
  String person;
  String age;
  String job;

  // Default Radio Button Item
  String radioItem = 'Mango';

  // Group Value for Radio Button.
  int id = 1;
  //int _selectedRadioIndex = 1;
  List<int> _selectedRadioIndexList = [];

  List<FruitsList> fList = [
    FruitsList(
      index: 1,
      name: "Mango",
    ),
    FruitsList(
      index: 2,
      name: "Banana",
    ),
    FruitsList(
      index: 3,
      name: "Apple",
    ),
    FruitsList(
      index: 4,
      name: "Cherry",
    ),
  ];
  int CardNo = -1;
  @override
  void initState() 
    super.initState();
    cards.add(createCard());
  

  var nameTECs = <TextEditingController>[];
  var ageTECs = <TextEditingController>[];
  var jobTECs = <TextEditingController>[];

  var cards = <Card>[];

  Card createCard() 
    var nameController = TextEditingController();
    var ageController = TextEditingController();
    var jobController = TextEditingController();
    nameTECs.add(nameController);
    ageTECs.add(ageController);
    jobTECs.add(jobController);
    _selectedRadioIndexList.add(0);
    CardNo = CardNo + 1;
    int thisCardNo = CardNo;

    return Card(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Text('Service $cards.length + 1'),
          TextFormField(
            style: TextStyle(color: Colors.blue),
            controller: nameController,
            decoration: InputDecoration(labelText: 'Name'),
            validator: validatetext,
            onSaved: (String val) 
              person = val;
            ,
          ),

          TextFormField(
            style: TextStyle(color: Colors.blue),
            controller: ageController,
            decoration: InputDecoration(labelText: 'age'),
            validator: validatetext,
            onSaved: (String val) 
              age = val;
            ,
          ),
          TextFormField(
            style: TextStyle(color: Colors.blue),
            controller: jobController,
            decoration: InputDecoration(labelText: 'Job'),
            validator: validatetext,
            onSaved: (String val) 
              job = val;
            ,
          ),

          //Expanded(
          //            child: Container(
          //            height: 350.0,
          //            child:
          StatefulBuilder(
              builder: (BuildContext context, StateSetter setState) 
            return Row(
              children: fList
                  .map((data) => Container(
                        width: 100,
                        child: RadioListTile(
                          title: Text("$data.name"),
                          groupValue: id,
                          value: data.index,
                          onChanged: (val) 
                            setState(() 
                              radioItem = data.name;
                              id = data.index;
                              print(id);
                              print(radioItem);
                              print(val);
                              _selectedRadioIndexList[thisCardNo] = val;
                            );
                          ,
                        ),
                      ))
                  .toList(),
            );
          ),
          //)),

          /* CheckboxListTile(
        title: Text("title text"),
        value: checkedValue,
        onChanged: (newValue) 
                     setState(() 
                       checkedValue = newValue;
                     );
                   ,
        //onChanged: (newValue)  ... ,
        controlAffinity: ListTileControlAffinity.leading,  //  <-- leading Checkbox
      ), */

          SizedBox(height: 10),
        ],
      ),

      //   ),
    );
  

  void _validateInputs() 
    print('button');
    if (_formKey.currentState.validate()) 
      _formKey.currentState.save();
      _onDone();
     else 
  

  _onDone() 
    updateProfile();
    List<PersonEntry> entries = [];
    for (int i = 0; i < cards.length; i++) 
      var name = nameTECs[i].text;
      var age = ageTECs[i].text;
      var job = jobTECs[i].text;
      entries.add(PersonEntry(name, age, job));
    
  

  ///////// Save to DB ////////////////////
  Future updateProfile() async 
    try 
      for (int i = 0; i < cards.length; i++) 
        var name = nameTECs[i].text;
        var age = ageTECs[i].text;
        var job = jobTECs[i].text;

        Map<String, dynamic> body = 'name': name, 'age': age, 'job': job;

        print(body);
        nameTECs[i].clear();
        //if(rang == true)

        Response response = await Dio()
            .post("http://192.168.1.102:8080/adddetails.php", data: body);
        print(response.statusCode);
        if (response.statusCode == 404) 
          print('404');
        
        if (response.statusCode == 200) 
          nameTECs[i].clear();
        
      
     catch (e) 
      print("Exception Caught: $e");
    
  

  ///////////////////////////////

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      key: _scaffoldKey,
      //appBar: myAppBar(),
      //endDrawer: myDrawer(),
      body: Column(
        children: <Widget>[
          Expanded(
            child: new Form(
              key: _formKey,
              child: ListView.builder(
                itemCount: cards.length,
                itemBuilder: (BuildContext context, int index) 
                  return cards[index];
                ,
              ),
            ),
          ),
          Container(
            padding: EdgeInsets.symmetric(horizontal: 2.0),
            color: Colors.grey,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                //    Container(
                Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: FloatingActionButton(
                      heroTag: "btn1",
                      child: Icon(Icons.add),
                      onPressed: () => setState(() => cards.add(createCard())),
                      backgroundColor: Colors.green,
                    )

                    /*RaisedButton(
                  child: Text('Add new'),
                  onPressed: () => setState(() => cards.add(createCard())),
                ),*/
                    ),
                Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: FloatingActionButton(
                      heroTag: "btn2",
                      child: Icon(Icons.remove),
                      onPressed: () => setState(() => cards.removeLast()),
                      backgroundColor: Colors.red,
                    )),
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: FloatingActionButton(
                      heroTag: "btn3",
                      child: Icon(Icons.save),
                      onPressed: _validateInputs),
                )
              ],
            ),
          ),
        ],
      ),
    );
  


class PersonEntry 
  final String name;
  final String age;
  final String studyJob;

  PersonEntry(this.name, this.age, this.studyJob);
  @override
  String toString() 
    return 'Person: name= $name, age= $age, study job= $studyJob';
  


Size get preferredSize => Size.fromHeight(kToolbarHeight);

String validatetext(String value) 
  if (value.length < 5)
    return 'More than 5 char is required';
  else
    return null;


void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Price(),
    );
  

【讨论】:

感谢您的回答。投票赞成。我会仔细阅读并理解为什么它不起作用。我希望当我单击加号按钮时它会起作用,并且不会与卡中现有的收音机冲突。 你可以参考这个medium.com/@Nash0x7E2/…和这个medium.com/flutterdevs/… 感谢您的帮助。我会处理它并尝试检查 http 部分。如果我在 http 请求期间遇到任何问题,我会通知您。 我需要更多帮助。你能告诉我如何在 http 请求中获取单选按钮的选定值。当前代码给出错误。 _selectedradio: final FruitsList = fList.firstWhere((element) => element.index == _selectedRadioIndex);

以上是关于单选按钮不会更改 Flutter 中的选择的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中只选择一组单选按钮的值?

基于角度 js 中的单选按钮选择的表单动作更改

如何在 ReactJS 中更改单选按钮时重置选定的下拉列表

基于单选按钮选择的动态 div 边框

单选按钮更改事件在 chrome 或 safari 中不起作用

如何从 Javascript 更改 HTML 单选按钮选择?