我想在具有两个选项卡的扁平布局中重用ListView。例如,我想用它来显示旧约中的所有书和新约中的书,即使用相同的ListView在不同的选项卡上显示两个列表。我该如何完成? 以下是到目前为止我提出的代码。我在考虑使用选项卡控制器访问当前索引并使用它显示正确的列表。但是,我无法做到这一点,而且我似乎无法提出这样做的逻辑。谢谢。
import 'package:flutter/material.dart';
import 'package:navigation_drawer/tabs/old_testament.dart';
import 'package:navigation_drawer/tabs/new_testament.dart';
import 'package:navigation_drawer/model/book.dart';
void main() {
runApp(new MaterialApp(
title: "Testament",
home: new HomeTab(),
));
}
class HomeTab extends StatefulWidget {
@override
State<StatefulWidget> createState() => new TabState();
}
// SingleTickerProviderStateMixin is used for animation
class TabState extends State<HomeTab> with SingleTickerProviderStateMixin {
// Create a tab controller
TabController controller;
@override
void initState() {
super.initState();
// Initialize the Tab Controller
controller = new TabController(length: 2, vsync: this);
}
@override
void dispose() {
// Dispose of the Tab Controller
controller.dispose();
super.dispose();
}
TabBar getTabBar() {
return new TabBar(
tabs: <Tab>[
new Tab(
// set icon to the tab
icon: new Icon(Icons.brightness_2),
text: "Old Testament",
),
new Tab(
icon: new Icon(Icons.brightness_6),
text: "New Testament",
),
],
// setup the controller
controller: controller,
);
}
TabBarView getTabBarView(var tabs) {
return new TabBarView(
// Add tabs as widgets
children: tabs,
// set the controller
controller: controller,
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
// Appbar
appBar: new AppBar(
centerTitle: true,
// Title
title: new Text("Testament"),
// Set the background color of the App Bar
backgroundColor: Colors.blue,
// Set the bottom property of the Appbar to include a Tab Bar
bottom: getTabBar()
),
// Set the TabBar view as the body of the Scaffold
body: getTabBarView(<Widget>[new OldTestament(), new NewTestament()])
);
}
}
class ListTab extends StatefulWidget {
ListTab({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => ListTabState();
}
class ListTabState extends State<ListTab> {
List books;
@override
void initState() {
books = getOldTestamentBooks();
super.initState();
}
@override
Widget build(BuildContext context) {
// create a list tile for books
ListTile makeListTile(Book book) => ListTile(
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(
right: new BorderSide(
width: 1.0,
color: Colors.blue
)
)
),
child: Icon(
Icons.book,
color: Colors.grey
),
),
title: Text(
book.title,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold
),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child: Text(
book.testament,
style: TextStyle(color: Colors.black)
)
),
)
],
),
trailing: Icon(
Icons.keyboard_arrow_right,
color: Colors.black,
size: 30.0
),
onTap: () {},
);
// create a card view for the list tile
Card makeCard(Book book) => Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.circular(5.0),
),
child: makeListTile(book),
),
);
final makeBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: books.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(books[index]);
},
),
);
return Scaffold(
backgroundColor: Colors.white,
body: makeBody,
);
}
}
答案 0 :(得分:0)
如果我理解正确,您想重复使用同一Listview来显示书籍列表(一个标签中的旧约,另一标签中的新约)。 我建议您要做的是创建一个仅包含Listview.builder和ListTile模型的小部件,该小部件将书籍列表作为构造函数的参数。
将ListView小部件与ListTab分开后,新的小部件类将如下所示:
import 'package:flutter/material.dart';
import 'package:navigation_drawer/model/book.dart';
class BookList extends StatelessWidget {
List<Book> _books;
BookList(this._books);
@override
Widget build(BuildContext context) {
return Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: _books.length,
itemBuilder: (BuildContext context, int index) {
return Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.circular(5.0),
),
child: ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
leading: Container(
padding: EdgeInsets.only(right: 12.0),
decoration: new BoxDecoration(
border: new Border(right: new BorderSide(width: 1.0, color: Colors.blue))),
child: Icon(Icons.book, color: Colors.grey),
),
title: Text(
_books[index].title,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
subtitle: Row(
children: <Widget>[
Expanded(
flex: 4,
child: Padding(
padding: EdgeInsets.only(left: 10.0),
child:
Text(_books[index].testament, style: TextStyle(color: Colors.black))),
)
],
),
trailing: Icon(Icons.keyboard_arrow_right, color: Colors.black, size: 30.0),
onTap: () {},
),
),
);
},
),
);
}
}
您的ListTab小部件将如下所示:
class ListTab extends StatefulWidget {
ListTab({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => ListTabState();
}
class ListTabState extends State<ListTab> {
List books;
@override
void initState() {
books = getOldTestamentBooks();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: BookList(books),
);
}
}
通过这种方式,您可以在所需的任何标签中重复使用BookList小部件。