본문 바로가기
Study

38. 스크롤링 개요: 다양한 스크롤링 방법과 위젯 소개 | Flutter

by 구구 구구 2024. 8. 7.
반응형

로우 폴리곤 스타일, dall-e

 

Flutter에서 스크롤링 개요: 다양한 스크롤링 방법과 위젯 소개

 

01. 서론

1) Flutter에서 스크롤링의 중요성

Flutter는 모바일, 웹, 데스크탑 등 다양한 플랫폼에서 일관된 UI를 제공하는 오픈 소스 UI 프레임워크입니다. 많은 애플리케이션에서 긴 콘텐츠를 다루기 위해 스크롤링이 필수적입니다. 예를 들어, 뉴스 앱은 수많은 기사 목록을 스크롤해야 하고, 소셜 미디어 앱은 사용자 피드를 스크롤해야 합니다. 스크롤링은 사용자 경험을 향상시키고, 많은 양의 데이터를 효율적으로 보여주는 데 중요한 역할을 합니다.

2) 다양한 스크롤링 방법의 필요성

애플리케이션에 따라 스크롤링 방식이 달라질 수 있습니다. 기본적인 수직 및 수평 스크롤링 외에도, 무한 스크롤링, 특수 스크롤링, 중첩 스크롤링 등 다양한 요구사항이 있습니다. 각각의 스크롤링 방법은 특정 상황에 맞게 사용되어야 하며, 이를 통해 앱의 성능과 사용자 경험을 최적화할 수 있습니다.

 

02. 기본 스크롤링

1) SingleChildScrollView 소개

`SingleChildScrollView`는 단일 자식을 스크롤 가능한 뷰로 감싸는 위젯입니다. 콘텐츠가 화면에 맞지 않을 때 사용자가 스크롤하여 전체 콘텐츠를 볼 수 있게 합니다. 주로 텍스트나 이미지와 같은 단일 요소를 스크롤할 때 사용됩니다.


SingleChildScrollView(
  child: Column(
    children: [
      Text('항목 1'),
      Text('항목 2'),
      // 추가 항목
    ],
  ),
);
        

위 코드에서 `SingleChildScrollView`는 `Column`을 감싸고 있으며, 사용자가 스크롤하여 모든 텍스트 항목을 볼 수 있습니다.

2) ListView와 GridView의 기본 사용법

`ListView`와 `GridView`는 복수의 항목을 스크롤하는 데 사용되는 대표적인 위젯입니다. `ListView`는 수직 스크롤링을 지원하며, `GridView`는 격자형 레이아웃으로 스크롤링을 지원합니다.

ListView 예제:


ListView(
  children: [
    ListTile(
      title: Text('항목 1'),
    ),
    ListTile(
      title: Text('항목 2'),
    ),
    // 추가 항목
  ],
);
        

위 코드에서 `ListView`는 여러 개의 `ListTile` 항목을 스크롤할 수 있게 합니다.

GridView 예제:


GridView.count(
  crossAxisCount: 2, // 한 줄에 두 개의 항목
  children: [
    Container(
      color: Colors.red,
      child: Center(child: Text('항목 1')),
    ),
    Container(
      color: Colors.blue,
      child: Center(child: Text('항목 2')),
    ),
    // 추가 항목
  ],
);
        

위 코드에서 `GridView`는 두 개의 열을 가진 격자형 레이아웃으로 항목을 배치하고 스크롤할 수 있게 합니다.

 

03. 무한 스크롤링

1) ListView.builder와 GridView.builder의 개념

`ListView.builder`와 `GridView.builder`는 항목을 동적으로 생성하여 메모리 사용을 최적화합니다. 긴 리스트나 그리드를 다룰 때 유용합니다. 필요한 항목만 동적으로 생성하고, 사용자가 스크롤할 때만 렌더링합니다.

ListView.builder 예제:


List items = List.generate(10000, (i) => 'Item $i');

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
    );
  },
);
        

위 코드에서 `ListView.builder`는 10,000개의 항목을 동적으로 생성하여 스크롤할 수 있게 합니다. 이는 메모리 사용을 최소화하고 성능을 최적화합니다.

GridView.builder 예제:


GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2, // 한 줄에 두 개의 항목
  ),
  itemCount: items.length,
  itemBuilder: (context, index) {
    return Container(
      color: index.isEven ? Colors.red : Colors.blue,
      child: Center(child: Text(items[index])),
    );
  },
);
        

위 코드에서 `GridView.builder`는 10,000개의 항목을 동적으로 생성하여 격자형 레이아웃으로 스크롤할 수 있게 합니다.

2) 무한 스크롤링 구현 방법

무한 스크롤링은 사용자가 리스트의 끝에 도달할 때 추가 데이터를 로드하여 리스트를 확장하는 기술입니다. 이는 주로 대용량 데이터 세트를 다루는 애플리케이션에서 사용됩니다.

무한 스크롤링 예제:


class InfiniteScrollExample extends StatefulWidget {
  @override
  _InfiniteScrollExampleState createState() => _InfiniteScrollExampleState();
}

