我已经创建了一个单选按钮类似的功能事件,用户可以一次只选择单个元素。但是当我触发事件选择值时,它不会更新状态,但是列表会更新。
这是我的块文件
class SlotsTabbarBloc extends Bloc<SlotsTabbarEvent, SlotsTabbarState> {
SlotsTabbarSuccessState slotsTabbarSuccess =
SlotsTabbarSuccessState(slotData: const [], enableButton: true);
SlotsTabbarBloc(
this.slotsUsecase,
) : super(SlotsTabbarInitial()) {
SlotsTabbarLoading();
on<SelectAvailablePanelRadioButtonEvent>(
_selectAvailablePanelRadioButtonEvent,
);
}
Future<void> _selectAvailablePanelRadioButtonEvent(
SelectAvailablePanelRadioButtonEvent event,
Emitter<SlotsTabbarState> emit,
) async {
bool isAvailableSlotRadioEnabled = false;
for (int i = 0; i < event.dummyData.length; i++) {
event.dummyData[i].isSelected =
i == event.index ? isAvailableSlotRadioEnabled = true : false;
}
slotsTabbarSuccess = slotsTabbarSuccess.copyWith(
isAvailableSlotRadioEnabled: isAvailableSlotRadioEnabled,
availableSlotEntity: event.availableSlotEntity,
dummyData: event.dummyData,
);
emit(slotsTabbarSuccess);
}
}
这是事件类
class SelectAvailablePanelRadioButtonEvent extends SlotsTabbarEvent {
bool isAvailableSlotRadioEnabled;
final int index;
final AvailableSlotEntity availableSlotEntity;
final List<DummyData> dummyData;
final List<InterviewSlotDtoListEntity> slotData;
SelectAvailablePanelRadioButtonEvent({
required this.isAvailableSlotRadioEnabled,
required this.availableSlotEntity,
required this.index,
required this.dummyData,
required this.slotData,
});
}
这是国家级的
class SlotsTabbarSuccessState extends SlotsTabbarState {
final List<InterviewSlotDtoListEntity> slotData;
final AvailableSlotEntity? availableSlotEntity;
final SpecificBookedCancelledSlotDetailsEntity?
specificBookedCancelledSlotDetailsEntity;
final String reasonForCancellationEnum;
final String cancellationReason;
final List<Map<String, dynamic>>? radioMap;
final bool enableButton;
final bool isRadioButtonSelected;
final bool isAvailableSlotRadioEnabled;
bool isBookedResponseTrue;
bool isCancelledResponseTrue;
bool markSlotAvailable;
final List<DummyData>? dummyData;
SlotsTabbarSuccessState({
this.dummyData,
required this.slotData,
this.specificBookedCancelledSlotDetailsEntity,
this.reasonForCancellationEnum = 'CANDIDATE_CANCEL',
this.availableSlotEntity,
this.radioMap,
// this.enableButton = true,
this.enableButton = true,
this.isAvailableSlotRadioEnabled = true,
this.isRadioButtonSelected = false,
this.isBookedResponseTrue = false,
this.isCancelledResponseTrue = false,
this.markSlotAvailable = false,
this.cancellationReason = '',
});
SlotsTabbarSuccessState copyWith({
final List<DummyData>? dummyData,
String? cancellationReason,
List<InterviewSlotDtoListEntity>? slotData,
AvailableSlotEntity? availableSlotEntity,
SpecificBookedCancelledSlotDetailsEntity?
specificBookedCancelledSlotDetailsEntity,
String? reasonForCancellationEnum = 'CANDIDATE_CANCEL',
List<Map<String, dynamic>>? radioMap,
bool? isBookedResponseTrue = false,
bool? isCancelledResponseTrue = false,
bool? markSlotAvailable = false,
bool? isRadioButtonSelected = false,
bool? isAvailableSlotRadioEnabled,
//bool? enableButton ,
bool? enableButton,
}) {
return SlotsTabbarSuccessState(
dummyData: dummyData ?? this.dummyData,
cancellationReason: cancellationReason ?? this.cancellationReason,
radioMap: radioMap ?? this.radioMap,
isAvailableSlotRadioEnabled:
isAvailableSlotRadioEnabled ?? this.isAvailableSlotRadioEnabled,
enableButton: enableButton ?? this.enableButton,
isRadioButtonSelected:
isRadioButtonSelected ?? this.isRadioButtonSelected,
markSlotAvailable: markSlotAvailable ?? this.markSlotAvailable,
reasonForCancellationEnum:
reasonForCancellationEnum ?? this.reasonForCancellationEnum,
slotData: slotData ?? this.slotData,
specificBookedCancelledSlotDetailsEntity:
specificBookedCancelledSlotDetailsEntity ??
this.specificBookedCancelledSlotDetailsEntity,
availableSlotEntity: availableSlotEntity ?? this.availableSlotEntity,
isBookedResponseTrue: isBookedResponseTrue ?? this.isBookedResponseTrue,
isCancelledResponseTrue:
isCancelledResponseTrue ?? this.isCancelledResponseTrue,
);
}
@override
List<Object> get props => [
slotData,
reasonForCancellationEnum,
isBookedResponseTrue,
isCancelledResponseTrue,
markSlotAvailable,
enableButton,
isAvailableSlotRadioEnabled,
isRadioButtonSelected,
cancellationReason,
];
}
下面是我在UI中调用块的方法。每当我点击单选按钮时,它应该触发事件,事件应该发出状态。事件被触发,但UI未在屏幕上更新。刷新屏幕后会更新。
import 'package:auto_route/auto_route.dart';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class DummyData {
final String name;
final String designation;
bool isSelected = false;
DummyData(
{required this.name,
required this.designation,
required this.isSelected});
}
class AvailableOnClickWidget extends StatelessWidget {
final String slotStartTime;
final String slotEndTime;
final bool showCheckBox;
final List<InterviewSlotDtoListEntity> slotData;
final String levelId;
final String techStackId;
bool isRadioButtonEnabled;
AvailableOnClickWidget({
super.key,
required this.slotData,
required this.slotStartTime,
required this.slotEndTime,
required this.showCheckBox,
required this.isRadioButtonEnabled,
required this.techStackId,
required this.levelId,
});
TextEditingController candidateNameContoller = TextEditingController();
// List<DummyData> dummyData = [
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// DummyData(name: 'name', designation: 'designation', isSelected: false),
// ];
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => Injector.resolve<SlotsTabbarBloc>(),
child: BlocBuilder<SlotsTabbarBloc, SlotsTabbarState>(
builder: (context, state) {
if (state is SlotsTabbarInitial) {
BlocProvider.of<SlotsTabbarBloc>(context).add(
GetSpecificAvailableSlotDetailsEvent(
slotData: slotData,
fromTime: slotData[0].interviewSlotTimeDTOList[0].fromTime!,
toTime: slotData[0].interviewSlotTimeDTOList[0].toTime!,
slotDate: slotData[0].date!,
interviewLevelId: levelId,
techStackId: techStackId,
),
);
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is SlotsTabbarSuccessState) {
if (state.isBookedResponseTrue) {
CustomBotToastWidget.showToastWidget(
context: context,
onProgressBarCompletion: () {},
toastMessage: StringConstants.slotMarkedAsBooked,
showLinearProgressIndicator: false,
showToastActionButton: false,
cancelOnTap: () {
BotToast.cleanAll();
},
);
}
return SizedBox(
height: MediaQuery.of(context).size.height * 0.95,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
24.verticalSpace,
TitleWithCancelButtonWidget(
title:
'${state.availableSlotEntity!.slotDate}, $slotStartTime - $slotEndTime',
textStyle: TextStyleConstants.s14w600c101828fMontserrat,
),
40.verticalSpace,
Flexible(
fit: FlexFit.loose,
child: ListView.separated(
shrinkWrap: true,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return AvailableOnClickPopUpListTile(
radioOnTap: () {
BlocProvider.of<SlotsTabbarBloc>(context).add(
SelectAvailablePanelRadioButtonEvent(
slotData: state.slotData,
availableSlotEntity:
state.availableSlotEntity!,
isAvailableSlotRadioEnabled:
state.dummyData![index].isSelected,
index: index,
dummyData: state.dummyData!,
),
);
},
imageUrl:
"https://lh3.googleusercontent.com/a/AEdFTp439zX_GEWqClFIwDVMbf8eUuCvqcLvjdiQcslZ=s96-c",
title: state.dummyData![index].name,
subtitle: state.dummyData![index].designation,
chipContainerText: state.dummyData![index].name,
isRadioButtonEnabled:
state.dummyData![index].isSelected
// ==
// state.isAvailableSlotRadioEnabled,
//,
);
// return AvailableOnClickPopUpListTile(
// imageUrl: state.availableSlotEntity!
// .slotUserDetailList[0].imageUrl,
// title:
// '${state.availableSlotEntity!.slotUserDetailList[0].firstName} ${state.availableSlotEntity!.slotUserDetailList[0].lastName}',
// subtitle: state.availableSlotEntity!
// .slotUserDetailList[0].designation,
// chipContainerText: state.availableSlotEntity!
// .slotUserDetailList[0].levelOfInterview,
// isRadioButtonEnabled:
// state.isAvailableSlotRadioEnabled,
// radioOnTap: () {
// BlocProvider.of<SlotsTabbarBloc>(context).add(
// SelectAvailablePanelRadioButtonEvent(
// availableSlotEntity: state.availableSlotEntity!,
// isAvailableSlotRadioEnabled: state
// .availableSlotEntity!
// .slotUserDetailList[0]
// .isSelected,
// ),
// );
// },
// );
},
separatorBuilder: (context, index) {
return 32.verticalSpace;
},
itemCount: state.dummyData!.length,
// state.availableSlotEntity!.slotUserDetailList.length,
),
),
40.verticalSpace,
ColumnWithHeadingTextFieldAndIsmFilledButton(
reasonForCancellationController: candidateNameContoller,
isAvailableOnClickWidget: true,
isCancelledOnClickWidget: false,
onPressed: () {
BlocProvider.of<SlotsTabbarBloc>(context).add(
MarkAsBookedEvent(
candidateName: candidateNameContoller.text,
interviewLevelId: levelId,
techStackId: techStackId,
slotId: state.availableSlotEntity!
.slotUserDetailList[0].slotId,
),
);
context.router.pop();
},
heading:
'${StringConstants.candidateName}${StringConstants.asterisk}',
maxLines: 1,
checkBoxOnChanged: (value) {},
textFieldOnChange: (value) {
BlocProvider.of<SlotsTabbarBloc>(context).add(
CandidateNameChangedEvent(
candidateName: candidateNameContoller.text,
enableButton: state.enableButton,
),
);
},
checkBoxBooleanValue: true,
ismFilledButtonText: StringConstants.markAsBooked,
isIsmButtonValid: state.enableButton,
showCheckBox: showCheckBox,
),
24.verticalSpace,
],
),
);
}
return const SizedBox.shrink();
},
),
).symmetricHorizontalPadding(16);
}
}
2条答案
按热度按时间z31licg01#
我不知道这是否有效,但试试这个:在
SlotsTabbarBloc
块_selectAvailablePanelRadioButtonEvent
函数结束时更改此:对此:
也从
AvailableOnClickWidget
中删除BlocProvider
,并将其添加到MaterialApp
之前的main.dart
,类似于以下内容:gv8xihay2#
添加发射和完美的工作。我不知道为什么