Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only scrolls with SliverFillRemaining and takes to much space at the end #74

Closed
luissalgadofreire opened this issue May 10, 2022 · 2 comments

Comments

@luissalgadofreire
Copy link

luissalgadofreire commented May 10, 2022

I have working code with SliverStickyHeader but need to add SliverFillRemaining at the end for the list of slivers to scroll. Scrolling doesn't work without it. The problem is it takes too much space (the whole viewport height) at the end.

Is there anything I'm doing wrong here?

This is the relevant portion of code:

return CustomScrollView(
      controller: scrollController,
      slivers: <Widget>[
        ...cards
            .where((c) => c.show)
            .map((c) => SliverStickyHeader(
              header: _buildSubHeader(
                  context: context,
                  text: c.text,
                  iconData: c.iconData,
                  color: c.color
              ),
              sliver: SliverFixedExtentList(
                  itemExtent: 73,
                  delegate: SliverChildBuilderDelegate((context, index) => TransactionTileWidget(
                        transaction: c.transactions[index],
                        onTransactionPressed: (e) => print("Hello")
                    ),
                    childCount: c.transactions.length,
                  )
              ),
            )
        ),
        SliverFillRemaining(
          child: Container()
        ),
      ],
    );
Greater code context below (click to expand) ▼:
class TransactionsView extends HookWidget {
  const TransactionsView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final scrollController = useScrollController();

    useEffect(() {
      scrollController.addListener(() => _onScrollListener(context, scrollController));
      return scrollController.dispose;
    }, [scrollController]);

    return _buildBody(context, scrollController);
  }

  Widget _buildBody(BuildContext context, ScrollController scrollController) {
    return BlocBuilder<TransactionCubit, TransactionState>(
        builder: (_, state) {
          if (state is TransactionLoading) {
            return const Center(child: CupertinoActivityIndicator());
          }
          if (state is TransactionDone) {
            return _buildTransactions(context, scrollController, state);
          }
          return const SizedBox();
        },
      );
  }

  Widget _buildTransactions(BuildContext context, ScrollController scrollController, TransactionDone state) {

    final cards = <SliverStickyHeaderTemplate>[
      SliverStickyHeaderTemplate(
          text: 'Pins',
          iconData: MoneyIcons.pin_filled,
          color: AppTheme.current.styles.color.systemFillColorCautionBrush,
          transactions: state.pinnedTransactions,
          show: getIt<MainUserSettings>().smartInboxShowPinsCard
              && (state.pinnedTransactions).length > 0
      ),
      ...
    ];

    return CustomScrollView(
      controller: scrollController,
      slivers: <Widget>[
        ...cards
            .where((c) => c.show)
            .map((c) => SliverStickyHeader(
              header: _buildSubHeader(
                  context: context,
                  text: c.text,
                  iconData: c.iconData,
                  color: c.color
              ),
              sliver: SliverFixedExtentList(
                  itemExtent: 73,
                  delegate: SliverChildBuilderDelegate((context, index) => TransactionTileWidget(
                        transaction: c.transactions[index],
                        onTransactionPressed: (e) => print("Hello")
                    ),
                    childCount: c.transactions.length,
                  )
              ),
            )
        ),
        SliverFillRemaining(
          child: Container()
        ),
      ],
    );
  }

  void _onScrollListener(BuildContext context, ScrollController scrollController) {
    final maxScroll = scrollController.position.maxScrollExtent;
    final currentScroll = scrollController.position.pixels;
    final transactionCubit = BlocProvider.of<TransactionCubit>(context);
    final state = transactionCubit.cubitProcessState;

    if (currentScroll == maxScroll && state == CubitProcessState.idle) {
      transactionCubit.findAllTransactions();
    }
  }
}
@luissalgadofreire
Copy link
Author

luissalgadofreire commented May 10, 2022

It turns out the initial list was smaller than the viewport and scrolling was not being activated. I ended up:

  • adding a SliverAdapterToBox at the end
  • setting SliverFillRemaining hasScrollBody to false

The above changes forced scrolling while having SliverFillRemaining only fill the space down to the end of the viewport. Everything started working as it should.

Working code with changes commented:

return CustomScrollView(
      controller: scrollController,
      physics: BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
      slivers: <Widget>[
        ...cards
            .where((c) => c.show)
            .map((c) => SliverStickyHeader(
              header: _buildSubHeader(
                  context: context,
                  text: c.text,
                  iconData: c.iconData,
                  color: c.color
              ),
              sliver: SliverFixedExtentList(
                  itemExtent: 73,
                  delegate: SliverChildBuilderDelegate(
                    (context, index) => TransactionTileWidget(
                        transaction: c.transactions[index],
                        onTransactionPressed: (e) => print("Hello")
                    ),
                    childCount: c.transactions.length,
                  )
              ),
            )
          ),
        SliverFillRemaining(
          hasScrollBody: false,               // <--- HERE
          fillOverscroll: true,
          child: Container()
        ),
        SliverToBoxAdapter(                   // <--- HERE
            child: Container(height: 10)      // <--- HERE
        ),                                    // <--- HERE
      ],
    );

@luissalgadofreire
Copy link
Author

Solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant