使用 flutter 提供程序包加载状态应用程序时在自定义按钮中显示 CircularProgressIndicator

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

我希望有人能帮助我:) 我有一个 flutter 应用程序并使用 provider package 来管理状态。

我想要实现的目标: 当我单击按钮并删除订单时,我想通知我的按钮并提供 isLoading 值。当 isLoading == true 时,按钮应显示加载微调器并降低其不透明度。

目前状态如何: 当我单击按钮时,订单会被删除,但不透明度不会降低,加载微调器也不会显示。虽然我可以在按钮中访问 isLoading 。

这是我的 OrderService(商店):

import ...

class OrderService with ChangeNotifier {
  final supabaseClient = Supabase.instance.client;

  bool _isLoading = false;

  bool get isLoading => _isLoading;

  _toggleLoading() {
    _isLoading = !_isLoading;
    notifyListeners();
  }

  Future<void> deleteOrderWithId(int id, BuildContext context) async {
    try {
      _toggleLoading();
      await supabaseClient.from('orders').delete().eq('id', id);
    } catch (err) {
      print(err);
    } finally {
      _toggleLoading();
    }
  }

  Future<void> createOrderFromOrder(Order order, BuildContext context) async {...}
}

这是我的自定义按钮:

import ...

class TrustyButton extends StatelessWidget {
  final void Function() onTap;
  final String text;
  final ButtonType type;
  final Icon? icon;

  TrustyButton({
    super.key,
    required this.onTap,
    required this.text,
    required this.type,
    this.icon,
  });

  final Map<ButtonType, Map<String, Color>> color = {...}

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => OrderService(),
      child: Consumer<OrderService>(
        builder: (context, orderService, _) => GestureDetector(
          onTap: () {
            onTap();
          },
          child: Opacity(
            opacity: orderService.isLoading ? 0.5 : 1,
            child: Container(
              height: 56,
              decoration: BoxDecoration(
                color: color[type]!['backgroundColor']!,
                borderRadius: const BorderRadius.all(
                  Radius.circular(20),
                ),
                boxShadow: [
                  BoxShadow(
                    color: const Color(0x15000000),
                    blurRadius: 10,
                    spreadRadius: 0,
                    offset: Offset.fromDirection(2, 2),
                  ),
                ],
              ),
              child: Center(
                child: orderService.isLoading
                    ? const CircularProgressIndicator(
                        color: Colors.white,
                      )
                    : renderButtonContent(),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
flutter dart state provider state-management
1个回答
0
投票

您面临这个问题,因为您正在

OrderService
内创建
TrustyButton
的新实例。相反,您必须抬起
ChangeNotifierProvider<TrustyButton>
,并通过
Consumer
内的
TrustyButton
使用它。 这是一个最小的例子:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: ChangeNotifierProvider(
            create: (context) => OrderService(),
            builder: (context, _) {
              return TrustyButton(
                onTap: () => context.read<OrderService>().deleteOrderWithId(),
              );
            },
          ),
        ),
      ),
    );
  }
}

class OrderService with ChangeNotifier {
  bool _isLoading = false;

  bool get isLoading => _isLoading;

  void _toggleLoading() {
    _isLoading = !_isLoading;
    notifyListeners();
  }

  Future<void> deleteOrderWithId() async {
    try {
      _toggleLoading();
      await Future.delayed(const Duration(seconds: 5));
    } catch (err) {
      print(err);
    } finally {
      _toggleLoading();
    }
  }
}

class TrustyButton extends StatelessWidget {
  final void Function() onTap;

  TrustyButton({
    super.key,
    required this.onTap,
  });

  @override
  Widget build(BuildContext context) {
    return Consumer<OrderService>(
        builder: (context, orderService, _) => GestureDetector(
          onTap: onTap,
          child: Opacity(
            opacity: orderService.isLoading ? 0.5 : 1,
            child: Container(
              height: 56,
              decoration: BoxDecoration(
                color: Colors.amberAccent,
                borderRadius: const BorderRadius.all(
                  Radius.circular(20),
                ),
                boxShadow: [
                  BoxShadow(
                    color: const Color(0x15000000),
                    blurRadius: 10,
                    spreadRadius: 0,
                    offset: Offset.fromDirection(2, 2),
                  ),
                ],
              ),
              child: Center(
                child: orderService.isLoading
                    ? const CircularProgressIndicator(
                        color: Colors.white,
                      )
                    : Text('Delete'),
              ),
            ),
          ),
        ),
      );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.