为什么 Flutter 中弹窗中的 UI 没有更新?

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

我有一个项目,我与提供者一起管理状态。在这个项目中,我希望弹出窗口中选择的容器的颜色发生变化,但变化不是瞬时的。

main.dart代码:

import 'package:easy_localization/easy_localization.dart';
import 'package:want_to_do/services/service.locator.dart';
import 'export.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();
  SystemChrome.setSystemUIOverlayStyle(
    const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
    ),
  );
  await setupLocator();
  runApp(
    EasyLocalization(
      supportedLocales: [
        AppLocaleConstant.TR_LOCALE,
        AppLocaleConstant.EN_LOCALE,
      ],
      path: AppLocaleConstant.LANG_PATH,
      fallbackLocale: AppLocaleConstant.EN_LOCALE,
      child: MultiProvider(
        providers: [
          ChangeNotifierProvider(
            create: (_) => SettingsViewModel(),
          ),
        ],
        child: const MyApp(),
      ),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      navigatorKey: locator<AppRoutes>().baseNavigatorKey,
      onGenerateRoute: Routes.generateRoute,
      initialRoute: Routes.MainTab,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      builder: (context, widget) {
        return widget!;
      },
    );
  }
}

自定义任务优先级代码:

import 'package:want_to_do/export.dart';
import 'package:want_to_do/generated/locale_keys.g.dart';

class CustomTaskPriority extends StatelessWidget {
  final VoidCallback onClickCancel;
  final VoidCallback onClickSave;
  final int selectedPriority;
  final ValueChanged<int> onPrioritySelected;
  const CustomTaskPriority({
    super.key,
    required this.onClickCancel,
    required this.onClickSave,
    required this.selectedPriority,
    required this.onPrioritySelected,
  });

