文本框聚焦时“有大小”错误

问题描述 投票:0回答:0

我有一个固定的

AppBar()
BottomNavigationBar()
并且只为整个应用程序改变身体。

为了实现这一点,我使用了

builder:
小部件中的
MaterialApp()
属性。

现在,当我点击

TextField
时,它会抛出
hasSize
错误。当我从
FocusNode()
中删除
TextField
时,错误消失了。那么,为什么焦点节点会抛出这个错误,我应该怎么做才能解决这个问题。

主要功能:

void main() async {
  navigationServiceController.registerLazySingleton(() => NavigationService());
  WidgetsFlutterBinding.ensureInitialized();
  prefs = await SharedPreferences.getInstance();
  if (kIsWeb) {
    setUrlStrategy(PathUrlStrategy());
  }
  await Firebase.initializeApp(
      name: "T2G", options: DefaultFirebaseOptions.currentPlatform);
  await getFlagList();
  await gettingLanguage();

  SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  runApp(const Inizilation());
}

class Inizilation extends StatelessWidget {
  const Inizilation({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      initialRoute: initialPage(),
      initialBinding: InitialBinding(),
      title: "T2G",
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        scrollbarTheme: const ScrollbarThemeData(
          thickness: MaterialStatePropertyAll<double>(0),
          trackVisibility: MaterialStatePropertyAll<bool>(false),
          thumbVisibility: MaterialStatePropertyAll<bool>(false),
        ),
        fontFamily: "AvenirLTDStd",
        appBarTheme: const AppBarTheme(backgroundColor: kWhite),
        primaryColor: kOrange,
        primarySwatch: Colors.red,
        applyElevationOverlayColor: true,
        focusColor: Colors.transparent,
        iconTheme: const IconThemeData(
          color: kBlack,
        ),
      ),
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [
        Locale("de", "DE"),
        Locale("en", "US"),
        Locale("fr", "FR"),
        Locale("nl", "NL"),
        Locale("pt-br", "pt-BR"),
      ],
      scrollBehavior: RemoveGlowEffect().copyWith(scrollbars: false),
      enableLog: true,
      defaultTransition: Transition.fade,
      transitionDuration: const Duration(milliseconds: 500),
      builder: (BuildContext context, Widget? child) =>
          MainLayout(child: child),
      key: navigatorKey,
      onGenerateRoute:
          navigationServiceController<NavigationService>().generateRoute,
    );
  }
}

导航功能:

class NavigationService {
  Future<dynamic> navigateTo(String routeName) {
    return Get.toNamed(routeName)!;
  }

  void navigateBack() {
    return Get.back();
  }

  void splashScreenPage() {
    navigateTo(splashScreen);
  }

  void emailPage() {
    enableLanguage.value = true;
    enableAppBar.value = true;
    commonBottomBarViewModel.title.value = false;
    navigateTo(emailCheckScreen);
  }

  void passwordPage() {
    navigateTo(passwordScreen);
  }

  void registerPage() {
    navigateTo(registerScreen);
  }

  void forgotEmailTriggerPage() {
    navigateTo(forgotPasswordEmailScreen);
  }

  void forgotPasswordPage() {
    navigateTo(forgotPasswordScreen);
  }

  void taskListPage() {
    enableLanguage.value = false;
    enableBottomBar.value = true;
    commonBottomBarViewModel.title.value = true;
    navigateTo(taskListScreen);
  }

  void taskDetailsPage() {
    navigateTo(taskDetailsScreen);
  }

  void actualDurationPage() {
    navigateTo(actualDurationScreen);
  }

  void extraAmountPage() {
    navigateTo(extraAmountScreen);
  }

  void signaturePage() {
    navigateTo(signatureScreen);
  }

  void taskComplitionPage() {
    navigateTo(taskCompletionScreen);
  }

  void logoutPage() {
    enableLanguage.value = true;
    enableBottomBar.value = false;
    navigateTo(logoutScreen);
  }

