SliverAutoScrollTag
Opened this issue · 4 comments
I need another instance of the AutoScrollTag
be SliverAutoScrollTag
so i can use it inside CustomScrollView.
Please note that my itemBuilder
is a SliverGrid
and i want to wrap it with a SliverAutoScrollTag
.
Note that SliverToBoxAdapter
won't work here.
Hi @AlaaEldeenYsr
Any simple reproducible code example is helpful : ) Can you provide the it?
My layout is kind of complicated nested scroll physics which make every item of my list is a SliverGrid
and to wrap it with AutoScrollTag
it throws an exception as it's a RenderBox and not a sliver, So we need the SliverAutoScrollTag
copy of the widget.
The every item of my list annotated in below with // TODO: Scroll To Index
@jerrywell
@override
Widget build(BuildContext context) {
final controller = context.read<CategoryCubit>();
return Scaffold(
appBar: AppBar(
forceMaterialTransparency: true,
title: ReactiveValueListenableBuilder(
formControl: controller.selectedCategoryId,
builder: (context, control, child) {
final selectedCategory = controller.categories.data?.firstWhere(
(element) => element.id == control.value,
orElse: () => controller.categories.data!.first,
);
return Text(selectedCategory?.title ?? '');
},
),
actions: [
IconButton(
onPressed: () {
context.replace('/search');
},
icon: AppIcon(
icon: Assets.icons.search.path,
size: 20.sp,
),
),
],
),
body: EntityBuilder(
entity: controller.categories,
pendingBuilder: (context) => const AppInPageLoader(),
rejectedBuilder: (context, error) => ErrorModelWidget(error: error, onRefresh: controller.refresh),
fulfilledBuilder: (context, data) => CustomScrollView(
slivers: [
SliverFloatingHeader(
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: Observer(
builder: (context) => Column(children: [
ReactiveFormField<String, int>(
formControl: controller.selectedCategoryId,
valueAccessor: CategoryValueAccessor(list: data),
builder: (field) => DefaultTabController(
length: data?.length ?? 0,
initialIndex: field.value ?? 0,
child: TabBar(
tabAlignment: TabAlignment.start,
labelPadding: EdgeInsets.symmetric(
horizontal: AppSpaces.horizontalPadding8,
),
onTap: (value) => field.didChange(value),
// dividerHeight: 2.h,
dividerColor: AppColors.grey7,
labelStyle: Theme.of(context).tabBarTheme.labelStyle?.copyWith(
fontSize: AppFontSizes.s12,
fontWeight: FontWeight.w700,
),
unselectedLabelStyle: Theme.of(context).tabBarTheme.unselectedLabelStyle?.copyWith(
color: AppColors.grey6,
fontSize: AppFontSizes.s12,
fontWeight: FontWeight.w700,
),
isScrollable: true,
tabs: [
...?data?.map((e) => Tab(text: e.title)),
],
),
),
),
if (controller.category.fulfilled)
Column(children: [
DefaultTabController(
length: controller.category.data?.children?.length ?? 0,
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
alignment: AlignmentDirectional.topStart,
child: ButtonsTabBar(
buttonMargin: EdgeInsets.all(AppSpaces.borderRadius8),
unselectedBackgroundColor: AppColors.grey5,
contentPadding: EdgeInsets.symmetric(
horizontal: AppSpaces.horizontalPadding20,
vertical: 5.5.h,
),
radius: 100,
labelStyle: Theme.of(context).tabBarTheme.labelStyle?.copyWith(
color: Theme.of(context).scaffoldBackgroundColor,
fontWeight: FontWeight.w500,
fontSize: AppFontSizes.s14,
),
unselectedLabelStyle: Theme.of(context).tabBarTheme.unselectedLabelStyle?.copyWith(
color: AppColors.secondary,
fontWeight: FontWeight.w300,
),
tabs: [
...?controller.category.data?.children?.map((e) => Tab(text: e.title)),
],
),
),
),
Divider(
color: AppColors.grey7,
height: 0,
thickness: 2.h,
)
]),
]),
),
),
),
CupertinoSliverRefreshControl(
onRefresh: () async => controller.refresh(),
),
EntityBuilder(
entity: controller.category,
rejectedBuilder: (context, error) => SliverFillRemaining(
hasScrollBody: false,
child: ErrorModelWidget(error: error, onRefresh: controller.refresh),
),
pendingBuilder: (context) => const SliverFillRemaining(
hasScrollBody: false,
child: AppInPageLoader(),
),
pristineBuilder: (context) => const SliverToBoxAdapter(),
fulfilledBuilder: (context, data) => MultiSliver(pushPinnedChildren: true, children: [
...?data.children?.mapIndexed(
// TODO: Scroll To Index
(i, e) => SliverPadding(
padding: EdgeInsets.only(bottom: AppSpaces.verticalPadding16).add(
EdgeInsets.symmetric(
horizontal: AppSpaces.horizontalPadding16,
vertical: AppSpaces.verticalPadding12,
),
),
sliver: MultiSliver(children: [
SliverToBoxAdapter(
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(
e.title ?? '',
style: TextStyle(
fontSize: AppFontSizes.s16,
fontWeight: FontWeight.w600,
),
),
SizedBox(
height: AppSpaces.verticalPadding16,
)
]),
),
SliverGrid.builder(
itemCount: data.children?[i].products?.length ?? 0,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisExtent: 238.h,
crossAxisCount: 3,
mainAxisSpacing: AppSpaces.horizontalPadding8,
crossAxisSpacing: AppSpaces.verticalPadding8,
),
itemBuilder: (context, j) {
final item = e.products![j];
return ModelProductCard(
item: item,
onCartChange: (value) {
final controller = context.read<ProductCardActionsCubit>();
controller.handleCartChange(
hasVariants: item.hasVariants,
cartItemId: item.cartItem?.id,
body: PutCartItemRequestModel(
productId: item.id,
price: item.inventory?.price,
quantity: value,
offerId: item.offer?.id,
),
);
},
onHeartClick: () {
final controller = context.read<ProductCardActionsCubit>();
controller.toggleProductFavourites(
productId: item.id,
);
},
);
},
)
]),
),
),
]),
),
],
),
),
bottomNavigationBar: FreeDeliveryBottomBar(
hasProductsCount: true,
elevatedButton: ElevatedButton(
onPressed: () => context.go("/cart"),
child: const Text("فتح السلة"),
),
),
);
}
Any updates on this? I am in the same boat and really want this feature.
Hi @AlaaEldeenYsr, The attached example is unable to build and debug, so i can't check it.
However, I have write the code snippet for CustomScrollView
with both SliverList
and SliverGrid
as following.
You can replace the body of example with follow code snippets:
body: CustomScrollView(
scrollDirection: scrollDirection,
controller: controller,
slivers: [
SliverGrid(
delegate: SliverChildListDelegate(
randomList.sublist(0, 10).map<Widget>((data) {
return Padding(
padding: EdgeInsets.all(8),
child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),
);
}).toList(),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisExtent: 100,
crossAxisCount: 3,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
),
SliverList(
delegate: SliverChildListDelegate(
randomList.sublist(10, 100).map<Widget>((data) {
return Padding(
padding: EdgeInsets.all(8),
child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),
);
}).toList(),
),
)
],
),
@lockieRichter the code snippet should be helpful enough to demo how it works with Slivers.