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
Create one more event for updating selection:
add this event to your bloc:
and add the update event on onTap:
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.
Then define the event and event-handler which will be used to update the selection.
And add in your widget trigger that event on tap.