如何从无状态小部件更改为有状态小部件? [英] How to change from Stateless Widget to Stateful Widget?

查看:62
本文介绍了如何从无状态小部件更改为有状态小部件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用复选框和下拉菜单的应用程序屏幕。但是,我已经意识到我已经在StatelessWidget中对其进行了编码,因此当选择一个选项时,我无法更改状态。如何使它正常工作,以便在选中一个复选框时它会显示为已选中而不是空?



我尝试将代码粘贴到有状态的小部件,但是会一直出错,因为我不确定哪部分应该放在哪里。

  import‘package:carve_brace_app / model / activity.dart’; 
导入的 package:flutter / material.dart;

类DetailPage扩展了StatelessWidget {
final Activity活动;
DetailPage({Key key,this.activity}):super(key:key);

@override
小部件构建(BuildContext上下文){
final levelIndicator = Container(
child:Container(
child:LinearProgressIndicator(
backgroundColor:Color.fromRGBO(209,224,224,0.2),
值:2.0,
值Color:AlwaysStoppedAnimation(Colors.green)),
),
);

final topContentText = Column(
crossAxisAlignment:CrossAxisAlignment.start,
子级:< Widget> [
SizedBox(高度:120.0),
容器(
宽度:90.0,
子级:new Divider(color:Colors.green),
),
SizedBox(高度:10.0),
Text(
activity.activityName,
样式:TextStyle(颜色:Colors.white,fontSize:45.0),
),
SizedBox(高度:30.0),
Row($ b) $ b mainAxisAlignment:MainAxisAlignment.start,
子级:< Widget> [
Expanded(
flex:6,
子级:Padding(
padding:EdgeInsets.only (左:10.0),
子级:文本(
上次运行:3-2-19\n +
上次平均应变:34%\n +
上次运行时间:00:45:23,
样式:TextStyle(颜色:Colors.white),
))),
//展开后(flex:1,孩子:newRow)
],
),
],
);

final topContent = Stack(
子级:< Widget> [
容器(
高度:MediaQuery.of(context).size.height * 0.45,
填充:EdgeInsets.all(40.0),
宽度:MediaQuery.of(context).size.width,
装饰:BoxDecoration(
渐变:LinearGradient(
开始:Alignment.centerLeft,
结束:Alignment.centerRight,
颜色:[
Color.fromRGBO(33,147,176,100),
Color.fromRGBO(109,213 ,237,100)
],
),
),
子级:Center(
子级:topContentText,
),
) ,
位置(
左:235.0,
上:180.0,
子级:InkWell(
onTap:(){
Navigator.pop(context) ;
},
chil d:new CircleAvatar(
半径:80.0,
backgroundImage:NetworkImage(activity.icon),
backgroundColor:Colors.white,
),
),
),
位置(
剩余:8.0,
顶部:60.0,
子级:InkWell(
onTap:(){
Navigator.pop (上下文);
},
子级:Icon(Icons.arrow_back,颜色:Colors.white),
),

],
);

final bottomContentText = Text(
Config:,
样式:TextStyle(fontSize:18.0),
);
final mappingCheckBox = CheckboxListTile(
标题:Text( Mapped),
值:false,
onChanged:(newValue){},
controlAffinity:ListTileControlAffinity。领先,//<-领先的复选框
);
final rtCheckBox = CheckboxListTile(
title:Text( Real-time Tracking),
value:false,
onChanged:(newValue){},
controlAffinity :ListTileControlAffinity.leading,//<-前导复选框
);
final descriptionText = Text(
Description:,
样式:TextStyle(fontSize:12.0),
);
最终描述= TextFormField(
装饰:InputDecoration(
hintText:‘输入活动描述’,
),
);
final scheduleFor = Text(
Scheduled for:,
样式:TextStyle(fontSize:12.0),
);
最终下拉列表=新的DropdownButton< String>(
项目:< String> ['Now(Default)','B','C','D']。map((String value) {
return new DropdownMenuItem< String>(
value:value,
child:new Text(value),
);
})。toList(),
提示:Text( Now(Default)),
onChanged:(_){},
);
final readButton = Container(
填充:EdgeInsets.symmetric(垂直:16.0),
宽度:170,// MediaQuery.of(context).size.width,
子级:RaisedButton(
onPressed:()=> {},
颜色:Colors.lightBlue,
子级:
Text( Start,样式:TextStyle(color:Colors .white,fontSize:20)),
));
final bottomContent =容器(
宽度:MediaQuery.of(context).size.width,
填充:EdgeInsets.all(40.0),
子级:Center(
子级:列(
子级:< Widget> [bottomContentText,mappedCheckbox,rtCheckBox,descriptionText,description,Text( \n),cheduleFor,下拉菜单,readButton],
),
),
);

return脚手架(
正文:列(
子代:< Widget> [topContent,bottomContent],
),
);
}
}


