Как повторно использовать просмотр списка во вкладках? - PullRequest
0 голосов
/ 28 марта 2019

Я хотел бы повторно использовать 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 голосов
/ 28 марта 2019

Если я правильно понял, вы хотите использовать один и тот же 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 на любой вкладке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...