Sliver Widgets with Scrolling

Jun's Coding Journey·2023년 9월 4일
0

[Learn] Flutter

목록 보기
12/22

Custom Scroll View


CustomScrollView widget is a versatile scrollable container that can host multiple "sliver" widgets. Slivers are portions of a scrollable area that can change as the user scrolls, allowing for complex custom scroll effects.

The CustomScrollView is highly customizable and can combine different types of scrollable lists and layouts into a unified scrollable area.

CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      expandedHeight: 150.0,
      floating: false,
      pinned: true,
      flexibleSpace: FlexibleSpaceBar(
        title: Text('My Sliver App Bar'),
      ),
    ),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return ListTile(
            title: Text('Item $index'),
          );
        },
        childCount: 100,
      ),
    ),
  ],
)

 

Sliver App Bar


SliverAppBar

SliverAppBar widget is a specialized app bar that integrates with a CustomScrollView to produce various scrolling effects. It's a part of the sliver family of widgets, which are used to achieve custom scrollable layouts and effects.

CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      expandedHeight: 200.0,
      floating: false,
      pinned: true,
      flexibleSpace: FlexibleSpaceBar(
        title: Text('Sliver App Bar Example'),
        background: Image.network(
          'https://example.com/image.jpg',
          fit: BoxFit.cover,
        ),
      ),
    ),
    // ... other slivers like SliverList or SliverGrid
  ],
)

 

FlexibleSpaceBar

FlexibleSpaceBar widget is used within a SliverAppBar to create effects that change based on the scroll position. It's a flexible space that can expand and collapse, allowing you to create visually appealing effects, like a background image that fades out or a title that transitions in size or position as the user scrolls.

SliverAppBar(
  expandedHeight: 250.0,
  pinned: true,
  flexibleSpace: FlexibleSpaceBar(
    title: Text('Flutter Dev'),
    background: Image.network(
      'https://example.com/flutter-image.jpg',
      fit: BoxFit.cover,
    ),
    collapseMode: CollapseMode.parallax,
  ),
)

 

Sliver Fixed Extent List


SliverFixedExtentList is a sliver that displays multiple box children with the same main axis extent in a linear array. It's essentially a list of items in a CustomScrollView where each item has a fixed extent or size.

SliverFixedExtentList is a more efficient alternative to SliverList when the items have a fixed size because it allows Flutter to perform some optimization knowing that the size of each item is the same.

CustomScrollView(
  slivers: <Widget>[
    SliverFixedExtentList(
      itemExtent: 50.0, // Each item will be 50 pixels in height
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return ListTile(
            title: Text('Item $index'),
          );
        },
        childCount: 100, // Let's assume we have 100 items
      ),
    ),
  ],
)

 

Sliver Grid


SliverGrid widget is a sliver that displays its children in a two-dimensional grid. It is to CustomScrollView what GridView is to a regular scrollable view. Just as you use SliverList for a list of items inside a CustomScrollView, you use SliverGrid to display a grid of items inside a CustomScrollView.

SliverGrid is especially handy when you're working with scrollable areas that contain a mix of different layout structures, such as a grid of items followed by a list of items, and maybe some other custom scroll effects, all under a single scrollable view.


CustomScrollView(
  slivers: <Widget>[
    SliverGrid(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3, // 3 items in cross axis (horizontal direction for a vertical grid)
        mainAxisSpacing: 10.0, // Spacing between items on the vertical axis
        crossAxisSpacing: 10.0, // Spacing between items on the horizontal axis
      ),
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return Container(
            color: Colors.teal[100 * (index % 9)],
            child: Center(child: Text('Grid Item $index')),
          );
        },
        childCount: 50, // Let's assume we have 50 items
      ),
    ),
  ],
)

 

Sliver Persistent Header


SliverPersistentHeader is a sliver widget that displays a header which can remain pinned (sticky) or can scroll off-screen with parts of the sliver scrolling content. It is often used in conjunction with a CustomScrollView to create effects where a header is initially displayed and then either shrinks, expands, or gets pinned as the user scrolls.

The SliverPersistentHeader is typically used for UI patterns like a collapsing toolbar.

CustomScrollView(
  slivers: <Widget>[
    SliverPersistentHeader(
      delegate: _SliverAppBarDelegate(
        minHeight: 60.0,
        maxHeight: 200.0,
        child: Container(
          color: Colors.teal,
          child: Center(child: Text('My Header')),
        ),
      ),
      pinned: true,
    ),
    // ... other slivers (like SliverList or SliverGrid) go here
  ],
)

// The custom delegate
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  final double minHeight;
  final double maxHeight;
  final Widget child;

  _SliverAppBarDelegate({
    required this.minHeight,
    required this.maxHeight,
    required this.child,
  });

  
  double get minExtent => minHeight;
  
  
  double get maxExtent => maxHeight;

  
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return SizedBox.expand(child: child);
  }

  
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
           minHeight != oldDelegate.minHeight ||
           child != oldDelegate.child;
  }
}

 

Sliver To Box Adapter


SliverToBoxAdapter widget is a handy bridge that allows you to use regular box widgets (like Container, Column, Row, etc.) within a CustomScrollView, which typically requires sliver-based widgets. This widget essentially adapts a normal box widget into a sliver so that it can be placed inside sliver-based scroll views.

To clarify further, CustomScrollView expects sliver widgets (SliverList, SliverGrid, SliverPersistentHeader, etc.). There are times when you need to add a typical box widget, like a single Container or a Text widget, within a CustomScrollView without converting the whole widget to a sliver. This is where SliverToBoxAdapter comes in handy.

CustomScrollView(
  slivers: [
    SliverAppBar(
      title: Text('Sliver AppBar'),
      expandedHeight: 200.0,
      flexibleSpace: FlexibleSpaceBar(
        background: Image.network(
          'https://example.com/image.jpg',
          fit: BoxFit.cover,
        ),
      ),
    ),
    SliverToBoxAdapter(
      child: Container(
        height: 200.0,
        color: Colors.red,
        child: Center(child: Text('This is a regular box widget!')),
      ),
    ),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return ListTile(title: Text('Item $index'));
        },
        childCount: 50,
      ),
    ),
  ],
)

 

Nested Scroll View


NestedScrollView widget is designed to support scrollable content both inside and outside a persistent header. It's particularly useful when you want to create an effect similar to the collapsing app bars you see in many modern applications. The most common use case for NestedScrollView is in combination with the SliverAppBar and a body content like ListView or CustomScrollView.

The main purpose of the NestedScrollView is to ensure that scroll events are properly propagated to child widgets, allowing multiple scrollable areas to work together in a coherent manner.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'NestedScrollView Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: NestedScrollView(
        headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
          return <Widget>[
            SliverAppBar(
              expandedHeight: 200.0,
              floating: false,
              pinned: true,
              flexibleSpace: FlexibleSpaceBar(
                title: Text("NestedScrollView Example"),
                background: Image.network(
                  'https://example.com/path_to_image.jpg',
                  fit: BoxFit.cover,
                ),
              ),
            )
          ];
        },
        body: ListView.builder(
          itemCount: 100,
          itemBuilder: (BuildContext context, int index) {
            return ListTile(
              title: Text('Item $index'),
            );
          },
        ),
      ),
    );
  }
}

profile
Greatness From Small Beginnings

0개의 댓글