class _InfiniteScrollExampleState extends State {
  List items = List.generate(30, (index) => index);
  ScrollController _scrollController = ScrollController();
  bool isLoading = false;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _loadMoreItems();
      }
    });
  }

  _loadMoreItems() async {
    if (isLoading) return;
    setState(() => isLoading = true);
    await Future.delayed(Duration(seconds: 2));
    setState(() {
      items.addAll(List.generate(30, (index) => items.length + index));
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('무한 스크롤링 예제')),
      body: ListView.builder(
        controller: _scrollController,
        itemCount: items.length + (isLoading ? 1 : 0),
        itemBuilder: (context, index) {
          if (index == items.length) {
            return Center(child: CircularProgressIndicator());
          }
          return ListTile(title: Text('Item ${items[index]}'));
        },
      ),
    );
  }
}
        

위 코드에서 `InfiniteScrollExample` 클래스는 `ListView.builder`와 `ScrollController`를 사용하여 무한 스크롤링을 구현합니다. 사용자가 리스트의 끝에 도달하면 `_loadMoreItems` 함수가 호출되어 추가 데이터를 로드합니다.

 

04. 특수 스크롤링 위젯

1) DraggableScrollableSheet의 사용법

`DraggableScrollableSheet`는 사용자가 드래그하여 확장하거나 축소할 수 있는 스크롤 가능한 시트를 제공합니다. 이 위젯은 화면의 하단에서 드래그하여 나타나는 다양한 시나리오에 유용합니다.

예제 코드:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('DraggableScrollableSheet 예제')),
        body: DraggableScrollableSheet(
          initialChildSize: 0.25,
          minChildSize: 0.25,
          maxChildSize: 0.75,
          builder: (BuildContext context, ScrollController scrollController) {
            return Container(
              color: Colors.blue[100],
              child: ListView.builder(
                controller: scrollController,
                itemCount: 25,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(title: Text('Item $index'));
                },
              ),
            );
          },
        ),
      ),
    );
  }
}
        

위 코드에서 `DraggableScrollableSheet`는 화면 하단에서 드래그하여 확장 및 축소할 수 있는 스크롤 가능한 시트를 제공합니다. `initialChildSize`, `minChildSize`, `maxChildSize` 속성을 통해 시트의 크기를 제어할 수 있습니다.

2) ListWheelScrollView의 사용법

`ListWheelScrollView`는 바퀴처럼 스크롤되는 영역을 제공합니다. 이 위젯은 피커(picker)와 같은 UI 컴포넌트를 만들 때 유용합니다.

예제 코드:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ListWheelScrollView 예제')),
        body: Center(
          child: Container(
            height: 200,
            child: ListWheelScrollView(
              itemExtent: 50,
              children: List.generate(10, (index) {
                return Container(
                  color: index.isEven ? Colors.blue : Colors.red,
                  child: Center(child: Text('Item $index')),
                );
              }),
            ),
          ),
        ),
      ),
    );
  }
}
        

위 코드에서 `ListWheelScrollView`는 바퀴처럼 스크롤되는 UI를 제공합니다. `itemExtent` 속성을 사용하여 각 항목의 높이를 지정합니다.

 

05. 화려한 스크롤링 효과

1) 탄력적 스크롤링(스크롤 바운싱)

탄력적 스크롤링은 사용자가 리스트 끝까지 스크롤했을 때 탄력적으로 반응하는 효과를 제공합니다. 이는 기본적으로 `ListView`와 같은 스크롤 가능한 위젯에서 제공됩니다.

예제 코드:


ListView(
  children: [
    Container(height: 100, color: Colors.red),
    Container(height: 100, color: Colors.blue),
    Container(height: 100, color: Colors.green),
    Container(height: 100, color: Colors.yellow),
    Container(height: 100, color: Colors.orange),
  ],
);
        

위 코드에서 `ListView`는 기본적으로 탄력적 스크롤링 효과를 제공합니다. 사용자가 리스트의 끝까지 스크롤했을 때 탄력적으로 반응합니다.

2) 패럴랙스 스크롤링

패럴랙스 스크롤링은 배경 이미지가 콘텐츠보다 느리게 스크롤되는 효과를 제공합니다. 이를 통해 시각적으로 매력적인 UI를 만들 수 있습니다.

