skip to Main Content

I’ve make a about us page in my flutter application where terms,policy & other sections are listed and on click of them I store that index in some variable & I want to open its description below section name.

I successfully done it by using valuenotifier but now I want to convert in into Bloc.

Below are my files,

AboutUsState.dart

    import 'package:equatable/equatable.dart';
    import 'package:flutter/material.dart';
    import '../../../Model/ModelInformation.dart';
    
    @immutable
    abstract class AboutUsState extends Equatable {}
    
    class AboutUsLoadingState extends AboutUsState {
      @override
      List<Object?> get props => [];
    }
    
    class AboutUsLoadedState extends AboutUsState {
    
      final ModelInformation modelInformation;
        AboutUsLoadedState(this.modelInformation);
      @override
      List<Object?> get props => [modelInformation];
    }
    
    class AboutUsErrorState extends AboutUsState {
    
      final String error;
      AboutUsErrorState(this.error);
      @override
      List<Object?> get props => [error];
    
    }

AboutUsEvent.dart

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

@immutable
abstract class AboutUsEvent extends Equatable {
  const AboutUsEvent();
}

class LoadAboutUsEvent extends AboutUsEvent {
  @override
  List<Object?> get props => [];
}

class UpdateSelectedViewEvent extends AboutUsEvent {

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

AboutUsBloc.dart

import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../Model/ModelInformation.dart';
import 'AboutUsEvent.dart';
import 'AboutUsState.dart';
import 'Repository.dart';

class AboutUsBloc extends Bloc<AboutUsEvent,AboutUsState> {

  final Repository repository;
    int selectedView = -1;

  AboutUsBloc(this.repository,this.selectedView) : super(AboutUsLoadingState()) {

    on<LoadAboutUsEvent>((event, emit) async {

        emit(AboutUsLoadingState());

        try {
          var dict = await repository.getAboutUs();
          final ModelInformation modelInformation = ModelInformation.fromJson(dict["mainResponse"]);

          emit(AboutUsLoadedState(modelInformation));
        } catch (e) {
          emit(AboutUsErrorState(e.toString()));
        }

    }
    );

  }
}

Repository.dart

import '../../../Services/ServiceManager.dart';
import '../../../Util/Constant.dart';

class Repository {

  Future getAboutUs() async {

   return await ServiceManager.callWebservice(
        varMethodType: enumMethodType.POST,
        strSuffixPath: ConstantApi.keyGetAboutUs,
        dictParameters: {},
        dictHeaders: {},
        arrayUploadFile: []
    );
  }

}

AboutUs.dart

import 'package:flutter_bloc/flutter_bloc.dart';
import '../../Model/ModelInformation.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../Util/Constant.dart';
import 'AboutUs/AboutUsBloc.dart';
import 'AboutUs/AboutUsEvent.dart';
import 'AboutUs/AboutUsState.dart';
import 'AboutUs/Repository.dart';

class ClassAboutUs extends StatefulWidget {
  @override
  stateClassAboutUs createState() => stateClassAboutUs();
}

class stateClassAboutUs extends State<ClassAboutUs> {

  final AboutUsBloc aboutUsBloc = AboutUsBloc(Repository(),-1);

  @override
  void initState() {
    super.initState();
    aboutUsBloc.add(LoadAboutUsEvent());
  }