解决方案

点击在 StatelessWidget 类上,并​​使用 option +输入(或 cmd +。(如果在macOS上使用VS Code),则会看到一个IDE选项可以帮助您完成此操作。





这是工作代码。

 类DetailPage扩展了StatefulWidget {
final Activity活动;

DetailPage({Key key,this.activity}):super(key:key);

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

类_DetailPageState扩展了State< DetailPage> {
bool _tracking = false,_mapped = false; //您需要这个
String _schedule;

@override
小部件build(BuildContext context){
final levelIndicator = Container(
child:Container(
child:LinearProgressIndicator(backgroundColor:Color。 fromRGBO(209,224,224,0.2),值:2.0,valueColor:AlwaysStoppedAnimation(Colors.green)),
),
);

final topContentText = Column(
crossAxisAlignment:CrossAxisAlignment.start,
子级:< Widget> [
SizedBox(高度:120.0),
容器(
宽度:90.0,
子级:Divider(color:Colors.green),
),
SizedBox(高度:10.0),
Text(
widget.activity.activityName,
样式:TextStyle(颜色:Colors.white,fontSize:45.0),
),
SizedBox(高度:30.0),
Row(
mainAxisAlignment:MainAxisAlignment.start,
子级:< Widget> [
Expanded(
flex:6,
子级:Padding(
padding:EdgeInsets)。仅(左:10.0),
子级:文本(
上次运行:3-2-19\n +上次平均应变:34%\n +上次运行时间: 00:45:23,
样式:TextStyle(颜色:Colors.w hite),
))))
//展开后(flex:1,child:newRow)
],
),
],
) ;

final topContent = Stack(
子级:< Widget> [
容器(
高度:MediaQuery.of(context).size.height * 0.45,
填充:EdgeInsets.all(40.0),
宽度:MediaQuery.of(context).size.width,
装饰:BoxDecoration(
渐变:LinearGradient(
开始:Alignment.centerLeft,
结束:Alignment.centerRight,
颜色:[Color.fromRGBO(33,147,176,100),Color.fromRGBO(109,213,237,100)],
),
),
子级:Center(
子级:topContentText,
),
),
位置(剩余
:235.0,
顶部:180.0,
子级:InkWell(
onTap:(){
Navigator.pop(context);
},
子级:CircleAvatar(
半径:80.0,
backgroundColo r:Colors.white,
),
),
),
定位(
左:8.0,
上:60.0,
孩子:InkWell(
onTap:(){
Navigator.pop(context);
},
子级:Icon(Icons.arrow_back,颜色:Colors.white),
),

],
);

final bottomContentText = Text(
Config:,
样式:TextStyle(fontSize:18.0),
);
finalappedCheckCheckBox = CheckboxListTile(
title:Text( Mapped),
value:_mapped,
onChanged:(newValue)=> setState(()=> _mapped = newValue),
controlAffinity:ListTileControlAffinity.leading,//<-前导复选框
);
最终rtCheckBox = CheckboxListTile(
标题:Text(实时跟踪),
值:_tracking,
onChanged:(newValue)=> setState(()= > _tracking = newValue),
controlAffinity:ListTileControlAffinity.leading,//<-前导复选框
);
final descriptionText = Text(
Description:,
样式:TextStyle(fontSize:12.0),
);
最终描述= TextFormField(
装饰:InputDecoration(
hintText:‘输入活动描述’,
),
);
final scheduleFor = Text(
Scheduled for:,
样式:TextStyle(fontSize:12.0),
);
最终下拉列表= DropdownButton< String>(
值:_schedule,
项:< String> ['Now(默认)','B','C','D'] .map((String value){
return DropdownMenuItem< String>(
value:value,
child:Text(value),
);
})。 toList(),
提示:Text( Now(Default)),
onChanged:(newValue){
setState((){
_schedule = newValue;
});
},
);
final readButton = Container(
padding:EdgeInsets.symmetric(vertical:16.0),
width:170,//MediaQuery.of(context).size.width,
子级:RaisedButton(
onPressed:()=> {},
颜色:Colors.lightBlue,
子级:Text(开始,样式:TextStyle(颜色:Colors.white,fontSize :20)),
));
final bottomContent =容器(
宽度:MediaQuery.of(context).size.width,
填充:EdgeInsets.all(40.0),
子级:Center(
子级:列(
子级:< Widget> [bottomContentText,mappedCheckbox,rtCheckBox,descriptionText,description,Text( \n),cheduledFor,下拉菜单,readButton],
),
),
);

return脚手架(
正文:列(
子代:< Widget> [topContent,bottomContent],
),
);
}
}


I have an app screen that uses Checkboxes and a Drop down Menu. However, I have realised I'd coded it inside a StatelessWidget so I am unable to change the state when an option is selected. How do I get this working so that when a Checkbox is selected then it will display as being "checked" rather than empty?

I have tried pasting in my code into a Stateful Widget, however keep running into errors, as I am not totally sure on which parts should go where.

import 'package:carve_brace_app/model/activity.dart';
import 'package:flutter/material.dart';

class DetailPage extends StatelessWidget {
  final Activity activity;
  DetailPage({Key key, this.activity}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final levelIndicator = Container(
      child: Container(
        child: LinearProgressIndicator(
            backgroundColor: Color.fromRGBO(209, 224, 224, 0.2),
            value: 2.0,
            valueColor: AlwaysStoppedAnimation(Colors.green)),
      ),
    );

    final topContentText = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        SizedBox(height: 120.0),
        Container(
          width: 90.0,
          child: new Divider(color: Colors.green),
        ),
        SizedBox(height: 10.0),
        Text(
          activity.activityName,
          style: TextStyle(color: Colors.white, fontSize: 45.0),
        ),
        SizedBox(height: 30.0),
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Expanded(
                flex: 6,
                child: Padding(
                    padding: EdgeInsets.only(left: 10.0),
                    child: Text(
                      "Last Run: 3-2-19\n"+
                      "Last Avg Strain: 34%\n"+
                      "Last Run Time: 00:45:23",
                      style: TextStyle(color: Colors.white),
                    ))),
            // Expanded(flex: 1, child: newRow)
          ],
        ),
      ],
    );

    final topContent = Stack(
      children: <Widget>[
        Container(
          height: MediaQuery.of(context).size.height * 0.45,
          padding: EdgeInsets.all(40.0),
          width: MediaQuery.of(context).size.width,
            decoration: BoxDecoration(
              gradient: LinearGradient(
                begin: Alignment.centerLeft,
                end: Alignment.centerRight,
                colors: [
                  Color.fromRGBO(33, 147, 176, 100),
                  Color.fromRGBO(109, 213, 237, 100)
                ],
              ),
            ),
          child: Center(
            child: topContentText,
          ),
        ),
        Positioned(
          left: 235.0,
          top: 180.0,
          child: InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: new CircleAvatar(
                radius: 80.0,
                backgroundImage: NetworkImage(activity.icon),
                backgroundColor: Colors.white,
              ),
          ),
        ),
        Positioned(
          left: 8.0,
          top: 60.0,
          child: InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: Icon(Icons.arrow_back, color: Colors.white),
          ),
        )
      ],
    );

    final bottomContentText = Text(
      "Config:",
      style: TextStyle(fontSize: 18.0),
    );
    final mappedCheckbox = CheckboxListTile(
     title: Text("Mapped"),
    value: false,
    onChanged: (newValue) { },
    controlAffinity: ListTileControlAffinity.leading,  //  <-- leading Checkbox
    );
    final rtCheckBox = CheckboxListTile(
     title: Text("Real-time Tracking"),
    value: false,
    onChanged: (newValue) { },
    controlAffinity: ListTileControlAffinity.leading,  //  <-- leading Checkbox
    );
    final descriptionText = Text(
      "Description:",
      style: TextStyle(fontSize: 12.0),
    );
    final description = TextFormField(
      decoration: InputDecoration(
      hintText: 'Enter an activity description',
    ),
  );
    final scheduledFor = Text(
      "Scheduled for:",
      style: TextStyle(fontSize: 12.0),
    );
    final dropdown = new DropdownButton<String>(
  items: <String>['Now (Default)', 'B', 'C', 'D'].map((String value) {
    return new DropdownMenuItem<String>(
      value: value,
      child: new Text(value),
    );
  }).toList(),
  hint: Text("Now (Default)"),
  onChanged: (_) {},
);
    final readButton = Container(
        padding: EdgeInsets.symmetric(vertical: 16.0),
        width: 170,//MediaQuery.of(context).size.width,
        child: RaisedButton(
          onPressed: () => {},
          color: Colors.lightBlue,
          child:
              Text("Start", style: TextStyle(color: Colors.white, fontSize: 20)),
        ));
    final bottomContent = Container(
      width: MediaQuery.of(context).size.width,
      padding: EdgeInsets.all(40.0),
      child: Center(
        child: Column(
          children: <Widget>[bottomContentText, mappedCheckbox, rtCheckBox, descriptionText, description, Text("\n"), scheduledFor, dropdown, readButton],
        ),
      ),
    );

    return Scaffold(
      body: Column(
        children: <Widget>[topContent, bottomContent],
      ),
    );
  }
}

