Несколько лесов для каждой страницы в приложении Flutter - PullRequest
1 голос
/ 06 марта 2020

Документация API: https://api.flutter.dev/flutter/material/Scaffold-class.html гласит:

Скаффолд был спроектирован как единый контейнер верхнего уровня для MaterialApp, и, как правило, нет необходимости вкладывать каркасы. Например, в пользовательском интерфейсе с вкладками, где bottomNavigationBar - это TabBar, а тело - TabBarView, у вас может возникнуть желание сделать так, чтобы каждая панель вкладок отображала скаффолд с другим названием AppBar. Было бы лучше добавить прослушиватель к TabController, который обновляет панель приложений.

Означает ли это, что для приложения "Материал" требуется только один элемент Scaffold или один элемент-родитель Scaffold для каждой страницы. Если это первое, как мы будем ориентироваться? Если это позже, не значит ли это, что обычные AppBar и BottomBar перерисовываются при каждой навигации? Какая лучшая практика.

Ответы [ 2 ]

1 голос
/ 06 марта 2020

Это означает, что, как правило, должен быть один Scaffold для каждой страницы (точнее, для каждого Route / screen), и что вы не должны вкладывать Scaffold s.

Навигация между экранами

Например, посмотрите на этот фрагмент, который вы можете запустить в DartPad :

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

Здесь вы можете видите, есть две разные страницы / Route s / screens, и у каждой есть свой Scaffold. Мы перемещаемся назад и вперед, используя Navigator, и поэтому наши страницы добавляются в стек, один Scaffold поверх другого. Это нормально.

Если позже, разве это не означает, что общий AppBar и BottomBar перерисовываются при каждой навигации?

Да, но это так именно то, что мы хотим, когда мы делаем два отдельных экрана, каждый со своим собственным Scaffold.

Навигация внутри тела лесов / вложенные навигации

С другой стороны, посмотрите в этом примере:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Scaffold(
        body: Center(
          child: RaisedButton(
            child: Text('Open route'),
            onPressed: () {},
          ),
        ),
      ),
    );
  }
}

Здесь мы вкладываем два Scaffold s, и, как вы можете видеть, вторая панель приложения рисуется под первой панелью приложения. Это не лучший подход для вкладок или вложенных переходов. Если вы хотите перемещаться внутри тела Scaffold и изменять панель приложения в зависимости от содержимого, предпочтительнее использовать TabControllers, например DefaultTabController. Взгляните на этот пример:

import 'package:flutter/material.dart';

void main() {
  runApp(TabBarDemo());
}

class TabBarDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            title: Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Icon(Icons.directions_car),
              Icon(Icons.directions_transit),
              Icon(Icons.directions_bike),
            ],
          ),
        ),
      ),
    );
  }
}

Как видите, мы использовали только один Scaffold, так как на самом деле мы имеем дело только с одним экраном. Просто так получается, что мы хотим показывать контентные страницы и перемещаться внутри тела Scaffold.

Заключение

Как общее правило: используйте только один Scaffold на Route / экран. Используйте только один Scaffold с виджетами, такими как TabController или IndexedStack, для навигации по содержимому внутри тела одного экрана.

0 голосов
/ 06 марта 2020

Я предлагаю вам использовать общие Scaffold с AppBar и BottomBar для вашего приложения, и, как пользователь, изменяющий вкладки BottomBar, вы должны управлять телом Scaffold.

* 1007. * Вы можете управлять своим одиночным эшафотом с помощью нескольких вкладок:
class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  int _currentIndex;
  List<Widget> _children;

  @override
  void initState() {
    _currentIndex = 0;
    _children = [
      Screen1(),
      Screen2(),
      Screen3(),
      Screen4(),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: onTabTapped,
        type: BottomNavigationBarType.fixed,
        fixedColor: Colors.blue,
        items: [
          BottomNavigationBarItem(
            title: Text("Screen 1"),
          ),
          BottomNavigationBarItem(
            title: Text("Screen 2"),
          ),
          BottomNavigationBarItem(title: Text("Screen 3")),
          BottomNavigationBarItem(title: Text("Screen 4")),
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...