Несколько виджетов использовали один и тот же GlobalKey с TabController - PullRequest
0 голосов
/ 06 января 2019

Я пытаюсь установить начальный индекс при запуске приложения, получая этот индекс через общие настройки. Но у меня есть это сообщение об ошибке:

I / флаттер (19911): ══╡ ИСКЛЮЧЕНИЕ, ВЫДЕРЖАННОЕ БИБЛИОТЕКОЙ ВИДЖЕТОВ ════════════════════════════ I / flutter (19911): следующее утверждение было сгенерировано при создании RawGestureDetector (состояние: I / flutter (19911): RawGestureDetectorState # 438bc (жесты: [касание], поведение: непрозрачное)): I / flutter (19911): несколько виджетов использовали один и тот же GlobalKey. I / flutter (19911): ключ [GlobalKey # 1b0d6] использовался несколькими виджетами. Родители этих виджетов были: I / flutter (19911): - Padding (заполнение: EdgeInsets (16,0, 0,0, 16,0, 0,0), renderObject: RenderPadding # 61119 NEEDS-LAYOUT I / трепетание (19911): НЕОБХОДИМО ОТКРЫТЬ КРАСКУ) I / flutter (19911): - Padding (заполнение: EdgeInsets (16,0, 0,0, 16,0, 0,0), renderObject: RenderPadding # b3fbc NEEDS-LAYOUT I / флаттер (19911): НЕОБХОДИМОСТЬ КРАСКИ I / flutter (19911): GlobalKey может быть указан только для одного виджета за раз в дереве виджетов.

Вот мой код:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

import 'package:dynamic_theme/dynamic_theme.dart';

import 'package:my_pau/widgets/tabs/tab_playground.dart';
import 'package:my_pau/widgets/tabs/tab_public_bench.dart';
import 'package:my_pau/widgets/tabs/tab_public_toilet.dart';
import 'package:my_pau/widgets/tabs/tab_car_park.dart';
import 'package:my_pau/widgets/tabs/tab_car_pay_machine.dart';
import 'package:my_pau/widgets/drawer_widget.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() async {
  // Force the layout to Portrait mode
  await SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);

  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appTitle = 'My Pau';

    ThemeData _buildTheme(Brightness brightness) {
      return brightness == Brightness.dark
          ? ThemeData.dark().copyWith(
              textTheme: ThemeData.dark().textTheme.apply(
                    bodyColor: Colors.white,
                    displayColor: Colors.white,
                    fontFamily: 'Basier',
                  ),
              primaryColor: Colors.teal,
              accentColor: Colors.tealAccent,
              primaryColorDark: Colors.teal,
              backgroundColor: Colors.black)
          : ThemeData.light().copyWith(
              textTheme: ThemeData.light().textTheme.apply(
                    bodyColor: Colors.black,
                    displayColor: Colors.black,
                    fontFamily: 'Basier',
                  ),
              primaryColor: Colors.teal,
              accentColor: Colors.tealAccent,
              backgroundColor: Colors.white);
    }

    return DynamicTheme(
        defaultBrightness: Brightness.light,
        data: (brightness) => _buildTheme(brightness),
        themedWidgetBuilder: (context, theme) {
          return MaterialApp(
            debugShowCheckedModeBanner: false,
            localizationsDelegates: [
              // ... app-specific localization delegate[s] here
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
            ],
            supportedLocales: [
              const Locale('fr', 'FR'), // French
            ],
            title: appTitle,
            theme: theme,
            home: MyHomePage(title: appTitle),
          );
        });
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {

  Map<String, int> views = {
    'playground' : 0,
    'publicToilet' : 1,
    'carPark' : 2,
    'carPayMachine' : 3,
    'publicBench' : 4,
  };

  final List<Tab> _myTabs = <Tab>[
    Tab(icon: Icon(Icons.child_care), text: "Aire de jeux"),
    Tab(icon: Icon(Icons.wc), text: "WC publics"),
    Tab(icon: Icon(Icons.local_parking), text: "Parkings"),
    Tab(icon: Icon(Icons.departure_board), text: "Horodateurs"),
    Tab(icon: Icon(Icons.event_seat), text: "Bancs publics"),
  ];
  TabController _tabController;

  static const String _sharedPreferencesKeyView = 'view';
  String _defaultView;

  @override
  void initState() {
// _tabController = TabController(vsync: this, length: _myTabs.length, initialIndex: 3); ==> If I put this here it works
    _loadDefaultSettings().then((value) {
      _tabController = TabController(vsync: this, length: _myTabs.length, initialIndex: views[_defaultView]);
    });
    super.initState();
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  //Loading default settings value on start
  Future<void> _loadDefaultSettings() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      _defaultView =
          (prefs.getString(_sharedPreferencesKeyView) ?? 'playground');
    });
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 5,
      child: Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          bottom: TabBar(
            controller: _tabController,
            isScrollable: true,
            tabs: _myTabs,
          ),
        ),
        body: TabBarView(
          controller: _tabController,
          physics: NeverScrollableScrollPhysics(),
          children: <Widget>[
            TabPlayground(),
            TabPublicToilet(),
            TabCarPark(),
            TabCarPayMachine(),
            TabPublicBench(),
          ],
        ),
        drawer: DrawerWidget(),
      ),
    );
  }
}

Как мне избежать этого? Моя цель - при запуске приложения отобразить правильную вкладку в соответствии со значением, хранящимся в общих настройках;)

1 Ответ

0 голосов
/ 07 января 2019

Я решил свою проблему, используя небольшой трюк! Я оживляю TabController, когда сборка виджета завершена.

@override
  Widget build(BuildContext context) {
    WidgetsBinding.instance.addPostFrameCallback((_) => executeAfterWholeBuildProcess());
    return DefaultTabController(BuildContext context){...}

void _executeAfterWholeBuildProcess() {
    if (views[_defaultView] != null)
      _tabController.animateTo(views[_defaultView],
          duration: Duration(seconds: 1), curve: Curves.linear);
  }
...