解决方案

Click on the StatelessWidget class and use option + enter (or cmd + . if you use VS Code on macOS), you will see an IDE option that will help you do that.


Output (Your solution):

Here is the working code.

class DetailPage extends StatefulWidget {
  final Activity activity;

  DetailPage({Key key, this.activity}) : super(key: key);

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

class _DetailPageState extends State<DetailPage> {
  bool _tracking = false, _mapped = false; // you need this
  String _schedule;

  @override
  Widget build(BuildContext context) {
    final levelIndicator = Container(
      child: Container(
        child: LinearProgressIndicator(backgroundColor: Color.fromRGBO(209, 224, 224, 0.2), value: 2.0, valueColor: AlwaysStoppedAnimation(Colors.green)),
      ),
    );

    final topContentText = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        SizedBox(height: 120.0),
        Container(
          width: 90.0,
          child: Divider(color: Colors.green),
        ),
        SizedBox(height: 10.0),
        Text(
          widget.activity.activityName,
          style: TextStyle(color: Colors.white, fontSize: 45.0),
        ),
        SizedBox(height: 30.0),
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Expanded(
                flex: 6,
                child: Padding(
                    padding: EdgeInsets.only(left: 10.0),
                    child: Text(
                      "Last Run: 3-2-19\n" + "Last Avg Strain: 34%\n" + "Last Run Time: 00:45:23",
                      style: TextStyle(color: Colors.white),
                    ))),
            // Expanded(flex: 1, child: newRow)
          ],
        ),
      ],
    );

    final topContent = Stack(
      children: <Widget>[
        Container(
          height: MediaQuery.of(context).size.height * 0.45,
          padding: EdgeInsets.all(40.0),
          width: MediaQuery.of(context).size.width,
          decoration: BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.centerLeft,
              end: Alignment.centerRight,
              colors: [Color.fromRGBO(33, 147, 176, 100), Color.fromRGBO(109, 213, 237, 100)],
            ),
          ),
          child: Center(
            child: topContentText,
          ),
        ),
        Positioned(
          left: 235.0,
          top: 180.0,
          child: InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: CircleAvatar(
              radius: 80.0,
              backgroundColor: Colors.white,
            ),
          ),
        ),
        Positioned(
          left: 8.0,
          top: 60.0,
          child: InkWell(
            onTap: () {
              Navigator.pop(context);
            },
            child: Icon(Icons.arrow_back, color: Colors.white),
          ),
        )
      ],
    );

    final bottomContentText = Text(
      "Config:",
      style: TextStyle(fontSize: 18.0),
    );
    final mappedCheckbox = CheckboxListTile(
      title: Text("Mapped"),
      value: _mapped,
      onChanged: (newValue) => setState(() => _mapped = newValue),
      controlAffinity: ListTileControlAffinity.leading, //  <-- leading Checkbox
    );
    final rtCheckBox = CheckboxListTile(
      title: Text("Real-time Tracking"),
      value: _tracking,
      onChanged: (newValue) => setState(() => _tracking = newValue),
      controlAffinity: ListTileControlAffinity.leading, //  <-- leading Checkbox
    );
    final descriptionText = Text(
      "Description:",
      style: TextStyle(fontSize: 12.0),
    );
    final description = TextFormField(
      decoration: InputDecoration(
        hintText: 'Enter an activity description',
      ),
    );
    final scheduledFor = Text(
      "Scheduled for:",
      style: TextStyle(fontSize: 12.0),
    );
    final dropdown = DropdownButton<String>(
      value: _schedule,
      items: <String>['Now (Default)', 'B', 'C', 'D'].map((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
      hint: Text("Now (Default)"),
      onChanged: (newValue) {
        setState(() {
          _schedule = newValue;
        });
      },
    );
    final readButton = Container(
        padding: EdgeInsets.symmetric(vertical: 16.0),
        width: 170, //MediaQuery.of(context).size.width,
        child: RaisedButton(
          onPressed: () => {},
          color: Colors.lightBlue,
          child: Text("Start", style: TextStyle(color: Colors.white, fontSize: 20)),
        ));
    final bottomContent = Container(
      width: MediaQuery.of(context).size.width,
      padding: EdgeInsets.all(40.0),
      child: Center(
        child: Column(
          children: <Widget>[bottomContentText, mappedCheckbox, rtCheckBox, descriptionText, description, Text("\n"), scheduledFor, dropdown, readButton],
        ),
      ),
    );

    return Scaffold(
      body: Column(
        children: <Widget>[topContent, bottomContent],
      ),
    );
  }
}

这篇关于如何从无状态小部件更改为有状态小部件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