Flutter开发:如何在ListView.separated中每4行插入一条广告
实现方案
直接调整列表的item计数逻辑,将广告作为独立item渲染,不要在separatorBuilder中处理广告,即可同时满足分隔线展示和每4条插广告的需求。
核心调整逻辑
- 总item数计算:总长度 = 文章列表长度 + 广告位数量 + 1(底部加载占位),广告位数量公式为
(articleslist.length / 4).floor(),即每4篇文章插入1条广告 - itemBuilder中做索引映射,判断当前位置需要渲染的内容类型
- separatorBuilder保持默认返回Divider即可,所有item之间都会保留分隔线
修改后代码
ListView.separated( scrollDirection: Axis.vertical, shrinkWrap: true, controller: _scrollController, // 重新计算总item数:文章数 + 广告数 + 1个底部加载位 itemCount: articleslist.length + (articleslist.length / 4).floor() + 1, itemBuilder: (BuildContext context, int index) { // 先处理底部加载位 if (index == articleslist.length + (articleslist.length / 4).floor()) { _loading = true; return Center( child: Row( children: [ Container( padding: EdgeInsets.all(5), child: CircularProgressIndicator( color: Colors.deepOrange[800], ), ), const SizedBox(width: 15), Text( 'Articles are being loaded...', style: TextStyle(color: Colors.deepOrange[800]), ) ], ), ); } // 处理空列表 if (articleslist.isEmpty) { return Container( child: Center( child: Text('Loading...', style: TextStyle(color: Colors.deepOrange)))); } // 计算当前索引对应的内容类型 int itemIndex = index - (index ~/ 5); // 每5个item里有1个广告,减去广告占用的索引位 // 判断是否是广告位:索引+1能被5整除的位置就是广告位 if ((index + 1) % 5 == 0) { // 这里替换为你自己的google_mobile_ads横幅广告实现 return const BannerAdWidget(); } // 剩余位置渲染文章内容 var imgUrl = articleslist[itemIndex].img.toString(); imgUrl = BaseUrl + imgUrl.toString(); var title = articleslist[itemIndex].title; title = title.replaceAll(RegExp(r'<[^>]*>'), ''); var body = articleslist[itemIndex].body; body = body.replaceAll(RegExp(r'<[^>]*>'), ''); return InkWell( onTap: () { print('Tapped : ${articleslist[itemIndex].nid}'); print(itemIndex); Navigator.push( context, MaterialPageRoute( builder: (context) => DetailPage( articleslist[itemIndex].title, articleslist[itemIndex].img, articleslist[itemIndex].nid, articleslist[itemIndex].uid, articleslist[itemIndex].created, ))); }, child: Container( padding: const EdgeInsets.fromLTRB(8.0, 6.0, 8.0, 0.0), child: Row( children: <Widget>[ Container( width: 120, height: 75, child: ClipRRect( borderRadius: BorderRadius.circular(8), child: imgUrl == 'No img' ? Image.asset('images/placeholder.png', height: 220, fit: BoxFit.cover) : FadeInImage.assetNetwork( placeholder: 'images/placeholder.png', image: imgUrl, height: 220, fit: BoxFit.cover, ), ), ), const SizedBox(width: 20), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[ Text( title, style: const TextStyle( color: Colors.black, fontSize: 16), ), const SizedBox(height: 10), Text( // 修正原代码未定义uid的问题 'author : ${articleslist[itemIndex].uid}', style: const TextStyle( fontSize: 10, ), ), const SizedBox(height: 5), Text( articleslist[itemIndex].created, style: const TextStyle( fontSize: 10, ), ) ], ), ), ], ), ), ); }, separatorBuilder: (context, index) => const Divider(), ),
补充说明
你只需要把代码中BannerAdWidget替换为你自己基于google_mobile_ads实现的横幅广告组件即可,原有的分隔线会保留在所有内容(文章、广告、加载位)之间,完全符合需求。
内容的提问来源于stack exchange,提问作者Mahant
相关产品推荐
相关产品推荐

