inblog logo
|
{CODE-RYU};
    Flutter

    [Flutter] Flutter 예제 - NestedScrollView 사용

    류재성's avatar
    류재성
    Apr 16, 2024
    [Flutter] Flutter 예제 - NestedScrollView 사용
    Contents
    1. NestedScrollView 를 사용하는 목적2. Column 내부에 ListView 가 있는 경우3. ListView 내부에 ListView가 있는 경우4. NestedScrollView 5. ProfileApp 예제NestedScrollView 로 변경하기
     
     

    1. NestedScrollView 를 사용하는 목적

    [Flutter] Flutter 예제 - Profile App 만들기 - {CODE-RYU};
    Flutter
    [Flutter] Flutter 예제 - Profile App 만들기 - {CODE-RYU};
    https://inblog.ai/coderyu1/flutter-flutter-예제-profile-app-만들기-18715?traffic_type=internal
    [Flutter] Flutter 예제 - Profile App 만들기 - {CODE-RYU};
     
    notion image
     
    위의 블로그처럼 프로필 앱 화면을 만들었다. 하지만 이 예제는 TabBarView 부분만 스크롤이 작동하고 TabBar 윗 부분은 고정되어있다.
    notion image
     
    하지만 인스타그램과 같은 앱들은 화면 전체가 스크롤화 되어있다. 화면 전체를 스크롤화하기 위해 몇가지 상황을 만들어보자.
     

    2. Column 내부에 ListView 가 있는 경우

     
    import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Column( // 부모 컬럼 children: [ Container( height: 500, color: Colors.red, ), Expanded( child: ListView.builder( // 자식 리스트뷰 itemCount: 10, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(top: 5), child: Container( height: 100, color: Colors.blue, ), ); }, ), ), ], ), ); } }
     
    notion image
     
    💡
    컬럼 내부에 리스트뷰가 있다면 부모인 컬럼 박스는 그대로 유지된 채로 자식 리스트뷰만 스크롤이 생성된다.
     
     
     
     
    빨간 색 리스트뷰는 작동하지만 내부의 리스트뷰는 작동되지 않는다.
    스크롤을 공유하지 않는다. 이 상태에서는 위의스크롤이 끝나야 아래의 스크롤이 작동한다.
     

    3. ListView 내부에 ListView가 있는 경우

     
    import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: ListView( children: [ Container( height: 500, color: Colors.red, ), ListView.builder( itemCount: 10, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(top: 5), child: Container( height: 100, color: Colors.blue, ), ); }, ), ], ), ); } }
    notion image
     
     
    💡
    리스트뷰 내부에 리스트뷰가 있는 경우 위와 같은 오류가 발생한다. 이 오류는 리스트뷰의 크기는 무제한이기 때문에 자식 리스트뷰가 차지할 크기를 알 수 없어 발생한 오류이다. 따라서 리스트뷰 내부에 리스트뷰가 있다면 자식 리스트뷰의 크기를 지정해주어야 한다.
     
    import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: ListView( children: [ Container( height: 500, color: Colors.red, ), SizedBox( height: 1050, child: ListView.builder( itemCount: 10, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(top: 5), child: Container( height: 100, color: Colors.blue, ), ); }, ), ), ], ), ); } }
    notion image
    notion image
     
    💡
    이렇게 자식 리스트뷰에 SizedBox를 사용해 크기를 지정했다. 이렇게 되면 부모 리스트뷰가 있을 땐 부모 스크롤만 움직이고, 부모 리스트뷰가 없어지면 자식 리스트뷰의 스크롤이 작동한다. 빨간 부분이 화면에서 사라지면 빨간 부분을 찾기 위해 재실행을 할 수 밖에 없다. 인스타그램처럼 화면 전체의 스크롤을 공유하기 위해 NestedScrollView 를 사용한다.
     

    4. NestedScrollView

     
    💡
    NestedScrollView는 다른 스크롤 가능한 뷰들을 중첩하여 사용할 수 있게 해주는 위젯이다. 이는 스크롤 위치가 서로 연동되는 특징을 가지고 있어
     
    import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( home: const HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: NestedScrollView( headerSliverBuilder: (context, _) { return [ SliverList( delegate: SliverChildListDelegate([ Container( height: 500, color: Colors.red, ), Container( height: 500, color: Colors.green, ), Container( height: 500, color: Colors.yellow, ), ]), ), ]; }, body: ListView.builder( physics: const NeverScrollableScrollPhysics(), itemCount: 10, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.only(top: 5), child: Container( height: 100, color: Colors.blue, ), ); }, ), ), ); } }
     
    notion image
     
    notion image
     
     

    5. ProfileApp 예제NestedScrollView 로 변경하기

     
    pages/profile_page.dart
    import 'package:flutter/material.dart'; import '../components/profile_buttons.dart'; import '../components/profile_count_info.dart'; import '../components/profile_drawer.dart'; import '../components/profile_header.dart'; import '../components/profile_tab.dart'; class ProfilePage extends StatelessWidget { const ProfilePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: _buildAppBar(), endDrawer: ProfileDrawer(), body: NestedScrollView( headerSliverBuilder: (context, _) { return [ SliverList( delegate: SliverChildListDelegate([ ProfileHeader(), ProfileCountInfo(), ProfileButtons(), ]), ), ]; }, body: ProfileTab(), ), ); } AppBar _buildAppBar() { return AppBar( leading: Icon(Icons.arrow_back_ios), title: Text("Profile"), centerTitle: true, ); } }
     
    notion image
     
    NestedScrollView 를 사용해 화면 전체를 스크롤이 가능하게 변경했다.
    Share article

    {CODE-RYU};

    RSS·Powered by Inblog