简体   繁体   中英

ToggleButton in Bloc

I am trying to implement a ToggleButton using the Bloc pattern provided by Flutter. The code is very simple, but there is a problem. When I try to update my index so that it can be emitted from the Bloc to change my value from bool, the whole thing will do nothing. I have tried rewriting the code to look for the problem, but my guess is that the update will not go through. Does anybody know how to solve this issue?

Here is my Bloc:

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';

part 'calculate_event.dart';
part 'calculate_state.dart';

class CalculateBloc extends Bloc<CalculateEvent, CalculateState> {
  ///Constructor
  CalculateBloc()
      : super(CalculateInitial(
            selection: List.filled(3, false),
            totalAmount: '',
            textEditingController: TextEditingController())) {
    ///On-Method to emit the State
    on<CalculateEvent>((event, emit) {
      ///UpdateSelectionEvent
      if (event is UpdateSelectionEvent) {
        ///emit the Index of the button-press
        final updateSelect = List.of(state.selection);

        for (int i = 0; i < updateSelect.length; i++) {
          updateSelect[i] = event.selectIndex == i;
        }

        emit(UpdateSelectionState(
            selection: updateSelect,
            totalAmount: state.TotalAmount,
            tip: state.tip,
            textEditingController: state.textEditingController));
      }

      ///CalculatePercentageEvent
      if (event is CalculatePercentageEvent) {
        final controller = state.textEditingController;
        final totalAmount = double.parse(controller.text);
        final selectedIndex = state.selection.indexWhere((element) => element);
        final tipPercentage = [0.1, 0.15, 0.2][selectedIndex];
        final tipTotal = (totalAmount * tipPercentage).toStringAsFixed(2);
        emit(CalculatePercentageState(
            selection: state.selection,
            totalAmount: totalAmount.toString(),
            tip: tipTotal,
            textEditingController: state.textEditingController));
      }
    });
  }
}

Here is my State-class:

part of 'calculate_bloc.dart';

@immutable
abstract class CalculateState extends Equatable {
  final List<bool> selection;
  final String? tip;
  final String TotalAmount;
  final TextEditingController textEditingController;

  CalculateState(
      {this.tip = '',
      required this.TotalAmount,
      required this.selection,
      required this.textEditingController});

  @override
  List<Object?> get props => [selection, tip, TotalAmount];
}

class CalculateInitial extends CalculateState {
  CalculateInitial(
      {required List<bool> selection,
      String? tip = '',
      required String totalAmount,
      required TextEditingController textEditingController})
      : super(
            selection: selection,
            TotalAmount: totalAmount,
            textEditingController: textEditingController);
}

class CalculatePercentageState extends CalculateState {
  CalculatePercentageState(
      {required List<bool> selection,
      String? tip = '',
      required String totalAmount,
      required TextEditingController textEditingController})
      : super(
            selection: selection,
            TotalAmount: totalAmount,
            tip: tip,
            textEditingController: textEditingController);
}

class UpdateSelectionState extends CalculateState {
  UpdateSelectionState(
      {required List<bool> selection,
      String? tip = '',
      required String totalAmount,
      required TextEditingController textEditingController})
      : super(
            selection: selection,
            TotalAmount: totalAmount,
            tip: tip,
            textEditingController: textEditingController);
}

Here is my Event-class:

part of 'calculate_bloc.dart';

@immutable
abstract class CalculateEvent {}

class CalculatePercentageEvent extends CalculateEvent {}

class UpdateSelectionEvent extends CalculateEvent {
  final int selectIndex;

  UpdateSelectionEvent(this.selectIndex);
}

And my UI:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_day_1/bloc/calculate_bloc.dart';

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

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => CalculateBloc(),
      child: Scaffold(
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              BlocBuilder<CalculateBloc, CalculateState>(
                  bloc: BlocProvider.of<CalculateBloc>(context),
                  builder: (context, state) {
                    if (state.tip != null) {
                      return Column(
                        children: [
                          Padding(
                            padding: const EdgeInsets.all(20),
                            child: Text(state.tip ?? '',
                                style: const TextStyle(fontSize: 30)),
                          ),
                          const Text('Total Amount'),
                          SizedBox(
                            width: 80,
                            child: TextField(
                              controller: state.textEditingController,
                              keyboardType:
                                  const TextInputType.numberWithOptions(),
                              textAlign: TextAlign.center,
                              decoration:
                                  const InputDecoration(hintText: '\$100.00'),
                            ),
                          ),
                          Padding(
                            padding: const EdgeInsets.all(20),
                            child: ToggleButtons(
                              onPressed: (index) =>
                                  BlocProvider.of<CalculateBloc>(context)
                                      .add(UpdateSelectionEvent(index)),
                              isSelected: state.selection,
                              children: const [
                                Text('10%'),
                                Text('15%'),
                                Text('20%'),
                              ],
                            ),
                          ),
                        ],
                      );
                    } else {
                      return Container(
                        child: const Text('flase'),
                      );
                    }
                  }),
              ElevatedButton(
                onPressed: () {
                  BlocProvider.of<CalculateBloc>(context)
                      .add(CalculatePercentageEvent());
                },
                child: const Text('Calculate Amount'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

I have tried to utalize some of the BlocListener but it will not work. My other guess is to use additionl states to emit it.

I have found the problem. On the HomePage, the BlocProvider keeps building the app with the CalculateInitialState so that the new value is not passed through.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM