[英]Use extracted Listview.builder with two lists in Flutter
我是 Flutter 的初学者。
我设计了这个页面:
而不是重复整个 Listview.builder。 我想将自定义 Listview.builder 的两个实例与两个列表一起使用,一个列表用于水果,另一个用于蔬菜。
如上图所示,我尝试通过以下方式在蔬菜部分显示蔬菜:
Listview.builder 小部件:
import 'package:flutter/material.dart';
import 'package:grocery_store/models/products_list.dart';
import '../utilities/add_product.dart';
import '../utilities/constants.dart';
class ProductsListView extends StatelessWidget {
final String? productImage;
final String? productName;
final String? productCategory;
final String? productPrice;
const ProductsListView({
Key? key,
this.productImage,
this.productName,
this.productCategory,
this.productPrice,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: fruitsList.length,
itemBuilder: (BuildContext context, int index) {
return ClipRect(
child: Container(
width: 140.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 10,
color: Colors.black,
),
],
),
margin: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 10),
child: Column(
children: [
Image.asset(
fruitsList[index].fruitImage!,
height: 80.0,
width: 90.0,
),
const SizedBox(
height: 15,
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
fruitsList[index].fruitName!,
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
Text(
fruitsList[index].fruitCategory!,
textAlign: TextAlign.left,
style: const TextStyle(
height: 1.5,
color: kDarkGrey,
fontSize: 12.5,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
Text(
fruitsList[index].fruitPrice!,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const AddProduct(),
],
)
],
),
),
),
);
},
);
}
}
水果蔬菜清单:
import '../utilities/constants.dart';
class Fruits {
final String? fruitImage;
final String? fruitName;
final String? fruitCategory;
final String? fruitPrice;
Fruits(
{this.fruitImage, this.fruitName, this.fruitCategory, this.fruitPrice});
}
final Fruits bananas = Fruits(
fruitImage: '${kFruitsImagesAsset}bananas.png',
fruitName: 'Bananas',
fruitCategory: 'Organic',
fruitPrice: '\$4.99',
);
final Fruits apples = Fruits(
fruitImage: '${kFruitsImagesAsset}apples.png',
fruitName: 'Apples',
fruitCategory: 'Organic',
fruitPrice: '\$5.00',
);
final Fruits chikku = Fruits(
fruitImage: '${kFruitsImagesAsset}chikku.png',
fruitName: 'Chikku',
fruitCategory: 'Organic',
fruitPrice: '\$9.00',
);
final Fruits peaches = Fruits(
fruitImage: '${kFruitsImagesAsset}peaches.png',
fruitName: 'Peaches',
fruitCategory: 'Organic',
fruitPrice: '\$12.00',
);
List<Fruits> fruitsList = [bananas, apples, chikku, peaches];
class Vegetables {
final String? vegetableImage;
final String? vegetableName;
final String? vegetableCategory;
final String? vegetablePrice;
Vegetables(
{this.vegetableImage,
this.vegetableName,
this.vegetableCategory,
this.vegetablePrice});
}
final Vegetables okra = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}okra.png',
vegetableName: 'Okra',
vegetableCategory: 'Organic',
vegetablePrice: '\$6.99',
);
final Vegetables peas = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}peas.png',
vegetableName: 'Peas',
vegetableCategory: 'Organic',
vegetablePrice: '\$10.50',
);
final Vegetables potatoes = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}potatoes.png',
vegetableName: 'Potatoes',
vegetableCategory: 'Organic',
vegetablePrice: '\$5.99',
);
final Vegetables taro = Vegetables(
vegetableImage: '${kVegetablesImagesAsset}taro.png',
vegetableName: 'Taro',
vegetableCategory: 'Organic',
vegetablePrice: '\$5.50',
);
List<Vegetables> vegetablesList = [okra, peas, potatoes, taro];
我要显示两个列表的主页:
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:grocery_store/models/product_cards_column.dart';
import 'package:grocery_store/utilities/constants.dart';
import 'package:grocery_store/utilities/grocery_text_field.dart';
import '../models/products_cards.dart';
import '../models/products_list.dart';
class GroceryPage extends StatelessWidget {
const GroceryPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
var discountPortrait =
MediaQuery.of(context).orientation == Orientation.portrait;
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 1, 0),
child: Row(
children: [
const Text(
'Grocery',
style: kTitleTextStyle,
),
const Spacer(),
ClipRRect(
borderRadius: BorderRadius.circular(16.0),
child: Image.asset(
'images/apple.jpg',
width: 46.0,
height: 46.0,
fit: BoxFit.cover,
),
),
],
),
),
const SizedBox(height: 10.0),
Row(children: [
GroceryTextField.groceryTextField(
groceryText: 'Search...',
),
const SizedBox(width: 5.0),
Container(
height: 50.0,
width: 50.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18.0),
color: kLightGrey,
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: SvgPicture.asset(
'images/funnel.svg',
semanticsLabel: 'Funnel',
color: kDarkGrey,
),
),
),
]),
const SizedBox(height: 10.0),
Container(
height: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
color: const Color(0xFFE9F9F2),
),
width: double.infinity,
child: Stack(
children: [
Positioned(
bottom: -150,
right: discountPortrait ? -30 : 30,
height: 290,
width: 430,
child: Image.asset(
'${kProductsImagesAsset}lettuce.png',
),
),
Positioned(
top: discountPortrait ? 35 : 15,
left: discountPortrait ? 25 : 100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Get Up To',
style: kGreenTitleStyle.copyWith(
fontSize: discountPortrait ? 20 : 60,
),
),
Text(
'%10 off',
style: kGreenTitleStyle.copyWith(
fontSize: 40.0,
),
),
],
),
),
],
),
),
Column(
children: const [
ProductCardsRow(
groceryType: 'Fruits',
),
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
),
),
],
),
Column(
children: const [
ProductCardsRow(
groceryType: 'Vegetables',
),
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
),
),
],
),
],
),
),
),
),
);
}
}
希望有人能帮忙
是的,它非常简单,只需单击项目中的listview.builder
方法,然后单击 Android Studio IDE window 右侧的 FLutter Outline ,如下所示:
完成后,ListView.Builder 将在此小部件树中可见。 您需要做的是右键单击要提取的小部件,然后单击提取方法。 您将看到一个对话框,询问新创建的小部件的名称:
并且将在文件底部创建一个新的小部件。 只需更改 listview.builders 的参数,它看起来像这样:
Widget build(BuildContext context) {
return CommonList(typeList: fruitslist); // use this to change the list
}
在新创建的小部件中,您需要执行相同的操作:
class CommonList extends StatelessWidget {
final List typeList; //add a list parameter
const CommonList({
Key? key, required this.typeList, //request that list parameter
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: typeList.length, // change the list type
itemBuilder: (BuildContext context, int index) {
return ClipRect(
child: Container(
width: 140.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 10,
color: Colors.black,
),
],
),
margin: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 10),
child: Column(
children: [
Image.asset(
typeList[index].fruitImage!, //update list to use it everywhere
height: 80.0,
width: 90.0,
),
const SizedBox(
height: 15,
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
typeList[index].fruitName!, //like here
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
Text(
typeList[index].fruitCategory!, //here
textAlign: TextAlign.left,
style: const TextStyle(
height: 1.5,
color: kDarkGrey,
fontSize: 12.5,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
Text(
typeList[index].fruitPrice!, //and here again
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const AddProduct(),
],
)
],
),
),
),
);
},
);
}
您可以在构造函数中设置另一个变量并将其称为list
并将您的Vegetables
和Fruits
传递给它,如下所示:
class ProductsListView extends StatelessWidget {
final List list;
const ProductsListView({
Key? key,
required this.list,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return ClipRect(
child: Container(
width: 140.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.white,
boxShadow: const [
BoxShadow(
blurRadius: 10,
color: Colors.black,
),
],
),
margin: const EdgeInsets.all(10.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 10, 10),
child: Column(
children: [
Image.asset(
list is List<Fruits> ? (list[index] as Fruits).fruitImage! : (list[index] as Vegetables).vegetableImage!,
height: 80.0,
width: 90.0,
),
const SizedBox(
height: 15,
),
Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
list is List<Fruits> ? (list[index] as Fruits).fruitName! : (list[index] as Vegetables).vegetableName!,
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
Text(
list is List<Fruits> ? (list[index] as Fruits).fruitCategory! : (list[index] as Vegetables).vegetableCategory!
textAlign: TextAlign.left,
style: const TextStyle(
height: 1.5,
color: kDarkGrey,
fontSize: 12.5,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
Text(
list is List<Fruits> ? (list[index] as Fruits).fruitPrice! : (list[index] as Vegetables).vegetablePrice!,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
const AddProduct(),
],
)
],
),
),
),
);
},
);
}
}
并像这样使用它:
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
list: vegetablesList,
),
),
SizedBox(
height: 215,
width: double.infinity,
child: ProductsListView(
list: fruitsList,
),
),
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.