BlocBuilder中的TextButton在Flutter中默认被禁用

ykejflvf  于 2023-04-13  发布在  Flutter
关注(0)|答案(1)|浏览(119)

我试图通过flutter Bloc库显示一个基本的屏幕,在一个人可以查看他在特定的一天的约会数量,通过点击日历小部件中的特定日期。
下面是上述屏幕的代码

import 'dart:developer';

import 'package:chikitsalaya/doctor/bloc/doctor_appointment_bloc.dart';
import 'package:chikitsalaya/doctor/bloc/doctor_appointment_event.dart';
import 'package:chikitsalaya/doctor/bloc/doctor_appointment_state.dart';
import 'package:chikitsalaya/doctor/doctor_appointment_details_screen.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';

import '../common/common_ui.dart';
import '../payment/appointment_booking_payment.dart';

class DoctorAppointmentScreen extends StatelessWidget {

  const DoctorAppointmentScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (BuildContext context) => DoctorAppointmentBloc(DoctorAppointmentInitial()),
      child: Scaffold(
          backgroundColor: Colors.white,
          appBar: CommonUI(context).commonAppBar(),
          drawer: CommonUI(context).commonDrawer(),
          body: SafeArea(
            minimum: const EdgeInsets.all(16.0),
            child: Column(
              children: <Widget>[
                /// This is the Calendar Picker Widget , where doctor can pick a particular date and see what all appointments are present
                buildCalendarWidget(context),
                /// This is the BlocBuilder Widget for dynamically displaying all the appointments for a particular date picked above
                BlocBuilder<DoctorAppointmentBloc,DoctorAppointmentState>(
                    builder: (context,state){
                      if(state is DoctorAppointmentDatePicked){
                        List<dynamic> currentDayAppointmentDetails = state.appointmentDetails;
                        return buildDailyAppointmentWidget(context,currentDayAppointmentDetails,state.day);
                      }else if(state is DoctorAppointmentInitial){
                        /// This is the initial state , so the date naturally would be the current date
                        context.read<DoctorAppointmentBloc>().add(DoctorAppointmentScreenOnDateChanged(DateTime.now()));
                        /// This is required because BlocBuilder requires a mandatory Widget to be returned back
                        return const CircularProgressIndicator();
                      }else if(state is DoctorAppointmentScreenError){
                        log("Error from Backend "+state.exceptionMessage);
                        return ErrorWidget(state.exceptionMessage);
                      }else if(state is DoctorAppointmentScreenNoAppointmentFound){
                        return Text("No Appointment Found for "+state.pickedDate);
                      }else if(state is DoctorAppointmentDetailsScreenInitial){
                        log("Inside state DoctorAppointmentDetailsScreenInitial");
                        //TODO: User View Resolver for this transition
                        Navigator.push(context, MaterialPageRoute(builder: (context) => DoctorAppointmentDetailsScreen(appointmentId:state.appointmentId)));
                        return const CircularProgressIndicator();
                      }else{
                        return const CircularProgressIndicator();
                      }
                    }
                ),
              ],
            ),
          )
      ),
    );
  }

  Widget buildCalendarWidget(BuildContext context) {
    return BlocBuilder<DoctorAppointmentBloc,DoctorAppointmentState>(
      builder: (context,state) {
        return CalendarDatePicker(
            initialDate: DateTime.now(),
            firstDate: DateTime.now(),
            lastDate: DateTime(2024),
            onDateChanged: (dateTime) {
              log('DateTime picked is '+dateTime.toString());
              context.read<DoctorAppointmentBloc>().add(DoctorAppointmentScreenOnDateChanged(dateTime));
            });
      }
    );
  }

  Card buildDailyAppointmentWidget(BuildContext context,List<dynamic> currentDayAppointmentDetails, String day){
    return Card(
      elevation: 6,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
      child: Column(
        children: <Widget>[
          Text(day),
          Expanded(
            child: GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: (currentDayAppointmentDetails.length>=3) ? 3 : currentDayAppointmentDetails.length
              ),
              itemCount: currentDayAppointmentDetails.length,
              shrinkWrap: true,
              itemBuilder: (context,index) {
                return Padding(
                      padding: const EdgeInsets.only(left: 10.0,top: 40.0,right: 10.0,bottom: 40.0),
                      child: BlocBuilder<DoctorAppointmentBloc,DoctorAppointmentState>(
                        builder: (context,state) {
                          return TextButton(
                            /*style: ElevatedButton.styleFrom(
                              primary: Colors.green,
                              onPrimary: Colors.white,
                              shadowColor: Colors.greenAccent,
                              elevation: 3,
                              shape: RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(32.0)),
                            ),*/
                            onPressed: () {
                              try{
                                log("Pressed button");
                                print("Pressed someting");
                                context.read<DoctorAppointmentBloc>().add(DoctorAppointmentScreenOnPressed(currentDayAppointmentDetails[index]['appointmentId']));
                              }on Exception catch (_,error){
                                log("Error is "+error.toString());
                              }
                            },
                            //label: Text(currentDayAppointmentDetails![index]!['time']!),
                            //backgroundColor: Colors.green,
                            child: Text(currentDayAppointmentDetails![index]!['time']!),
                          );
                        }
                      ),
                    );
              }),
            ),
        ],
      ),
    );
  }

}

