【发布时间】:2020-08-18 14:24:33
【问题描述】:
我正在尝试为我的应用构建评论部分。在那方面,我试图拥有一个阅读更多功能,显然顾名思义,它会在点击小部件时扩展小部件以显示更多文本。 我正在使用带有 BottomNavigationBar 的索引堆栈在评论和产品页面之间切换。
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'Product_Page_Widgets.dart';
void main() => runApp(Product());
class Product extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ProductState(),
);
}
}
class ProductState extends StatefulWidget {
Map<dynamic,dynamic> productData;
CollectionReference reviews;
ProductState({@required this.productData,@required this.reviews});
@override
_ProductStateState createState() => _ProductStateState();
}
class _ProductStateState extends State<ProductState> with TickerProviderStateMixin{
List<NetworkImage> _Images = [];
List<Widget> productImages = [];
List<Widget> reviewWidgets = [];
String changeableText = "";
List<String> firstHalf = [];
List<String> secondHalf = [];
var cardHeight = [];
bool load = false;
int pageIndex = 0;
List<Widget> pageWidget = [];
addPageWidgets() async{
pageWidget.add( ProductPageWidget(
productName: widget.productData['Name'],
galleryItems: _Images,cachedImages: productImages,description:widget.productData['description'] ?? "placeholder")
);
Widget w = await buildReviewsWidgets();
pageWidget.add(w);
}
GlobalKey key = new GlobalKey();
Future <Widget> buildReviewsWidgets() async{
var docs = await widget.reviews.getDocuments();
var documents = docs.documents;
print(documents.toString());
if(docs != null) {
for (int i = 0; i < documents.length; i++) {
cardHeight.add(MediaQuery.of(context).size.height/4);
print(documents[i].data['Review']);
if(documents[i].data['Review'].toString().length>50){
firstHalf.add( documents[i].data['Review'].toString().substring(0,50));
secondHalf.add(documents[i].data['Review'].toString().substring(51));
}else{
firstHalf.add( documents[i].data['Review'].toString());
secondHalf.add("");
}
}
}
for(var doc in documents){
print(doc.data);
}
return Container(
height:MediaQuery.of(context).size.height,
child: ListView.builder(
key: key,
itemCount: documents.length,
itemBuilder: (context,index) => AnimatedSize(
vsync: this,
curve: Curves.easeIn,
duration: new Duration(milliseconds: 300),
child: Container(
height: cardHeight[index],
child: Card(
elevation: 2.0,
child: ListTile(
onTap: (){
stateUpdate(index);
},
leading: CircleAvatar(),
title: Text(documents[index].data['Title']),
subtitle: Column(children: [
RatingBar(
itemBuilder: (context, _) => Icon(
Icons.star,
color: Colors.amber,
),
maxRating: 5.0,
allowHalfRating: false,
ignoreGestures: true,
initialRating: int.parse(documents[index].data['Rating'].toString()).toDouble(),
),
Wrap(
children: <Widget>[
Text(firstHalf[index].toString()),
Text("Read More")
],
),
]),
),
),
),
),
),
);
}
void AddNetworkImages (BuildContext context){
if(!load) {
for (int i = 0; i < widget.productData.length; i++) {
if (widget.productData.containsKey('Img$i')) {
print("Img$i exists");
_Images.add(
NetworkImage(widget.productData['Img$i'])
);
productImages.add(
CachedNetworkImage(
imageUrl: widget.productData['Img$i'],
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
),
);
}
}
}
}
void loadWidgets(BuildContext context){
setState(() {
});
load = true;
}
@override
void initState() {
//AddNetworkImages(context);
addPageWidgets();
super.initState();
}
@override
Widget build(BuildContext context) {
WidgetsBinding.instance
.addPostFrameCallback((_) => AddNetworkImages(context));
WidgetsBinding.instance
.addPostFrameCallback((_) => loadWidgets(context));
return Scaffold(
appBar: AppBar(
actions: <Widget>[
],
title: Text("$changeableText"),
backgroundColor: Colors.deepOrangeAccent,
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: BouncingScrollPhysics(
),
child:IndexedStack(
index: pageIndex,
children: pageWidget,
)),
bottomNavigationBar:BottomNavigationBar(
currentIndex: pageIndex,
onTap: (index){
setState(() {
pageIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart),
title: Text("Overview")
),
BottomNavigationBarItem(
icon: Icon(Icons.star),
title: Text("Reviews")
)
],
)
);
}
void stateUpdate(int index) {
setState(() {
firstHalf[index]+=secondHalf[index];
cardHeight[index] = MediaQuery.of(context).size.height/2;
});
print(index);
print(firstHalf[index]);
}
}
现在,在 buildReviewsWidgets() 方法中,我正在获取所有评论数据,对其进行迭代并将其拆分为 firstHalf 和 secondHalf 列表,这样,在点击 ListTile 时,我可以简单地加入 firstHalf[index ] 和 secondHalf [index],就像我在 ListTiles 的 ontap 方法上所做的那样,但是点击列表图块根本没有任何作用.. 列表图块不会更新,基本上没有任何反应。但有趣的是,如果我 setState 并更改 changeableText 的值,它确实会更新 appbar 上的文本。谁能告诉我为什么会这样?我该如何解决?
【问题讨论】:
-
Widget w = await buildReviewsWidgets();你想用它实现什么?如果你有一些Future使用FutureBuilder,不是这样的...... -
这里发生了很多事情,并且代码的格式使得很难直观地解析和理解你正在发生的事情。不过,我的第一个猜测是,
setState正在触发您的小部件的重建就好了,但是您正在更新的内容不会导致任何可见的变化。 -
@pskink 如果您查看该方法,您会发现它正在获取文档并按照相同的方式构建小部件。
-
@pskink 实际上,我认为我不需要它,因为我不需要获取每次都会更新的恒定信息源。
-
@Abion47 在 ListView.builder 中,您可以看到 ListTile 的 subtitle 属性设置为 Text 小部件,其中 firstHalf[index] 作为字符串传递,并且在 onTap 方法上,我调用了另一个方法确实使用 setState 来更新 firstHalf[index] 的值。这还不足以触发重建吗?