【问题标题】:Flutter - How to access one element in ListView.builder?Flutter - 如何访问 ListView.builder 中的一个元素?
【发布时间】:2020-05-12 23:51:11
【问题描述】:

我有一个列表视图,其中包含从对象列表(报价)创建的元素。每个报价都有关于其自身的详细信息。我想在点击后更改图标 (_isFavIcon)。但是当我点击它时,它会改变列表的每个元素(每个图标)。 同样在更改图标后,我想将它们添加到另一个列表中。但那是以后的事了。

它的外观如下:ListView

也许我应该使用ListView 而不是ListView.builder

这是我的代码:

class OfferList extends StatefulWidget {
  final List<Offer> offers;

  OfferList(this.offers);

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

class _OfferListState extends State<OfferList> {
  bool isPressed = true;

  Icon _isFavIcon = new Icon(
    Icons.favorite_border,
    color: Colors.red,
  );

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);


    _addToFavorites() {
      _isFavIcon = new Icon(Icons.favorite, color: Colors.red);
    }

    return Container(
      height: 700,
      child: ListView.builder(
        itemBuilder: (ctx, index) {
          return Stack(
            children: <Widget>[
              Container(
                decoration: BoxDecoration(
                    gradient: LinearGradient(
                        begin: Alignment.topRight,
                        end: Alignment.bottomLeft,
                        colors: [
                      Colors.white,
                      Colors.lightBlueAccent.withOpacity(0.2)
                    ])),
                width: mediaQuery.size.width,
                child: Card(
                  child: Row(
                    children: <Widget>[
                      Container(
                        margin: EdgeInsets.symmetric(
                          vertical: 15,
                          horizontal: 15,
                        ),
                        child: Container(
                          decoration: BoxDecoration(
                            boxShadow: [
                              BoxShadow(
                                color: Colors.grey.withOpacity(0.3),
                                spreadRadius: 1.2,
                                blurRadius: 7,
                              ),
                            ],
                          ),
                          child: Image.asset(widget.offers[index].flag),
                        ),
                        padding: EdgeInsets.all(5),
                      ),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Container(
                            width: 150,
                            child: Text(
                              widget.offers[index].title,
                              style: TextStyle(
                                fontSize: 16,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                          Text(
                            'From: ' +
                                DateFormat.yMMMd()
                                    .format(widget.offers[index].dateFrom),
                            style: TextStyle(
                              color: Colors.grey,
                            ),
                          ),
                          Text(
                            'To: ' +
                                DateFormat.yMMMd()
                                    .format(widget.offers[index].dateTo),
                            style: TextStyle(
                              color: Colors.grey,
                            ),
                          ),
                        ],
                      ),
                      Padding(
                        padding: EdgeInsets.all(8.0),
                        child: Row(
                          children: <Widget>[
                            RaisedButton(
                              color: Colors.lightBlueAccent,
                              textColor: Colors.white,
                              shape: RoundedRectangleBorder(
                                borderRadius: new BorderRadius.circular(30.0),
                              ),
                              child: Text('Open'),
                              onPressed: () {},
                            ),
                            Container(
                              padding: EdgeInsets.only(left: 10),
                              child: InkWell(
                                onTap: () {
                                  setState(() {
                                    _addToFavorites();
                                  });
                                },
                                child: _isFavIcon,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          );
        },
        itemCount: widget.offers.length,
      ),
    );
  }
}

【问题讨论】:

  • 将您的 ListItem 拆分为自己的 StatefulWidget

标签: listview flutter mobile dart element


【解决方案1】:

您可以同时满足这两个要求(切换 favIcon 并拥有收藏列表)添加列表并检查该项目何时在该列表中以显示图标。

class OfferList extends StatefulWidget {
  final List<Offer> offers;

  OfferList(this.offers);

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

class _OfferListState extends State<OfferList> {
  bool isPressed = true;
  List<Offer> _favOffers = [];

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);

    void _toggleFavorite(Offer offer) {
      if (_favOffers.contains(offer)) {
        _favOffers.remove(offer);
      } else {
        _favOffers.add(offer);
      }
    }

    return Container(
      height: 700,
      child: ListView.builder(
        itemBuilder: (ctx, index) {
          return Stack(
            children: <Widget>[
              Container(
                decoration: BoxDecoration(
                    gradient: LinearGradient(
                        begin: Alignment.topRight,
                        end: Alignment.bottomLeft,
                        colors: [
                      Colors.white,
                      Colors.lightBlueAccent.withOpacity(0.2)
                    ])),
                width: mediaQuery.size.width,
                child: Card(
                  child: Row(
                    children: <Widget>[
                      Container(
                        margin: EdgeInsets.symmetric(
                          vertical: 15,
                          horizontal: 15,
                        ),
                        child: Container(
                          decoration: BoxDecoration(
                            boxShadow: [
                              BoxShadow(
                                color: Colors.grey.withOpacity(0.3),
                                spreadRadius: 1.2,
                                blurRadius: 7,
                              ),
                            ],
                          ),
                          child: Image.asset(widget.offers[index].flag),
                        ),
                        padding: EdgeInsets.all(5),
                      ),
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Container(
                            width: 150,
                            child: Text(
                              widget.offers[index].title,
                              style: TextStyle(
                                fontSize: 16,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ),
                          Text(
                            'From: ' +
                                DateFormat.yMMMd()
                                    .format(widget.offers[index].dateFrom),
                            style: TextStyle(
                              color: Colors.grey,
                            ),
                          ),
                          Text(
                            'To: ' +
                                DateFormat.yMMMd()
                                    .format(widget.offers[index].dateTo),
                            style: TextStyle(
                              color: Colors.grey,
                            ),
                          ),
                        ],
                      ),
                      Padding(
                        padding: EdgeInsets.all(8.0),
                        child: Row(
                          children: <Widget>[
                            RaisedButton(
                              color: Colors.lightBlueAccent,
                              textColor: Colors.white,
                              shape: RoundedRectangleBorder(
                                borderRadius: new BorderRadius.circular(30.0),
                              ),
                              child: Text('Open'),
                              onPressed: () {},
                            ),
                            Container(
                              padding: EdgeInsets.only(left: 10),
                              child: InkWell(
                                onTap: () {
                                  setState(() {
                                    _toggleFavorite(widget.offers[index]);
                                  });
                                },
                                child:
                                    (_favOffers.contains(widget.offers[index]))
                                        ? Icon(
                                            Icons.favorite,
                                            color: Colors.red,
                                          )
                                        : Icon(
                                            Icons.favorite_border,
                                            color: Colors.black,
                                          ),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          );
        },
        itemCount: widget.offers.length,
      ),
    );
  }
}

【讨论】:

    【解决方案2】:

    实际上,您正在为所有项目覆盖 _isFavIcon

    您需要向您的 Offer 模型添加一个名为 isFavorite 的属性,并在 onTap 方法上切换 isFavorite 属性

    这是您案例的完整工作示例

    报价模式

    class Offer {
    
      // other attributes
      bool isFavorite = false;
    
    }
    

    优惠列表小部件

    class OfferList extends StatefulWidget {
      final List<Offer> offers;
    
      OfferList(this.offers);
    
      @override
      _OfferListState createState() => _OfferListState();
    }
    
    class _OfferListState extends State<OfferList> {
      bool isPressed = true;
    
      Icon _isNotFavIcon = new Icon(
        Icons.favorite_border,
        color: Colors.red,
      );
    
      Icon _isFavIcon = new Icon(
        Icons.favorite,
        color: Colors.red,
      );
    
      List<Offer> _offers;
    
      @override
      void initState() {
        _offers = widget.offers;
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        final mediaQuery = MediaQuery.of(context);
        return Container(
          height: 700,
          child: ListView.builder(
            itemBuilder: (ctx, index) {
              return Stack(
                children: <Widget>[
                  Container(
                    decoration: BoxDecoration(
                        gradient: LinearGradient(
                            begin: Alignment.topRight,
                            end: Alignment.bottomLeft,
                            colors: [
                          Colors.white,
                          Colors.lightBlueAccent.withOpacity(0.2)
                        ])),
                    width: mediaQuery.size.width,
                    child: Card(
                      child: Row(
                        children: <Widget>[
                          Container(
                            margin: EdgeInsets.symmetric(
                              vertical: 15,
                              horizontal: 15,
                            ),
                            child: Container(
                              decoration: BoxDecoration(
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.grey.withOpacity(0.3),
                                    spreadRadius: 1.2,
                                    blurRadius: 7,
                                  ),
                                ],
                              ),
                              child: Image.asset(_offers[index].flag),
                            ),
                            padding: EdgeInsets.all(5),
                          ),
                          Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              Container(
                                width: 150,
                                child: Text(
                                  _offers[index].title,
                                  style: TextStyle(
                                    fontSize: 16,
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                              ),
                              Text(
                                'From: ' +
                                    DateFormat.yMMMd()
                                        .format(_offers[index].dateFrom),
                                style: TextStyle(
                                  color: Colors.grey,
                                ),
                              ),
                              Text(
                                'To: ' +
                                    DateFormat.yMMMd()
                                        .format(_offers[index].dateTo),
                                style: TextStyle(
                                  color: Colors.grey,
                                ),
                              ),
                            ],
                          ),
                          Padding(
                            padding: EdgeInsets.all(8.0),
                            child: Row(
                              children: <Widget>[
                                RaisedButton(
                                  color: Colors.lightBlueAccent,
                                  textColor: Colors.white,
                                  shape: RoundedRectangleBorder(
                                    borderRadius: new BorderRadius.circular(30.0),
                                  ),
                                  child: Text('Open'),
                                  onPressed: () {},
                                ),
                                Container(
                                  padding: EdgeInsets.only(left: 10),
                                  child: InkWell(
                                    onTap: () {
                                      setState(() {
                                        _offers[index].isFavorite =
                                            !_offers[index].isFavorite;
                                      });
                                    },
                                    child: _offers[index].isFavorite
                                        ? _isFavIcon
                                        : _isNotFavIcon,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
              );
            },
            itemCount: _offers.length,
          ),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-07
      • 2021-03-07
      • 2019-04-27
      • 2020-08-13
      • 2021-12-20
      • 2020-10-25
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      相关资源
      最近更新 更多