Flutter - 在一个屏幕上显示两个 ListView
Posted
技术标签:
【中文标题】Flutter - 在一个屏幕上显示两个 ListView【英文标题】:Flutter - Displaying two ListViews on one screen 【发布时间】:2019-01-25 09:38:25 【问题描述】:我正在尝试在另一个垂直 listView.builder
之上添加一个水平 listView.builder
。两个listViews
都应该有text
。
这是我到目前为止所做的,只有顶部水平 listView.builder
被绘制,当我尝试点击底部时强> 垂直listView.builder
应该被绘制,应用程序在调试中崩溃,我得到错误:NoSuchMethodError: The getter 'visible' was called on null.
另外,我不知道如何添加两个 text
字段,所以我把它们省略了。
我有很多代码,如果您需要查看更多代码,请这样做here
Widget _cryptoWidget()
return new Container(
child: new Column(
children: <Widget>[
new Flexible(
child: new ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index)
return _listViewFiller();
),
),
new Flexible(
child: new RefreshIndicator(
key: refreshKey,
child: new ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _currencies.length,
itemBuilder: (BuildContext context, int index)
final int i = index ~/ 2;
final Crypto currency = _currencies[i];
final MaterialColor color = _colors[i % _colors.length];
if (index.isOdd)
return new Divider();
return _getListItemUi(currency, color);
,
),
onRefresh:refreshList,
),
)
],
)
);
【问题讨论】:
两个listview都是Axis.horizontal 我已经解决了这个问题,很快就会回答我自己的问题 只需要修复一些位置错误 我的问题现已发布 尝试将列表视图放入 scoolview 小部件中。并检查this,*** 上的相同问题 【参考方案1】:import 'package:flutter/material.dart';
import 'background.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: new MyHomePage(title: 'Popular'),
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
List<String> items = [
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
"Item 6",
"Item 7",
"Item 8"
];
@override
Widget build(BuildContext context)
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
final headerList = new ListView.builder(
itemBuilder: (context, index)
EdgeInsets padding = index == 0?const EdgeInsets.only(
left: 20.0, right: 10.0, top: 4.0, bottom: 30.0):const EdgeInsets.only(
left: 10.0, right: 10.0, top: 4.0, bottom: 30.0);
return new Padding(
padding: padding,
child: new InkWell(
onTap: ()
print('Card selected');
,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(10.0),
color: Colors.lightGreen,
boxShadow: [
new BoxShadow(
color: Colors.black.withAlpha(70),
offset: const Offset(3.0, 10.0),
blurRadius: 15.0)
],
image: new DecorationImage(
image: new ExactAssetImage(
'assets/img_$index%items.length.jpg'),
fit: BoxFit.fitHeight,
),
),
// height: 200.0,
width: 200.0,
child: new Stack(
children: <Widget>[
new Align(
alignment: Alignment.bottomCenter,
child: new Container(
decoration: new BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: new BorderRadius.only(
bottomLeft: new Radius.circular(10.0),
bottomRight: new Radius.circular(10.0))),
height: 30.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'$items[index%items.length]',
style: new TextStyle(color: Colors.white),
)
],
)),
)
],
),
),
),
);
,
scrollDirection: Axis.horizontal,
itemCount: items.length,
);
final body = new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
elevation: 0.0,
backgroundColor: Colors.transparent,
actions: <Widget>[
new IconButton(icon: new Icon(Icons.shopping_cart, color: Colors.white,), onPressed: ())
],
),
backgroundColor: Colors.transparent,
body: new Container(
child: new Stack(
children: <Widget>[
new Padding(
padding: new EdgeInsets.only(top: 10.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Align(
alignment: Alignment.centerLeft,
child: new Padding(
padding: new EdgeInsets.only(left: 8.0),
child: new Text(
'Recent Items',
style: new TextStyle(color: Colors.white70),
)),
),
new Container(
height: 300.0, width: _width, child: headerList),
new Expanded(child:
ListView.builder(itemBuilder: (context, index)
return new ListTile(
title: new Column(
children: <Widget>[
new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
height: 72.0,
width: 72.0,
decoration: new BoxDecoration(
color: Colors.lightGreen,
boxShadow: [
new BoxShadow(
color:
Colors.black.withAlpha(70),
offset: const Offset(2.0, 2.0),
blurRadius: 2.0)
],
borderRadius: new BorderRadius.all(
new Radius.circular(12.0)),
image: new DecorationImage(
image: new ExactAssetImage(
'assets/img_$index%items.length.jpg',
),
fit: BoxFit.cover,
)),
),
new SizedBox(
width: 8.0,
),
new Expanded(
child: new Column(
mainAxisAlignment:
MainAxisAlignment.start,
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
new Text(
'My item header',
style: new TextStyle(
fontSize: 14.0,
color: Colors.black87,
fontWeight: FontWeight.bold),
),
new Text(
'Item Subheader goes here\nLorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry',
style: new TextStyle(
fontSize: 12.0,
color: Colors.black54,
fontWeight: FontWeight.normal),
)
],
)),
new Icon(
Icons.shopping_cart,
color: const Color(0xFF273A48),
)
],
),
new Divider(),
],
),
);
))
],
),
),
],
),
),
);
return new Container(
decoration: new BoxDecoration(
color: const Color(0xFF273A48),
),
child: new Stack(
children: <Widget>[
new CustomPaint(
size: new Size(_width, _height),
painter: new Background(),
),
body,
],
),
);
一个很好的例子,这里有完整的源代码 Styled list
【讨论】:
哈哈这比我自己的答案还要好!感谢您的帮助 如何隐藏一种布局?【参考方案2】:此示例代码在单个页面中显示了两个垂直方向的listview,两个lisview数据都来自API 我单独设计了一个列表项小部件或模板(ListItemPosts)。
body: ListView(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 10.0),
new Container(
margin: EdgeInsets.only(left: 10.0,right: 10.0),
height: 40.0, width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: Colors.green.withOpacity(0.25)
),
child:Padding(
padding: const EdgeInsets.only(left: 15.0,right: 15.0,top: 8.0),
child: Text(
'Invoiced Products',
style: TextStyle(
fontFamily: 'Quicksand',
fontSize: 20.0,
color: Colors.green,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
),
SizedBox(height: 5.0),
FutureBuilder<List<SalesOrder>>(
future: fetchstring(http.Client()),
builder: (context, snapshot)
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData ? ListItemPosts(
items: snapshot.data)
: Center(child: CircularProgressIndicator());
,
),
SizedBox(height: 10.0)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 10.0),
new Container(
margin: EdgeInsets.only(left:10.0,right: 10.0),
height: 40.0, width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: Colors.red.withOpacity(0.25)
),
child:Padding(
padding: const EdgeInsets.only(left: 15.0,right: 15.0,top: 8.0),
child: Text(
'Pending Products',
style: TextStyle(
fontFamily: 'Quicksand',
fontSize: 20.0,
color: Colors.red,
fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
),
),
SizedBox(height: 5.0),
FutureBuilder<List<SalesOrder>>(
future: fetchstring(http.Client()),
builder: (context, snapshot)
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData ? ListItemPosts(
items: snapshot.data)
: Center(child: CircularProgressIndicator());
,
),
SizedBox(height: 10.0)
],
)
],
)
ListitemPost(小部件)
class ListItemPosts extends StatelessWidget
final List<SalesOrder> items;
ListItemPosts(Key key, this.items) : super(key: key);
@override
Widget build(BuildContext context)
return Container(
child: new ListView.builder(
itemCount: items[0].sodetails.length,
primary: false,
shrinkWrap: true,
itemBuilder: (BuildContext context, int position)
return new Column(
children: <Widget>[
Divider(height: 5.0),
listItem(your Data can pass),
],
);
)
);
Widget listItem(Get the data )
return Container(
height: 125.0,
width: double.infinity,
margin: EdgeInsets.only(left: 10.0,right: 10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
color: Colors.white,
),
child:
Row(
children: <Widget>[
/*Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12.0),
image:
DecorationImage(image: AssetImage(imagedata))),
height: 100.0,
width: 80.0,
),*/
SizedBox(width: 0.0),
Container(
width: MediaQuery.of(context).size.width -30.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(child:
Text(
imagename,
textAlign: TextAlign.left,
softWrap: false,
style: TextStyle(fontFamily: 'Quicksand',fontSize: 14.0,color: Colors.black),
)),
SizedBox(height: 5.0),
Flexible(child:
Text(
trim.stringtrim(imagedes),
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(fontFamily: 'Quicksand',fontSize: 12.0,color: Colors.black45),
),
),
SizedBox(height: 5.0),
Text(
'Price: '+Price.toString(),
style: TextStyle(fontFamily: 'Quicksand'),
),
SizedBox(height: 5.0),
Text(
'Qty: '+Quatity.toString(),
style: TextStyle(fontFamily: 'Quicksand'),
),
SizedBox(height: 5.0),
Container(
height: 2.0,
width: 100.0,
color: Colors.amber,
),
],
),
],
),
),
],
),
);
【讨论】:
【参考方案3】:这可能不是最干净的方法,但我对 Flutter 比较陌生,所以这是我能做的最好的。
首先,我创建了一个主 container
来传递所有信息,这样我就可以将所有相关代码保存在他们尊重的地方,这篇文章允许我在同一个 container
中显示两个 listViews
这是传递给_positonalArguments
的containers
之一。这让我可以防止元素溢出,例如 maxHeight: 335.0,
是一个严格的参数,由于反复试验而发现。
我在传递给_positionalArguments
的两个容器中使用了相同的BoxConstraints
,以及相同的margin
值。
抱歉,我使用的是图像而不是粘贴代码,我正在使用手机上的堆栈来回答这个问题。
【讨论】:
以上是关于Flutter - 在一个屏幕上显示两个 ListView的主要内容,如果未能解决你的问题,请参考以下文章
来自一个 StreamBuilder 的 Flutter 快照显示在另一个 StreamBuilder 中
如何在 Flutter 的同一屏幕中管理两个带有数据的 ListView