So I have this RefreshIndicator()
which requires RefreshController
and a child which is SinglechildScrollView()
and I need to add scrollController in it to be able to manipulate the showing and hiding of a widget when a certain position in the screen is met. As below.
...
ScrollController scrollController = ScrollController();
...
bool showFloatingCategories = false;
...
@override
void initState() {
scrollController.addListener(_scrollListener);
super.initState();
}
...
void _scrollListener() {
// Get the current scroll position
double scrollPosition = scrollController.position.pixels;
// Check if the scroll position is greater than or equal to 200
if (scrollPosition >= 200) {
// Scroll position is at or beyond 200, you can show/hide widgets here
setState(() {
showFloatingCategories = true; // Set your showFloatingCategories flag accordingly
});
} else {
// Scroll position is less than 200
print(scrollPosition);
setState(() {
showFloatingCategories = false; // Set your showFloatingCategories flag accordingly
});
}
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Stack(
children: [
Scaffold(
backgroundColor: AppTaste.whiteThemeColor,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: AppTaste.whiteThemeColor,
elevation: 0.4,
centerTitle: true,
title: GestureDetector(
onTap: () async {
},
child: Image.asset('assets/images/airduka_logo_blue.png', height: 35.0,)),
),
body: SmartRefresher(
controller: refreshController,
physics: const BouncingScrollPhysics(),
onRefresh: () async {
final result = await getAllProducts(isRefresh: true);
//final categoriyResult = await get
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await getAllProducts();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
enablePullUp: true,
child: SingleChildScrollView(
controller: scrollController,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(
height: 15.0,
),
SmallTextWidget(
text: categoryName,
color: AppTaste.secondaryThemeColor,
size: 18.0,
fontWeight: FontWeight.w600,
),
const SizedBox(
height: 10.0,
),
inventoryList.length >= 1
? GridView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: inventoryList.length,
shrinkWrap: true,
scrollDirection: Axis.vertical,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 1.0,
childAspectRatio: 0.8,
mainAxisSpacing: 5.0),
itemBuilder: (context, int index) {
var inventoryProduct = inventoryList[index];
final _isSelected = _selectedIndex.contains(inventoryProduct.id);
return ProductCardWidget(
index,
inventoryProduct
.product!.featuredImage!.digitalOceanUrl
.toString(),
//productCategorySnapshot.data[index]['company']['name'].toString(),
inventoryProduct.product!.title.toString(),
'KES${double.parse(inventoryProduct.sellingPrice.toString()).toStringAsFixed(0)}'
.replaceAllMapped(reg, mathFunc),
inventoryProduct.discount == null
? ''
: '${double.parse((inventoryProduct.discount! / inventoryProduct.cost! * 100).toString()).toStringAsFixed(0)}'
.replaceAllMapped(reg, mathFunc),
'KES${double.parse(inventoryProduct.cost.toString()).toStringAsFixed(0)}'
.replaceAllMapped(reg, mathFunc), () {
Navigator.push(
context,
PageTransition(
child: ProductInfoScreen(
user: widget.user,
discPrice:
inventoryProduct.cost.toString(),
userId: widget.user.id.toString(),
id: inventoryProduct.productId.toString(),
shopName: inventoryProduct.company!.name
.toString(),
productPrice: inventoryProduct
.sellingPrice
.toString(),
productTitle: inventoryProduct
.product!.title
.toString(),
productInfo: inventoryProduct.description
.toString(),
productImage: inventoryProduct.product!
.featuredImage!.digitalOceanUrl
.toString(),
inventoryId:
inventoryProduct.id.toString(),
shopId: inventoryProduct.merchantId
.toString(),
),
type: PageTransitionType.rightToLeft));
},
() {
ShopService()
.addToWishlist(
inventoryProduct.merchantId.toString(),
widget.user.id.toString(),
inventoryProduct.productId.toString(),
inventoryProduct.id.toString(),
)
.then((value) {
setState(() {});
if (value['error'] && value['data'].isNotEmpty) {
Flushbar(
margin: const EdgeInsets.only(
bottom: 12.0, left: 12.0, right: 12.0),
borderRadius: BorderRadius.circular(10.0),
message: value['message'],
duration: const Duration(seconds: 2),
).show(context);
} else if (value['error']) {
Flushbar(
margin: const EdgeInsets.only(
bottom: 12.0, left: 12.0, right: 12.0),
borderRadius: BorderRadius.circular(10.0),
message: 'Please try again later!!',
duration: const Duration(seconds: 2),
).show(context);
} else {
setState(() {});
Flushbar(
margin: const EdgeInsets.only(
bottom: 12.0, left: 12.0, right: 12.0),
borderRadius: BorderRadius.circular(10.0),
message: 'Added to wishlist!',
duration: const Duration(seconds: 2),
).show(context);
}
});
},
selectedForYouIndex,
isReportForYouClicked,
(){
setState(() {
selectedForYouIndex = index;
isReportForYouClicked = true;
});
},
(){
setState(() {
isReportForYouClicked =
false;
});
},
(){
showModalBottomSheet(
isDismissible: true,
enableDrag: true,
isScrollControlled: true,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))),
context: context,
builder: (context) {
return SafeArea(
child: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: SizedBox(
height: size.height - 80.0,
child: SingleChildScrollView(
child: Column(
children: [
Row(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(height: 5.5, width: 100.0, decoration: BoxDecoration(color: AppColors.fontHeaderColor, borderRadius: BorderRadius.circular(10.0))),
Container(),
]),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const SmallTextWidget(
text: "Report",
fontWeight: FontWeight.w700,
size: 16.0,
),
InkWell(
onTap: () {
Navigator.of(context).pop();
},
child: const Image(
image: AssetImage("assets/icons/cancel.png"),
height: 26,
),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: SmallTextWidget(text: "Your report is anonymous", fontWeight: FontWeight.w700, size: 10.0, color: AppColors.fontHeaderColor.withOpacity(0.6)),
),
const SizedBox(
height: 5.0,
),
FutureBuilder(
future: fetchFlags,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Column(
children: [
ListView.builder(
itemCount: snapshot.data.length,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Column(children: [
InkWell(
onTap: () {
setState(() {
///Remove product here
Flushbar(
title: 'Report',
message: 'Report submitted, you\'ll see few of this',
duration: const Duration(seconds: 2),
).show(context).then((value) => Navigator.of(context).pop());
});
},
child: ListTile(
title: Text(snapshot.data[index]['flag'].toString()),
),
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 14.0),
child: Divider(
height: 2.0,
color: AppColors.fontHeaderColor,
),
)
]);
}),
],
);
} else {
return Container();
}
})
],
),
),
),
),
);
}).then((value) {
setState(() {
inventoryList.removeWhere((element) => element.id == inventoryProduct.id);
isReportForYouClicked = false;
});
});
},
(){
setState(
() {
///Remove product here
inventoryList.removeWhere((element) =>
element.id == inventoryProduct.id);
isReportForYouClicked = false;
Flushbar(
title: 'Got it!',
message: 'You\'ll see few of this',
duration:
const Duration(seconds: 2),
).show(
context);
});
},
(){
setState(() {
selectedForYouIndex = index;
isReportForYouClicked =
!isReportForYouClicked;
});
},
_isSelected ? Colors.redAccent : AppTaste.whiteThemeColor,
_isSelected ? Icons.favorite_rounded : Icons.favorite_outline_rounded
);
})
: VerticalShimmerWidget(context),
const SizedBox(
height: 20.0,
),
],
),
),
),
),
),
showFloatingCategories ?
Positioned(
top: kToolbarHeight,
child: SafeArea(
child: Container(
height: 45.0,
width: size.width,
decoration: BoxDecoration(
color: Colors.white,
border: Border(
bottom: BorderSide(
color: Colors.grey.withOpacity(0.6)
)
)
),
child: FutureBuilder<List<AllCategoriesModel>>(
future: topCategoriesFuture,
builder: (context, AsyncSnapshot<List<AllCategoriesModel>> categorySnapshot) {
if (categorySnapshot.hasData) {
if(categorySnapshot.data!.isNotEmpty){
return ListView.builder(
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: categorySnapshot.data?.length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index){
return Padding(
padding: const EdgeInsets.only(right: 5.0, bottom: 5.0, left: 10.0),
child: InkWell(
onTap: () {
setState(() {
categoryName = categorySnapshot
.data![index].name
.toString();
});
},
child: Container(
//width: 100.0,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(5.0),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Center(
child: SmallTextWidget(
maxLine: 1,
text: categorySnapshot
.data![index].name
.toString(),
color: AppTaste.secondaryThemeColor,
size: 14,
),
),
),
),
),
);
});
}else{
return const Center();
}
} else {
return Padding(
padding: const EdgeInsets.only(right: 8.0),
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: List.generate(5, (index) => CategoryShimmerWidget(context)),
),
);
}
})
)
)) : const SizedBox(),
],
);
}
But the scrollController does not get attached/not working and when I do log print I get that it stays at 0.0. What could I do for this to work?