Jin's Dev Story

[Flutter] 스크롤 위치 파악하기 본문

Web & Android/Flutter

[Flutter] 스크롤 위치 파악하기

woojin._. 2023. 9. 22. 22:34

💡 import ‘package:flutter/rendering.dart’; 사용

 

스크롤 위치 파악

  1. 게시물목록 ListView에 ScrollController() 부착하기
  2. 스크롤위치 계속 감시해주는 리스너 부착하기
  3. 맨 밑까지 스크롤하면 서버에 게시물 더 달라고 GET요청하기
  4. 데이터 가져오면 data라는 state에 추가해주기

→ 스크롤 위치를 파악하고 싶으면 해당 위젯을 StatefulWidget으로 변경해야 함

→ 부모가 보낸 state를 등록할 때는 위 class에 등록하고 사용은 아래 class에서 함

→ 아래 class에서 위 class에 있는 변수를 사용할 때는 widget.변수명 사용

ScrollController

  • 스크롤바 위치 기록해줌
  • ListView를 사용하면 controller: 라는 파라미터 사용 가능
  • 변수를 넣으면 스크롤 위치에 대한 정보들을 변수에 기록해줌
    • 변수 처음 생성 시 ScrollController() 넣어서 만들어주기
  • 유저가 스크롤 할 때마다 매번 실행하고 싶다면 addListener 사용
class _HomeState extends State<Home> {
  var scroll = ScrollController();

  @override
  Widget build(BuildContext context) {
  if (widget.data.isNotEmpty){
    return ListView.builder(itemCount: 3, controller: scroll, (생략)

 

addListener

  • initState 안에서 사용
  • 스크롤 될 때마다 실행
class _HomeState extends State<Home> {
  var scroll = ScrollController();

  @override
  void initState() {
    super.initState();
    scroll.addListener( () {
      print('스크롤위치 변화함')
    });
  }

  @override
  Widget build(BuildContext context) {
  if (widget.data.isNotEmpty){
    return ListView.builder(itemCount: 3, controller: scroll, (생략)
  • scroll.position.pixels → 유저가 위에서부터 얼마나 스크롤 내렸는지 확인
  • scroll.position.maxScrollExtent → 최대 스크롤 내릴 수 있는 높이
  • scroll.position.userScrollDirection → 스크롤 방향이 위인지 아래인지 확인

⇒ 유저가 맨 밑까지 스크롤 했는지 확인하는 코드

@override
  void initState() {
    super.initState();
    scroll.addListener(() {
      if (scroll.position.pixels == scroll.position.maxScrollExtent){
        print('맨 밑까지 스크롤함')
      }
    });
  }

예제

  • 유저가 맨 밑까지 스크롤바 내리면 서버에서 게시물 가져와서 하단에 보여주기
import 'package:flutter/material.dart';
import './style.dart' as style;
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/rendering.dart';

void main() {
  runApp(
      MaterialApp(
      theme: style.theme,
      home: MyApp()
  ));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var tab = 0;  // 1. 현재 상태 저장
  var list = [1, 2, 3];
  var map = {'name':'john', 'age':20};
  var data = [];

  addData(a) {
    setState(() {
      data.add(a);
    });
  }

  getData() async {
    var result = await http.get(Uri.parse('https://codingapple1.github.io/app/data.json'));

    var result2 = jsonDecode(result.body);
    setState(() {
        data = result2;
    });

  }

  @override
  void initState() {
    super.initState();
    getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text('Instagram'),
          actions: [
            IconButton(
              icon: Icon(Icons.add_box_outlined),
              onPressed: () {},
              iconSize: 30,
            )
          ]),
      body: [Home(data : data, addData : addData), Text('샵페이지')][tab],  // 2. state에 따라 tab 보이는 상태 변경
      bottomNavigationBar: BottomNavigationBar(
        showSelectedLabels: false,
        showUnselectedLabels: false,
        onTap: (i){
          setState(() {
            tab = i;
          });
        },
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home_outlined), label: '홈'),
          BottomNavigationBarItem(icon: Icon(Icons.shopping_bag_outlined), label: '샵')
        ],
      ),
    );
  }
}

class Home extends StatefulWidget {
  const Home({Key? key, this.data, this.addData}) : super(key: key);
  final data, addData;

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {

  var scroll = ScrollController();

  getMore() async {
    var result = await http.get(Uri.parse('https://codingapple1.github.io/app/more1.json'));
    var result2 = jsonDecode(result.body);

    widget.addData(result2);
  }

  @override
  void initState() {
    super.initState();
    scroll.addListener(() {   // 스크롤바 높이 측정 코드
      if(scroll.position.pixels == scroll.position.maxScrollExtent) {
        getMore();
      }
    });
  }

  @override
  Widget build(BuildContext context) {

    if (widget.data.isNotEmpty) {
      return ListView.builder(
          itemCount: widget.data.length,
          controller: scroll,
          itemBuilder: (c, i) {
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Image.network(widget.data[i]['image']),
                Container(
                  constraints: BoxConstraints(maxWidth: 600),
                  padding: EdgeInsets.all(20),
                  width: double.infinity,
                  child: Column(
                    children: [
                      Text('좋아요 ${widget.data[i]['likes'].toString()}'),
                      Text(widget.data[i]['date']),
                      Text(widget.data[i]['content'])
                    ],
                  ),
                )
              ],
            );
          }
      );
    } else {
      return Text('로딩중임');
    }
  }
}

'Web & Android > Flutter' 카테고리의 다른 글

[Flutter] 페이지 나누기 - Navigator  (0) 2023.09.22
[Flutter] 페이지 나누기 - Tab  (0) 2023.09.22
[Flutter] http 패키지로 GET 요청  (0) 2023.09.22
[Flutter] 파일 분리하기  (0) 2023.09.22
[Flutter] ThemeData()  (0) 2023.09.22