下面的代码运行正常,即使是appointmentList项也能在GridView中正常显示。但是在Pressing任何一个约会日期时,“onPressed”函数都不会被调用。它甚至包括“print”和“log”行。

onPressed: () {
                              try{
                                log("Pressed button");
                                print("Pressed someting");
                                context.read<DoctorAppointmentBloc>().add(DoctorAppointmentScreenOnPressed(currentDayAppointmentDetails[index]['appointmentId']));
                              }on Exception catch (_,error){
                                log("Error is "+error.toString());
                              }
                            },

我也试过用“ElevatedButton & FloatingActionButton”代替现有的“TextButton”,但似乎什么都不起作用。而且似乎按钮默认被禁用了。
我真的觉得被困在这里了,任何帮助都将不胜感激。
我还提供了Bloc、BlocState和BlocEvent代码

集团

import 'dart:async';
import 'dart:developer';
import 'package:chikitsalaya/appointment/appointment_service.dart';
import 'package:chikitsalaya/common/user_service.dart';
import 'package:chikitsalaya/doctor/bloc/doctor_appointment_event.dart';
import 'package:chikitsalaya/doctor/bloc/doctor_appointment_state.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:intl/intl.dart';

class DoctorAppointmentBloc extends Bloc<DoctorAppointmentEvent,DoctorAppointmentState>{

  final AppointmentService _appointmentService = AppointmentServiceImpl();
  final UserService _userService = UserServiceImpl();

  DoctorAppointmentBloc(DoctorAppointmentState initialState) : super(initialState){
    on<DoctorAppointmentScreenOnDateChanged>(_onDateChanged);
    on<DoctorAppointmentDetailsScreenOnInit>(_onInitDetailsScreen);
    on<DoctorAppointmentScreenOnPressed>(_onPressed);
  }

  /// OnDateChanged , need to fetch all the monthly appointments from backend
  FutureOr<void> _onDateChanged(event,emit) async{
    DateTime pickedDate = event.dateTime;
    //TODO: Get the month of the pickedDate and pass it as a parameter for fetching data
    String formattedDate = DateFormat('dd-MM-yyyy').format(pickedDate);
    _appointmentService.fetchMonthlyAppointments("doctorId", "month")
        .then((appointmentList) {
          bool found = false;
          for(int i=0;i<appointmentList.length;i++){
            if(appointmentList[i].date==formattedDate){
              found = true;
              String weekDay = DateFormat('EEEE').format(pickedDate);
              emit(DoctorAppointmentDatePicked(appointmentDetails: appointmentList[i].appointments,
                  day: weekDay));
            }
            if(!found){
              log("No appointment found for date "+formattedDate);
              emit(DoctorAppointmentScreenNoAppointmentFound(formattedDate));
            }
          }
        }).onError((error, stackTrace) {
          log("In DoctorAppointmentScreenBloc error "+error.toString());
          log("In DoctorAppointmentScreenBloc stacktrace "+stackTrace.toString());
          emit(DoctorAppointmentScreenError(error.toString()));
        });
  }