  @override
  Widget build(BuildContext context) {

    return

      WillPopScope(
        onWillPop: ()  async{
          Navigator.pop(context);
          return true;
        },

        child: new Scaffold(
          backgroundColor: Theme.of(context).colorScheme.background,

          appBar: AppBar(
            elevation: 0.5,
            backgroundColor: Theme.of(context).colorScheme.background,
            titleSpacing: 0,
            centerTitle: false,
            leading: BackButton(
              color: Theme.of(context).colorScheme.onBackground.withOpacity(0.87),
              onPressed: (){
                Navigator.pop(context);
              },
            ),
            title: Text("About us",

              style: TextStyle(
                color: Theme.of(context).colorScheme.onBackground.withOpacity(0.87),
                fontFamily: ConstantFont.keyPrimaryFont,
                fontSize: 15,
                fontWeight: FontWeight.w400,
              ),
            ),
          ),
          body:
          BlocProvider(
              create: (_) => aboutUsBloc,

            child: BlocBuilder<AboutUsBloc, AboutUsState>(

              builder: (context, state) {
                if (state is AboutUsLoadingState) {
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                }
                if (state is AboutUsErrorState) {
                  return const Center(child:  Text("Error"));
                }
                if (state is AboutUsLoadedState) {

                  ModelInformation modelInformation = state.modelInformation;
                  return ListView.builder(
                    padding: EdgeInsets.fromLTRB(0, 0, 0, 10),
                    itemCount: modelInformation.mainmenu!.informationPages!.length,
                    itemBuilder: (context, index) {

                        return

                        aboutUsBloc.selectedView == index ?
                        Container(
                            color: Theme.of(context).colorScheme.primary.withOpacity(0.10),
                            child: Column(

                              crossAxisAlignment: CrossAxisAlignment.start,

                              children: [

                                InkWell(
                                  onTap: (){
                                    aboutUsBloc.selectedView = aboutUsBloc.selectedView== index ? -1 : index;

                                  },
                                  child:
                                  Padding(
                                      padding: const EdgeInsets.all(10),
                                      child: Row(
                                        children: [

                                          Expanded(
                                            child: Text("${modelInformation.mainmenu!.informationPages![index].headingTitle}",style: ConstantTextStyle.h2.copyWith(fontWeight: FontWeight.w600,color: Theme.of(context).colorScheme.primary)),
                                          ),
                                          Padding(
                                            padding: EdgeInsets.only(left: 5,top: 5,bottom: 5),
                                            child: Icon(Icons.keyboard_arrow_up_rounded,size: 15,color: Theme.of(context).colorScheme.onBackground.withOpacity(0.60),),
                                          ),

                                        ],
                                      )
                                  ),),
                                Padding(
                                  padding: const EdgeInsets.only(left: 10,right: 10,),
                                  child: Text("${modelInformation.mainmenu!.informationPages![index].description}",style: ConstantTextStyle.h3.copyWith(color: Theme.of(context).colorScheme.onBackground.withOpacity(0.87)),
                                    textAlign: TextAlign.justify,
                                  ),
                                ),


                              ],
                            )
                        ) :

                         Column(

                          crossAxisAlignment: CrossAxisAlignment.start,

                          children: [

                            InkWell(
                              onTap: (){
                                  aboutUsBloc.selectedView = aboutUsBloc.selectedView == index ? -1 : index;
                                aboutUsBloc.add(UpdateSelectedViewEvent());
                              },
                              child:
                              Padding(
                                  padding: const EdgeInsets.all(10),
                                  child: Row(
                                    children: [

                                      Expanded(
                                        child: Text("${modelInformation.mainmenu!.informationPages![index].headingTitle}",style: ConstantTextStyle.h2.copyWith(fontWeight: FontWeight.w600,color: Theme.of(context).colorScheme.primary)),
                                      ),
                                      Padding(
                                        padding: EdgeInsets.only(left: 5,top: 5,bottom: 5),
                                        child: Icon(Icons.keyboard_arrow_down_rounded,size: 15,color: Theme.of(context).colorScheme.onBackground.withOpacity(0.60),),
                                      ),

                                    ],
                                  )
                              ),),
                            Divider(height: 1,color: Theme.of(context).colorScheme.onBackground.withOpacity(0.37),),

                          ],
                        );
                    },
                  );
                }

                return Container();
              },
            ),
          )

        ),
      );
  }

}

I want to update listview single block based on selectedView value changes

2

Answers


  1. Create one more event for updating selection:

    class UpdateSelectedEvent extends AboutUsEvent {
      final int selectedView;
      final ModelInformation modelInformation;
    
      UpdateSelectedEvent(this.selectedView, this.modelInformation);
    
      @override
      List<Object?> get props => [selectedView, modelInformation];
    }
    

    add this event to your bloc:

    on<UpdateSelectedEvent>((event, emit) {
        selectedView = event.selectedView;
        emit(AboutUsLoadedState(event.modelInformation));
      });
    

    and add the update event on onTap:

    onTap: () => aboutUsBloc.add(UpdateSelectedEvent(index,modelInformation)),
    
    Login or Signup to reply.
  2. You shall NOT have your bloc object store state data, such as "selectedView". Having state variables directly within BLoC objects can lead to tightly coupled components and difficulties in managing state changes. By separating state into dedicated state classes, you achieve better encapsulation and isolation of concerns.

        @immutable
        class AboutUsLoadedState extends AboutUsState {
        
          final ModelInformation modelInformation;
    
          // Index of the selected view, if any.
          final int? selectedView;
    
          const AboutUsLoadedState(this.modelInformation, [this.selectedView]);
    
          @override
          List<Object?> get props => [modelInformation, selectedView];
        }
    

    Then define the event and event-handler which will be used to update the selection.

    class SelectViewEvent extends AboutUsEvent {
      final int selectedView;
    
      SelectedViewEvent (this.selectedView);
    
      @override
      List<Object?> get props => [selectedView];
    }
    
    on<UpdateSelectedEvent>((event, emit) {
          if (state is AboutUsLoadedState) {
             emit(AboutUsLoadedState(state.modelInformation, event.selectedView));
          } else {
            // TODO: Handle other cases
          }
        });
    

    And add in your widget trigger that event on tap.

    onTap: () => aboutUsBloc.add(SelectViewEvent(index)),
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search