【发布时间】:2020-12-30 04:00:10
【问题描述】:
背景:
我正在尝试生成可滚动的图像列表视图。该屏幕将分为三个阶段:
- 最初列出某种类型的图像(在元数据中的 firestore 字段中定义)
- 当用户选择其中一个小部件时,图像将更改为不同类型的图像
- 最后,可选的第三阶段显示不同的类型
每次按下时,所选图像将构建到一个新数组中,最终形成另一种由三个所选图像组成的图像视图,将在底部显示,单击按钮将读取“ 3 个选定图像的句子”。
我目前拥有的:
我通过调用包含 ListView 的类的 StreamProvider 提供了带有正确过滤图像的初始 ListView。目前这已被过滤,因为我对查询进行了硬编码。
这是最终显示 ListView 的屏幕
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_list.dart';
import 'package:showmeapp/Services/database.dart';
import 'package:showmeapp/models/new_image.dart';
class Sentence extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<List<NewImage>>.value(
value: FirestoreDatabaseService().firestoreImages,
child: Scaffold(
backgroundColor: Colors.blue[300],
appBar: AppBar(
title: Text('Make A Sentence'),
backgroundColor: Colors.blue[700],
elevation: 0.0,
),
body: ImageList(),
)
);
}
}
这是从该屏幕调用的 ImageList 类
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_card.dart';
import 'package:showmeapp/models/new_image.dart';
class ImageList extends StatefulWidget {
@override
_ImageListState createState() => _ImageListState();
}
class _ImageListState extends State<ImageList> {
@override
Widget build(BuildContext context) {
final images = Provider.of<List<NewImage>>(context) ?? [];
final requestImages = images.where((element) => element.imageClass == 'request').toList();
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: requestImages.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 24.0),
height: MediaQuery.of(context).size.height * 0.35,
child: ImageCard(newImage: requestImages[index]),
);
},
);
}
}
这是从 ImageList 类调用的自定义 ImageCard 类
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:showmeapp/Screens/Home/image_list.dart';
import 'package:showmeapp/models/new_image.dart';
class ImageCard extends StatelessWidget {
final NewImage newImage;
ImageCard({this.newImage});
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
width: MediaQuery.of(context).size.width * 0.3,
height: MediaQuery.of(context).size.height * 0.2,
child: Card(
elevation: 30.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
side: BorderSide(width: 2.0, color: Colors.blueAccent),
),
child: GestureDetector(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
'assets/${newImage.imageLocation}',
scale: 0.8,
height: MediaQuery.of(context).size.height * 0.2,
width: MediaQuery.of(context).size.width * 0.1,
),
),
onTap: () {
// String optionSelected = newImage.imageClass;
},
),
),
),
Container(
width: MediaQuery.of(context).size.width * 0.3,
child: Padding(
padding: EdgeInsets.all(5.0),
child: Center(
child: Text(
newImage.imageDescription,
style: TextStyle(
fontSize: 40.0,
),
),
),
),
)
],
);
}
}
最后,为了完整起见,这是与 Firebase 相关的函数和所有这些背后的调用
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:showmeapp/models/new_image.dart';
// A class for the Firestore Database Service
class FirestoreDatabaseService {
final String iid;
// Constructor for Database Class
FirestoreDatabaseService({ this.iid });
// create a reference to the Firestore 'images' collection
final CollectionReference firestoreImageCollection = FirebaseFirestore.instance.collection('images');
// Add or update image data - This will be useful for initial creation of image meta data for the app
Future updateFirestoreImageData(String description, String location, String type, String category) async {
return await firestoreImageCollection.doc(iid).set({
'image_category': category,
'image_description': description,
'image_location': location,
'image_type': type
});
}
// new image list from snapshot
List<NewImage> _newImageFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return NewImage(
imageClass: doc.data()['image_class'] ?? '',
imageType: doc.data()['image_type'] ?? '',
imageCategory: doc.data()['image_category'] ?? '',
imageLocation: doc.data()['image_location'] ?? '',
imageDescription: doc.data()['image_description'] ?? ''
);
}).toList();
}
// Get images from collection via stream
Stream<List<NewImage>> get firestoreImages {
return firestoreImageCollection.snapshots()
.map(_newImageFromSnapshot);
}
}
我正在努力解决的问题:
当用户选择“请求”图像之一时,我想传递一个值,以便下一组显示的图像属于“对象”类型。
但是如果我通过它,它总是将请求的提供者作为 Null 发送并且什么都不返回。
不起作用的代码:
ImageList 类
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_card.dart';
import 'package:showmeapp/models/new_image.dart';
class ImageList extends StatefulWidget {
@override
_ImageListState createState() => _ImageListState();
String searchClass;
ImageList({ this.searchClass });
}
class _ImageListState extends State<ImageList> {
@override
Widget build(BuildContext context) {
final String searchClass = ImageList().searchClass;
final images = Provider.of<List<NewImage>>(context) ?? [];
final requestImages = images.where((element) => element.imageClass == searchClass.toString()).toList();
print('search class is: $searchClass');
print('Class search class is: ${ImageList().searchClass}');
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: requestImages.length,
itemBuilder: (context, index) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 24.0),
height: MediaQuery.of(context).size.height * 0.35,
child: ImageCard(newImage: requestImages[index]),
);
},
);
}
}
句子屏幕/小部件
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_list.dart';
import 'package:showmeapp/Services/database.dart';
import 'package:showmeapp/models/new_image.dart';
class Sentence extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamProvider<List<NewImage>>.value(
value: FirestoreDatabaseService().firestoreImages,
child: Scaffold(
backgroundColor: Colors.blue[300],
appBar: AppBar(
title: Text('Make A Sentence'),
backgroundColor: Colors.blue[700],
elevation: 0.0,
),
body: ImageList(searchClass: 'request',),
)
);
}
}
因此,传递“请求”字符串并将其包含在 where 子句中会导致 Null。它仅在我在 where 子句中硬指定“请求”时才有效。上面的示例不是来自所选图像的操作,但与我试图告诉它最初通过传递的值加载“请求”图像的原理相同。一旦我可以通过初始值,那么我希望任何进一步的传递将插入到位:-)
我尝试了类、类和状态中的变量的变体(就像现在一样),但似乎无法让它携带值。
我将如何实现这一目标?是否可以使用 StreamProvider / ListView 构建器?
更新 我的 NewImage 类如下:
class NewImage {
final String imageType; // Whether the image is a Category image or Object Image
final String imageDescription; // Text to display with the image
final String imageLocation; // The URL or Location of the image
final String imageCategory; // The category that the image belongs to
final String imageClass; // A tag to identify the stage for sentences, such as Request, Object, Ending
NewImage({ this.imageType, this.imageDescription, this.imageLocation, this.imageCategory, this.imageClass });
}
谢谢
安德鲁
【问题讨论】:
标签: android-studio flutter listview dart google-cloud-firestore