  FutureOr<void> _onInitDetailsScreen(event, emit) async{
    String appointmentId = (event as DoctorAppointmentDetailsScreenOnInit).appointmentId;
    _appointmentService.fetchAppointmentDetails(appointmentId)
        .then((appointment) {
          log("Appointment Found for Id "+appointmentId+" "+appointment.toString());
          /// After fetching appointment details , need to fetch Patient details via Patient API
          String patientId = appointment.patientId;
          _userService.fetchPatientDetails(patientId)
              .then((patient) {
                log("Patient details found for Id "+patientId+" "+patient.toString());
                appointment.patientName=patient.patientName;
                appointment.patientAge=patient.patientAge;
                appointment.patientSex=patient.patientSex;
                emit(DoctorAppointmentDetailsScreenSuccess(appointment));
              }).onError((error, stackTrace) {
                log("Failed to fetch Patient details for Id "+patientId+" "+stackTrace.toString());
                emit(DoctorAppointmentDetailsScreenError(error.toString()));
              });
        }).onError((error, stackTrace) {
          log("Failed to fetch Appointment details for Id "+appointmentId+" "+stackTrace.toString());
          emit(DoctorAppointmentDetailsScreenError(error.toString()));
        });
  }

  FutureOr<void> _onPressed(event, emit) async{
    String appointmentId = (event as DoctorAppointmentScreenOnPressed).appointmentId;
    log("Inside AppointmentBloc OnPressed "+appointmentId);
    emit(DoctorAppointmentDetailsScreenInitial(appointmentId));
  }
}

BlocEvent

import 'package:equatable/equatable.dart';

abstract class DoctorAppointmentEvent extends Equatable {
  const DoctorAppointmentEvent();
}

class DoctorAppointmentStarted extends DoctorAppointmentEvent {
  @override
  List<Object?> get props => [];

}

class DoctorAppointmentScreenOnDateChanged extends DoctorAppointmentEvent {
  final DateTime dateTime;
  //TODO: Add Doctor ID as variable here

  const DoctorAppointmentScreenOnDateChanged(this.dateTime);

  @override
  List<Object?> get props => [dateTime];

}

class DoctorAppointmentScreenOnPressed extends DoctorAppointmentEvent {
  final String appointmentId;

  const DoctorAppointmentScreenOnPressed(this.appointmentId);

  @override
  List<Object?> get props => [appointmentId];

}

class DoctorAppointmentDetailsScreenOnInit extends DoctorAppointmentEvent {
  final String appointmentId;

  const DoctorAppointmentDetailsScreenOnInit(this.appointmentId);

  @override
  List<Object?> get props => [];

}

BlocState

import 'package:chikitsalaya/appointment/appointment_model.dart';
import 'package:equatable/equatable.dart';

abstract class DoctorAppointmentState extends Equatable {
  const DoctorAppointmentState();
}

class DoctorAppointmentInitial extends DoctorAppointmentState {

  const DoctorAppointmentInitial();

  @override
  List<Object?> get props => [];
}

class DoctorAppointmentDatePicked extends DoctorAppointmentState {

  final List<dynamic> appointmentDetails;
  final String day;
  const DoctorAppointmentDatePicked({required this.appointmentDetails,required this.day});

  @override
  List<Object?> get props => [appointmentDetails,day];

}

class DoctorAppointmentScreenError extends DoctorAppointmentState {
  final String exceptionMessage;

  const DoctorAppointmentScreenError(this.exceptionMessage);

  @override
  List<Object?> get props => [exceptionMessage];
}

class DoctorAppointmentScreenNoAppointmentFound extends DoctorAppointmentState {
  final String pickedDate;

  const DoctorAppointmentScreenNoAppointmentFound(this.pickedDate);

  @override
  List<Object?> get props => [pickedDate];
}

class DoctorAppointmentDetailsScreenInitial extends DoctorAppointmentState {
  final String appointmentId;

  const DoctorAppointmentDetailsScreenInitial(this.appointmentId);

  @override
  List<Object?> get props => [appointmentId];

}

class DoctorAppointmentDetailsScreenSuccess extends DoctorAppointmentState {
  final Appointment appointment;

  const DoctorAppointmentDetailsScreenSuccess(this.appointment);

  @override
  List<Object?> get props => [appointment];
}

class DoctorAppointmentDetailsScreenError extends DoctorAppointmentState {
  final String exceptionMessage;

  const DoctorAppointmentDetailsScreenError(this.exceptionMessage);

  @override
  List<Object?> get props => [exceptionMessage];
}
yqhsw0fo

yqhsw0fo1#

这个问题与GridView有关。如果您让GridView的itemBuilder返回一个包含所需子部件的InkWell,您将能够在InkWell上添加一个onTap事件来调用您的

context.read<DoctorAppointmentBloc>().add(DoctorAppointmentScreenOnPressed(currentDayAppointmentDetails[index]['appointmentId']));`

相关问题