예제 코드:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: [
            SliverAppBar(
              expandedHeight: 200.0,
              flexibleSpace: FlexibleSpaceBar(
                title: Text('패럴랙스 스크롤링'),
                background: Image.network(
                  'https://flutter.dev/images/catalog-widget-placeholder.png',
                  fit: BoxFit.cover,
                ),
              ),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return ListTile(
                    title: Text('Item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
        

위 코드에서 `SliverAppBar`와 `FlexibleSpaceBar`를 사용하여 패럴랙스 스크롤링 효과를 구현합니다. 배경 이미지가 콘텐츠보다 느리게 스크롤됩니다.

3) Sliver 클래스를 사용한 세부 제어

`Sliver` 클래스를 사용하면 스크롤 가능한 영역의 세부적인 제어가 가능합니다. 이를 통해 다양한 스크롤링 효과를 구현할 수 있습니다.

예제 코드:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: [
            SliverAppBar(
              expandedHeight: 200.0,
              floating: true,
              flexibleSpace: FlexibleSpaceBar(
                title: Text('Sliver 예제'),
                background: Image.network(
                  'https://flutter.dev/images/catalog-widget-placeholder.png',
                  fit: BoxFit.cover,
                ),
              ),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return ListTile(
                    title: Text('Item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
            SliverGrid(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    color: index.isEven ? Colors.blue : Colors.green,
                    child: Center(child: Text('Grid Item $index')),
                  );
                },
                childCount: 20,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
        

위 코드에서 `CustomScrollView`와 다양한 `Sliver` 위젯을 사용하여 세부적인 스크롤 제어를 제공합니다. `SliverAppBar`, `SliverList`, `SliverGrid`를 사용하여 다양한 레이아웃을 구성할 수 있습니다.

 

06. 중첩 스크롤링 위젯

1) ShrinkWrap 속성 사용법

`ShrinkWrap` 속성은 리스트가 다른 스크롤 가능한 부모 위젯 내에서 사용될 때 유용합니다. 기본적으로 `ListView`와 같은 위젯은 무한한 높이를 가정하지만, `ShrinkWrap`을 사용하면 리스트가 실제 콘텐츠에 맞게 축소됩니다.

예제 코드:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ShrinkWrap 예제')),
        body: SingleChildScrollView(
          child: Column(
            children: [
              ListView(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                children: [
                  ListTile(title: Text('항목 1')),
                  ListTile(title: Text('항목 2')),
                  ListTile(title: Text('항목 3')),
                ],
              ),
              Text('다른 콘텐츠'),
            ],
          ),
        ),
      ),
    );
  }
}
        

위 코드에서 `ListView`의 `shrinkWrap` 속성을 `true`로 설정하면 리스트의 높이가 실제 항목에 맞게 축소됩니다. 또한, `physics`를 `NeverScrollableScrollPhysics()`로 설정하여 리스트 자체가 스크롤되지 않도록 합니다.

2) Sliver를 사용한 중첩 스크롤링 구현

`Sliver` 위젯을 사용하면 중첩된 스크롤링을 효율적으로 처리할 수 있습니다. `CustomScrollView`와 다양한 `Sliver` 위젯을 사용하여 복잡한 스크롤링 레이아웃을 구현할 수 있습니다.

예제 코드:


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Sliver 중첩 스크롤링 예제')),
        body: CustomScrollView(
          slivers: [
            SliverAppBar(
              expandedHeight: 200.0,
              flexibleSpace: FlexibleSpaceBar(
                title: Text('Sliver 중첩 스크롤링'),
                background: Image.network(
                  'https://flutter.dev/images/catalog-widget-placeholder.png',
                  fit: BoxFit.cover,
                ),
              ),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return ListTile(
                    title: Text('Item $index'),
                  );
                },
                childCount: 20,
              ),
            ),
            SliverGrid(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Container(
                    color: index.isEven ? Colors.blue : Colors.green,
                    child: Center(child: Text('Grid Item $index')),
                  );
                },
                childCount: 20,
              ),
            ),
          ],
        ),
      ),
    );
  }
}
        

위 코드에서 `CustomScrollView`와 다양한 `Sliver` 위젯을 사용하여 중첩된 스크롤링 레이아웃을 구현합니다. `SliverAppBar`, `SliverList`, `SliverGrid`를 조합하여 다양한 콘텐츠를 스크롤할 수 있습니다.

 

07. 결론

1) Flutter에서 스크롤링의 핵심 요약

Flutter에서 스크롤링은 애플리케이션의 사용자 경험을 향상시키는 중요한 요소입니다. 기본 스크롤링, 무한 스크롤링, 특수 스크롤링 위젯, 화려한 스크롤링 효과, 중첩 스크롤링 등을 통해 다양한 시나리오에서 스크롤링을 효율적으로 처리할 수 있습니다. `ListView.builder`와 `GridView.builder`를 사용하여 성능을 최적화하고, `Sliver` 클래스를 사용하여 세부적인 스크롤 제어를 구현할 수 있습니다.

2) 추가 학습 자료와 참고 링크

Flutter에서 스크롤링을 더 깊이 이해하고자 하는 개발자를 위해 추가 학습 자료와 참고 링크를 제공합니다.


관련된 다른 글도 읽어보시길 추천합니다

 

2024.08.02 - [Study] - 37. Flutter에서 긴 리스트를 효율적으로 처리하는 방법 | Flutter

2024.08.02 - [Study] - 36. Flutter에서 일정 간격이 있는 리스트 만들기 | Flutter

2024.08.02 - [Study] - 35. Flutter로 다양한 유형의 아이템이 포함된 리스트 만들기 | Flutter


읽어주셔서 감사합니다

공감은 힘이 됩니다

 

:)

반응형

TOP

Designed by 티스토리