如何重用标签中的列表视图?

时间:2019-03-28 11:15:26

标签: listview dart flutter tabs

我想在具有两个选项卡的扁平布局中重用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,
    );
  }
}

1 个答案:

答案 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小部件。