0

我的目标是实现 Listview 的更新。我对我的代码有疑问。但我必须先说一下我的问题。我使用了 setState(),但我不明白为什么这个函数不起作用,我意识到使用 Stateless 小部件。

我用了这段代码

class _ListItem extends StatelessWidget {
  _ListItem({this.bgName, this.name, this.detail});

  // final int index;
  final String bgName;
  final String name;
  final String detail;
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 180.0,
      margin: const EdgeInsets.symmetric(
        vertical: 1.0,
      ),
      child: new Stack(
        children: <Widget>[
          new Container(
            decoration: new BoxDecoration(
              image: new DecorationImage(
                  image: new AssetImage(bgName),
                  colorFilter: new ColorFilter.mode(
                      Colors.black.withOpacity(0.45), BlendMode.darken),
                  fit: BoxFit.cover,
                  alignment: Alignment.center),
            ),
            child: new SizedBox.expand(
              child: Container(
                alignment: Alignment.center,
                child: new Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    new Text(
                      name,
                      style: new TextStyle(fontSize: 29.0, color: Colors.white),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(top: 12.0),
                      child: new Text(
                        detail,
                        style:
                        new TextStyle(fontSize: 16.0, color: Colors.white),
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

最近,我将类 _ListItem 更改为 Stateful Widget

我用了这段代码

class ListItem extends StatefulWidget {
  @override
  _ListItem createState() => _ListItem();
}
class _ListItem extends State<ListItem>  {
  _ListItem({this.bgName, this.name, this.detail});

  // final int index;
  final String bgName;
  final String name;
  final String detail;
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 180.0,
      margin: const EdgeInsets.symmetric(
        vertical: 1.0,
      ),
      child: new Stack(
        children: <Widget>[
          new Container(
            decoration: new BoxDecoration(
              image: new DecorationImage(
                  image: new AssetImage(bgName),
                  colorFilter: new ColorFilter.mode(
                      Colors.black.withOpacity(0.45), BlendMode.darken),
                  fit: BoxFit.cover,
                  alignment: Alignment.center),
            ),
            child: new SizedBox.expand(
              child: Container(
                alignment: Alignment.center,
                child: new Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    new Text(
                      name,
                      style: new TextStyle(fontSize: 29.0,  color: Colors.white),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(top: 12.0),
                      child: new Text(
                        detail,
                        style:
                        new TextStyle(fontSize: 16.0, color: Colors.white),
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

但在外面它给出了空的列表视图。

此时我使用了这段代码。

body: ListView.builder(
        physics: BouncingScrollPhysics(),
        itemCount: listItems.length,
        itemBuilder: (BuildContext ctxt, int index){
          return GestureDetector(
              child: listItems[index].widget,
              onTap: () {
                  //some code
              }
          );
        },
      )

所有代码

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:ui';
import 'package:samuraigym/my_icons_icons.dart' as custicon;
import 'package:samuraigym/program_training_handler.dart';
class MeasurementsScreen extends StatefulWidget {
  @override
  _MeasurementsScreenState createState() => _MeasurementsScreenState();
}


class _MeasurementsScreenState extends State<MeasurementsScreen> {
  List<_ListItem> listItems;
  String lastSelectedValue;
  var name = ["Рост", "Вес","Грудь","Плечи","Бицепс"];
  var nameItem = ["Рост", "Вес","Грудь","Плечи","Бицепс"];
  var indication = ["Введите ваш рост", "Введите ваш вес"];
  var indicationItem = ["Введите ваш рост", "Введите ваш вес"];
  TextEditingController customcintroller;

  void navigationPageProgrammTrainingHandler() {
    Navigator.of(context).push(MaterialPageRoute(
        builder: (BuildContext context) => ProgrammTrainingHandler()),
    );
  }
  @override
  void initState() {
    super.initState();
    initListItems();
  }

  Future<String> createAlertDialog(BuildContext context, int indexAl) async{
    customcintroller = TextEditingController();
    if(indexAl < 2){
      String returnVal = await showDialog(context: context, builder: (context){
        return AlertDialog(
          title: Text(name[indexAl]),
          content: TextField(
            textDirection: TextDirection.ltr,
            controller: customcintroller,
            style: TextStyle(
                color: Colors.lightGreen[400],
                fontSize: 18.5),
            decoration: InputDecoration(
              contentPadding: EdgeInsets.only(bottom: 4.0),
              labelText: indication[indexAl],
              alignLabelWithHint: false,
            ),
            keyboardType: TextInputType.phone,
            textInputAction: TextInputAction.done,
          ),
          actions: <Widget>[
            FlatButton(
              child: const Text('ОТМЕНА'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
            FlatButton(
              child: const Text('ОК'),
              onPressed: () {
                setState(() {
                  indicationItem[indexAl] = customcintroller.text.toString();
                  Navigator.of(context).pop();
                });

              },
            ),
          ],
        );
      });
    } else if (indexAl > 1){
      navigationPageProgrammTrainingHandler();
    }

  }


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: Color(0xff2b2b2b),
      appBar: AppBar(
        title: Text(
          'Замеры',
          style: new TextStyle(
            color: Colors.white,

          ),),
        leading: IconButton(
          icon:Icon(Icons.arrow_back),
          color: Colors.white ,
          onPressed:() => Navigator.of(context).pop(),
        ),
      ),
      body: ListView.builder(
        physics: BouncingScrollPhysics(),
        itemCount: listItems.length,
        itemBuilder: (BuildContext ctxt, int index){
          return GestureDetector(
              child: listItems[index].widget,
              onTap: () {
                  createAlertDialog(context, index).then((onValue){
                    indicationItem[index] = onValue.toString();
                  });
              }
          );
        },
      ),
    );
  }
  void initListItems() {
    listItems = [
      new _ListItem(
          bgName: 'assets/images/soso_growth.jpg',
          name:   nameItem[0],
          detail: "Нажми, чтобы добавить свой рост"),
      new _ListItem(
          bgName: 'assets/images/soso_weight.jpg',
          name:  nameItem[1],
          detail: "Нажми, чтобы добавить свой вес"),
      new _ListItem(
          bgName: 'assets/images/soso_chest.jpg',
          name: nameItem[2],
          detail: "PRO-версия"),
      new _ListItem(
          bgName: 'assets/images/soso_shoulder.jpg',
          name: nameItem[3],
          detail: "PRO-версия"),
      new _ListItem(
          bgName: 'assets/images/soso_biceps.jpg',
          name: nameItem[4],
          detail: "PRO-версия")

    ];
  }
}
class ListItem extends StatefulWidget {
  @override
  _ListItem createState() => _ListItem();
}
class _ListItem extends State<ListItem>  {
  _ListItem({this.bgName, this.name, this.detail});

  // final int index;
  final String bgName;
  final String name;
  final String detail;
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 180.0,
      margin: const EdgeInsets.symmetric(
        vertical: 1.0,
      ),
      child: new Stack(
        children: <Widget>[
          new Container(
            decoration: new BoxDecoration(
              image: new DecorationImage(
                  image: new AssetImage(bgName),
                  colorFilter: new ColorFilter.mode(
                      Colors.black.withOpacity(0.45), BlendMode.darken),
                  fit: BoxFit.cover,
                  alignment: Alignment.center),
            ),
            child: new SizedBox.expand(
              child: Container(
                alignment: Alignment.center,
                child: new Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    new Text(
                      name,
                      style: new TextStyle(fontSize: 29.0,  color: Colors.white),
                    ),
                    Padding(
                      padding: const EdgeInsets.only(top: 12.0),
                      child: new Text(
                        detail,
                        style:
                        new TextStyle(fontSize: 16.0, color: Colors.white),
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

请帮帮我。有些日子我无法解决问题))

4

2 回答 2

2

如果要在有状态小部件中发送数据,则必须在有状态类本身中执行此操作,而不是在状态中

   class ListItem extends StatefulWidget {
  String bgName;
  String name;
  String detail;

  ListItem({Key key, this.bgName, this.name, this.detail}) : super(key: key);

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

要在状态类中访问它,请这样做:

//somecode
 decoration: new BoxDecoration(
            image: new DecorationImage(
                image: new AssetImage(widget.bgName),
     //some code

要更改有状态小部件中的状态,请在您点击小部件时调用 setState 方法,例如,添加手势检测器或 InkWell 以添加点击功能并在其中调用设置状态。制作 ListItem 列表以在列表视图构建器中使用它,

 List<ListItem> items = [ ListItem(bgName: ' the bgName' ,name :'the 
  name',detail:'details'),
   //add another Items here
    ];

  ListView.builder(
  itemCount:items.length,
  itemBuilder: (context,index)=>items[index];
  );

完整示例

class ListItem extends StatefulWidget {
  String bgName;
  String name;
  String detail;

  ListItem({Key key, this.bgName, this.name, this.detail}) : super(key: key);

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

class _ListItem extends State<ListItem> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        print(widget.bgName);
        //call setState here;
        setState(() {
          widget.bgName = 'this item is tapped';
        });
      },
      child: Container(
        height: 180.0,
        margin: const EdgeInsets.symmetric(
          vertical: 1.0,
        ),
        child: new Stack(
          children: <Widget>[
            new Container(
              decoration: new BoxDecoration(
                image: new DecorationImage(
                    image: new AssetImage(widget.bgName),
                    colorFilter: new ColorFilter.mode(
                        Colors.black.withOpacity(0.45), BlendMode.darken),
                    fit: BoxFit.cover,
                    alignment: Alignment.center),
              ),
              child: new SizedBox.expand(
                child: Container(
                  alignment: Alignment.center,
                  child: new Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      new Text(
                        widget.name,
                        style:
                            new TextStyle(fontSize: 29.0, color: Colors.white),
                      ),
                      Padding(
                        padding: const EdgeInsets.only(top: 12.0),
                        child: new Text(
                          widget.detail,
                          style: new TextStyle(
                              fontSize: 16.0, color: Colors.white),
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}


 List<ListItem> items = [ ListItem(bgName: ' the bgName' ,name :'the 
  name',detail:'details'),
   //add another Items here
    ];


body: ListView.builder(
    physics: BouncingScrollPhysics(),
    itemCount: listItems.length,
    itemBuilder: (BuildContext ctxt, int index){
      return
          listItems[index]
         ;
    },
  )

我希望这能有所帮助。

于 2019-08-04T17:16:33.680 回答
0

为我解决问题的方法是将您的小部件(您的构建器返回的小部件)包装在具有唯一键的容器中。

在我的情况下,我在构建器中返回了一个无状态小部件,所以这里是对我有用的代码。

这是我的 listView Builer 的返回语句

return new Container(child: CouponWidget(coupons[position],true),
                     key:UniqueKey()  
                     );
于 2020-07-28T17:45:49.453 回答