  Route<dynamic> generateRoute(RouteSettings settings) {
    switch (settings.name) {
      case splashScreen:
        {
          return GetPageRoute(
            routeName: splashScreen,
            page: () => const SplashScreen(),
            binding: SplashScreenBinding(),
            settings: settings,
          );
        }

      case passwordScreen:
        {
          return GetPageRoute(
            routeName: passwordScreen,
            page: () => const PasswordPage(),
            settings: settings,
          );
        }
      case registerScreen:
        {
          return GetPageRoute(
            routeName: registerScreen,
            page: () => const AccountRegister(),
            settings: settings,
          );
        }
      case forgotPasswordEmailScreen:
        {
          return GetPageRoute(
            routeName: forgotPasswordEmailScreen,
            page: () => const ForgotEmailTrigger(),
            settings: settings,
          );
        }
      case forgotPasswordScreen:
        {
          return GetPageRoute(
            routeName: forgotPasswordScreen,
            page: () => const ForgotEmailTriggerConfirmation(),
            settings: settings,
          );
        }
      case taskListScreen:
        {
          return GetPageRoute(
            routeName: taskListScreen,
            page: () => const TaskListPage(),
            binding: TaskListBinding(),
            settings: settings,
          );
        }
      case taskDetailsScreen:
        {
          return GetPageRoute(
            routeName: taskDetailsScreen,
            page: () => const TaskDetailsPage(),
            binding: TaskDetailsBinding(),
            settings: settings,
          );
        }
      case actualDurationScreen:
        {
          return GetPageRoute(
            routeName: actualDurationScreen,
            page: () => const ActualDuration(),
            binding: TaskDetailsBinding(),
            settings: settings,
          );
        }
      case extraAmountScreen:
        {
          return GetPageRoute(
            routeName: extraAmountScreen,
            page: () => const ExtraAmount(),
            binding: ExtraAmountBinding(),
            settings: settings,
          );
        }
      case signatureScreen:
        {
          return GetPageRoute(
            routeName: signatureScreen,
            page: () => const Signature(),
            binding: SignatureBinding(),
            settings: settings,
          );
        }
      case taskCompletionScreen:
        {
          return GetPageRoute(
            routeName: taskCompletionScreen,
            page: () => const TaskComplition(),
            binding: TaskCompletionBinding(),
            settings: settings,
          );
        }
      case inAppNotificaitonScreen:
        {
          return GetPageRoute(
            routeName: inAppNotificaitonScreen,
            page: () => const InAppNotification(),
            settings: settings,
          );
        }
      case profileScreen:
        {
          return GetPageRoute(
            routeName: profileScreen,
            page: () => const ProfilePage(),
            binding: ProfileBinding(),
            settings: settings,
          );
        }
      default:
        {
          return GetPageRoute(
            routeName: emailCheckScreen,
            page: () => const EmailCheck(),
            binding: LoginBinding(),
            settings: settings,
          );
        }
    }
  }
}

主要布局:

class MainLayout extends StatelessWidget {
  const MainLayout({super.key, required this.child});

  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        navigationServiceController<NavigationService>().navigateBack();
        return true;
      },
      child: Scaffold(
          appBar: const CommonAppBar(),
          body: child,
          bottomNavigationBar: const CommonBottomBar()),
    );
  }
}

电子邮件检查页面:

class EmailCheck extends StatelessWidget {
  const EmailCheck({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    return GetBuilder<LoginViewModel>(
      init: LoginViewModel(),
      builder: (loginViewModel) {
        return Center(
          child: SingleChildScrollView(
            physics: const NeverScrollableScrollPhysics(),
            child: Container(
              width: width < 480 ? width : 400,
              height: height,
              padding: const EdgeInsets.all(10),
              alignment: Alignment.center,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  SizedBox.fromSize(
                    size: Size.fromHeight(height * 0.1),
                  ),
                  Image.asset(
                    kSearchFilterImage,
                    width: width * 0.4,
                    height: height * 0.2,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(bottom: 10, top: 10),
                    child: Obx(
                      () => CommonText(
                        text: kLanguage.value.loginTextInfo,
                        size: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                  Align(
                    alignment: Alignment.centerLeft,
                    child: Obx(
                      () => CommonText(
                        text: kLanguage.value.enterEmail,
                        textAlign: TextAlign.left,
                      ),
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.symmetric(vertical: 10),
                    child: Obx(
                      () => CommonTextFormField(
                        controller: loginViewModel.emailController,
                        focusNode: loginViewModel.emailFocusNode,
                        hint: kLanguage.value.knownemail,
                        keyboardType: TextInputType.emailAddress,
                        onFieldSubmitted: (email) =>
                            kIsWeb ? loginViewModel.validateEmail() : () {},
                        focusBorderColor: kBlack45,
                      ),
                    ),
                  ),
                  Obx(
                    () => LoadingButton(
                        status: loginViewModel.buttonLoading,
                        onTap: () => loginViewModel.validateEmail(),
                        text: kLanguage.value.ok),
                  ),
                ],
              ),
            ),
          ),
        );
      },
    );
  }
}

错误:

════════ Exception caught by foundation library ════════════════════════════════
The following assertion was thrown while dispatching notifications for FocusNode:
RenderBox was not laid out: RenderEditable#d95c6 NEEDS-LAYOUT NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
box.dart:1
Failed assertion: line 2009 pos 12: 'hasSize'

2

Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=2_bug.md

When the exception was thrown, this was the stack
#2      RenderBox.size
box.dart:2009
#3      EditableTextState._updateSizeAndTransform
editable_text.dart:3527
#4      EditableTextState._openInputConnection
editable_text.dart:2920
#5      EditableTextState._openOrCloseInputConnectionIfNeeded
editable_text.dart:2955
#6      EditableTextState._handleFocusChanged
editable_text.dart:3442
#7      ChangeNotifier.notifyListeners
change_notifier.dart:381
#8      FocusNode._notify
focus_manager.dart:1038
#9      FocusManager._applyFocusChange
focus_manager.dart:1803
(elided 4 frames from class _AssertionError and dart:async)
The FocusNode sending notification was: FocusNode#4f729([PRIMARY FOCUS])
    context: Focus
    PRIMARY FOCUS
════════════════════════════════════════════════════════════════════════════════
flutter textfield renderbox materialapp flutter-focus-node
© www.soinside.com 2019 - 2024. All rights reserved.