  @override
  Widget build(BuildContext context) {
    final List<int> priority = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 8),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 10),
            child: Text(
              LocaleKeys.home_taskPriority.locale,
              style: TextStyle(
                color: AppColors.white.withOpacity(0.87),
                fontSize: 16,
                fontWeight: FontWeight.w700,
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(bottom: 20),
            child: CustomDivider(),
          ),
          Wrap(
            spacing: 16,
            runSpacing: 16,
            children: [
              ...priority.map((priority) {
                return _buildPriorityItem(
                  onTap: () => onPrioritySelected(priority),
                  isClick: selectedPriority == priority,
                  priority: priority,
                );
              }).toList(),
            ],
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 20),
            child: Row(
              children: [
                Expanded(
                  child: CustomButton(
                    backgroundColor: AppColors.darkGrey,
                    title: LocaleKeys.cancel.locale,
                    titleColor: AppColors.lavenderBlue,
                    onClick: () => onClickCancel.call(),
                  ),
                ),
                SizedBox(width: 10),
                Expanded(
                  child: CustomButton(
                    title: LocaleKeys.save.locale,
                    onClick: () => onClickSave.call(),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildPriorityItem({
    required int priority,
    required bool isClick,
    required VoidCallback onTap,
  }) {
    return GestureDetector(
      onTap: () => onTap.call(),
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
        decoration: BoxDecoration(
          color: isClick ? AppColors.lavenderBlue : AppColors.balticSea,
          borderRadius: BorderRadius.circular(6),
        ),
        child: Column(
          children: [
            Image.asset(
              AppAssets.icFlagPath,
              width: 24,
              height: 24,
            ),
            SizedBox(height: 6),
            Text(
              '${priority.toString()}',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.w400,
                color: AppColors.white.withOpacity(0.87),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

我使用组件的区域 主选项卡代码:

import 'package:want_to_do/export.dart';
import 'package:want_to_do/generated/locale_keys.g.dart';
import 'package:want_to_do/ui/widgets/custom_task_priority.dart';

class MainTabPage extends StatefulWidget {
  const MainTabPage({super.key});

  @override
  State<MainTabPage> createState() => _MainTabPageState();
}

class _MainTabPageState extends BaseStatefulState<MainTabPage> {
  @override
  Widget build(BuildContext context) {
    final _vm = Provider.of<MainTabViewModel>(context);
    return Scaffold(
      backgroundColor: AppColors.backgroundColor,
      extendBody: true,
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          showCustomBottomSheet(
            context: context,
            child: AddTaskBottomSheet(
              taskTitleController: _vm.taskTitleController,
              taskDescriptionController: _vm.taskDescriptionController,
              onclickTaskPriority: () {
                _vm.checkTaskParameters()
                    ? showPopupDialog(
                        context: context,
                        child: CustomTaskPriority(
                          onClickCancel: appRoutes.popIfBackStackNotEmpty,
                          onClickSave: appRoutes.popIfBackStackNotEmpty,
                          selectedPriority: _vm.selectedPriority,
                          onPrioritySelected: (int value) {
                            _vm.selectedPriority = value;
                          },
                        ),
                      )
                    : showToastMessage(
                        LocaleKeys.errorMessages_emptyOrNotSame.locale,
                      );
              },
            ),
          );
        },
        shape: CircleBorder(eccentricity: 1),
        child: _buildFloatingActionButton(),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      bottomNavigationBar: BottomAppBar(
        padding: EdgeInsets.zero,
        color: AppColors.darkGrey,
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
          child: _buildNavigationBar(_vm),
        ),
      ),
      body: _buildBody(_vm),
    );
  }

  Widget _buildBody(MainTabViewModel vm) {
    switch (vm.currentIndex) {
      case 0:
        return HomeProvider();
      case 1:
        return CalendarProvider();
      case 2:
        return HomeProvider();
      case 3:
        return ProfileProvider();
      default:
        return HomeProvider();
    }
  }

  Widget _buildFloatingActionButton() {
    return Container(
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: AppColors.lavenderBlue,
        shape: BoxShape.circle,
      ),
      child: Image.asset(AppAssets.icPlusAddPath),
    );
  }

  Widget _buildNavigationBar(MainTabViewModel vm) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        BottomAppBarItem(
          iconAddress: vm.currentIndex == 0
              ? AppAssets.icActiveHomePath
              : AppAssets.icInactiveHomePath,
          pageName: LocaleKeys.home_home.locale,
          onTap: () {
            vm.currentIndex = 0;
          },
        ),
        BottomAppBarItem(
          iconAddress: vm.currentIndex == 1
              ? AppAssets.icActiveCalendarPath
              : AppAssets.icInactiveCalendarPath,
          pageName: LocaleKeys.calendar.locale,
          onTap: () {
            vm.currentIndex = 1;
          },
        ),
        SizedBox(),
        BottomAppBarItem(
          iconAddress: vm.currentIndex == 2
              ? AppAssets.icActiveFocusPath
              : AppAssets.icInactiveFocusPath,
          pageName: LocaleKeys.focus.locale,
          onTap: () {
            vm.currentIndex = 2;
          },
        ),
        BottomAppBarItem(
          iconAddress: vm.currentIndex == 3
              ? AppAssets.icActiveProfilePath
              : AppAssets.icInactiveProfilePath,
          pageName: LocaleKeys.profileTitle.locale,
          onTap: () {
            vm.currentIndex = 3;
          },
        ),
      ],
    );
  }
}

MainTabViewModel 代码:

import 'package:want_to_do/base/base_view_model.dart';
import 'package:want_to_do/export.dart';

class MainTabViewModel extends BaseViewModel {
  TextEditingController taskTitleController = TextEditingController();
  TextEditingController taskDescriptionController = TextEditingController();

  int _currentIndex = 0;

  int get currentIndex => _currentIndex;

  set currentIndex(int value) {
    _currentIndex = value;
    notifyListeners();
  }

  int _selectedPriority = 1;

  int get selectedPriority => _selectedPriority;

  set selectedPriority(int value) {
    _selectedPriority = value;
    print("Priority changed: $value");
    notifyListeners();
  }

  String _taskTitleText = '';
  String _taskDescriptionText = '';

  set taskTitleText(String text) {
    _taskTitleText = text;
    notifyListeners();
  }

  String get taskTitleText => _taskTitleText;

  set taskDescriptionText(String text) {
    _taskDescriptionText = text;
    notifyListeners();
  }

  String get taskDescriptionText => _taskDescriptionText;

  bool checkTaskParameters() {
    _taskTitleText = taskTitleController.text;
    _taskDescriptionText = taskDescriptionController.text;
    if (_taskTitleText.isNotEmpty && _taskDescriptionText.isNotEmpty)
      return true;
    return false;
  }
}

MainTabProvider 代码:

import 'package:want_to_do/export.dart';

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

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MainTabViewModel(),
      child: const MainTabPage(),
    );
  }
}

BaseStatfulState 代码:

import 'package:want_to_do/export.dart';
import 'package:want_to_do/services/service.locator.dart';
import 'package:want_to_do/utils/utility.dart';

abstract class BaseStatefulState<T extends StatefulWidget> extends State<T> {
  final AppRoutes appRoutes = locator<AppRoutes>();
  LocalStorageService localStorage = LocalStorageService();
  late FToast fToast;

  @override
  void initState() {
    super.initState();
    fToast = FToast();
    fToast.init(context);
  }

  void showToastMessage(String content) {
    fToast.showToast(
      child: Utility().buildToast(content),
      gravity: ToastGravity.TOP,
      positionedToastBuilder: (context, child) {
        return Positioned(
          child: child,
          top: 50,
          left: 20,
          right: 20,
        );
      },
    );
  }

  void showCustomBottomSheet({
    required BuildContext context,
    required Widget child,
  }) {
    showModalBottomSheet<void>(
      context: context,
      isScrollControlled: true,
      builder: (context) {
        return Padding(
          padding: EdgeInsets.only(
            bottom: MediaQuery.of(context).viewInsets.bottom,
          ),
          child: child,
        );
      },
    );
  }

  void showPopupDialog({
    required BuildContext context,
    required Widget child,
  }) {
    showDialog<void>(
      barrierColor: AppColors.black.withOpacity(0.74),
      barrierDismissible: false,
      context: context,
      builder: (context) {
        return Dialog(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(6),
          ),
          insetPadding: EdgeInsets.symmetric(horizontal: 24),
          elevation: 0,
          backgroundColor: AppColors.darkGrey,
          child: child,
        );
      },
    );
  }
}

BaseViewModel 代码:

import 'package:flutter/cupertino.dart';
class BaseViewModel extends ChangeNotifier {

}

单击加号按钮时出现的第一个屏幕: 在此输入图片描述

当我单击此屏幕上的某人时,我希望更改单击的容器的颜色。 这是我单击标志按钮时出现的屏幕: 在此输入图片描述

单击其中任何一个时的控制台输出: 在此输入图片描述

坦白说,我不想在组件中使用StatefulWidget。我不知道如何解决这种情况。我缺少什么?我在等待你的想法。提前致谢。我用消费者包装它,但仍然没有任何改变。

flutter dart user-interface cross-platform
1个回答
0
投票

首先,弹出窗口或显示对话框或底部工作表应该是一个单独的状态(statefullWidget 或 statefulbuilder 都为您提供 SetState() 函数)

其次,每当你想要更新此状态 UI 时,你应该将此 SetState() 函数作为参数传递并从外部调用它。

© www.soinside.com 2019 - 2024. All rights reserved.