arch-atlas

Best seller list view & Custom scroll view

Presentation (Building the UI)

12:10

Summary

This lesson focuses on building the "Best Seller" list view and integrating it into the home screen layout. The instructor explains the UX flaw of having nested scrollable areas and introduces CustomScrollView with slivers to make the entire screen scroll as a unified view. He demonstrates wrapping standard widgets in a SliverToBoxAdapter and refactors the layout to use SliverFillRemaining to handle the remaining vertical space without heavily penalizing performance.

Key Ideas

  • ListView.builder provides efficient, lazy-loaded list rendering for standard layouts.
  • Nested scroll views (e.g., a scrollable list inside a scrollable column) create confusing and clunky user experiences.
  • CustomScrollView allows multiple scrollable and non-scrollable widgets to scroll together seamlessly on a single screen.
  • SliverToBoxAdapter acts as a bridge, allowing standard box-based widgets (like Column or Padding) to be placed inside a sliver array.
  • shrinkWrap: true forces a ListView to compute its entire height at once, which destroys the performance benefits of lazy loading.
  • NeverScrollableScrollPhysics prevents a nested ListView from intercepting scroll gestures, delegating the scroll action entirely to the parent view.
  • SliverFillRemaining forces its child to fill all the remaining viewport space in a CustomScrollView.

Code Snippets

BestSellerListView with scrolling disabled to delegate to parent CustomScrollViewdart
import 'package:bookly/features/home/presentation/views/widgets/best_seller_list_view_item.dart';
import 'package:flutter/material.dart';

class BestSellerListView extends StatelessWidget {
  const BestSellerListView({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      physics: const NeverScrollableScrollPhysics(),
      padding: EdgeInsets.zero,
      itemCount: 10,
      itemBuilder: (context, index) {
        return const Padding(
          padding: EdgeInsets.symmetric(vertical: 10),
          child: BestSellerListViewItem(),
        );
      },
    );
  }
}
Refactoring HomeViewBody to use CustomScrollView and sliversdart
import 'package:bookly/core/utils/styles.dart';
import 'package:bookly/features/home/presentation/views/widgets/best_seller_list_view.dart';
import 'package:bookly/features/home/presentation/views/widgets/custom_app_bar.dart';
import 'package:bookly/features/home/presentation/views/widgets/featured_list_view.dart';
import 'package:flutter/material.dart';

class HomeViewBody extends StatelessWidget {
  const HomeViewBody({super.key});

  @override
  Widget build(BuildContext context) {
    return const CustomScrollView(
      slivers: [
        SliverToBoxAdapter(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Padding(
                padding: EdgeInsets.symmetric(horizontal: 30),
                child: CustomAppBar(),
              ),
              FeaturedBooksListView(),
              SizedBox(
                height: 50,
              ),
              Padding(
                padding: EdgeInsets.symmetric(horizontal: 30),
                child: Text(
                  'Best Seller',
                  style: Styles.textStyle18,
                ),
              ),
              SizedBox(
                height: 20,
              ),
            ],
          ),
        ),
        SliverFillRemaining(
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 30),
            child: BestSellerListView(),
          ),
        ),
      ],
    );
  }
}

Architecture Insight

Architecture insight

CustomScrollView and slivers compose multiple scrollables — useful when you have heterogeneous content (featured row + best-seller column) but easy to over-use.

CA-wise, scroll behavior is presentation-only; never let a raw scroll position bleed into a Cubit's business state. The exception is when the position is genuinely meaningful — infinite-scroll page index, for example, *is* business state.

Looking ahead — Pagination state in section 5 is the one case where scroll position becomes a Cubit's business.

My Notes

The instructor tackles the classic "nested list" scrolling issue in Flutter. His first instinct—using shrinkWrap: true on the ListView—is a common anti-pattern that he correctly identifies as a performance bottleneck because it forces the list to render all items synchronously.

However, his final solution (SliverFillRemaining wrapping a ListView with NeverScrollableScrollPhysics and *no* shrinkWrap) is flawed. By restricting the ListView to the remaining screen height and disabling its internal scroll, any items that fall below the viewport fold become permanently unreachable.

`[Editor's note]`: The correct, performant way to build a scrollable page containing a list is to use SliverList (or SliverList.builder via SliverChildBuilderDelegate) directly in the CustomScrollView's slivers array. This delegates both layout and scrolling to the sliver protocol natively, preserving lazy loading without viewport restrictions.