본문 바로가기
Flutter/Flutter FAQ

Flutter 플러터에서 가로로 스크롤 가능한 카드들과 스냅 효과를 구현해주세요., Horizontally scrollable cards with Snap effect in flutter

by 베타코드 2023. 8. 11.
반응형

질문


나는 좌우로 스와이프할 때 적합한 스냅 효과가 있는 가로로 스크롤되는 카드 목록을 만들고 싶습니다.

각 카드 사이에 일정한 간격이 있으며 아래 이미지와 같이 화면에 맞게 조정됩니다.

이미지 설명 입력

또한, 이 가로로 스크롤 가능한 목록 요소는 수직으로 스크롤 가능한 목록 내에 포함되어야 합니다.

내가 달성한 것은 플러터 문서를 따라가며 가로로 스크롤되는 카드 목록만 표시하는 것입니다.

class SnapCarousel extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = '가로 목록';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
        ),
        body: Container(
          margin: EdgeInsets.symmetric(vertical: 20.0),
          height: 200.0,
          child: ListView(
            scrollDirection: Axis.horizontal,
            children: <Widget>[
              Container(
                width: 160.0,
                color: Colors.red,
              ),
              Container(
                width: 160.0,
                color: Colors.blue,
              ),
              Container(
                width: 160.0,
                color: Colors.green,
              ),
              Container(
                width: 160.0,
                color: Colors.yellow,
              ),
              Container(
                width: 160.0,
                color: Colors.orange,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

답변


사용하세요 PageViewListView:

import 'package:flutter/material.dart';

main() => runApp(MaterialApp(home: MyHomePage()));

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('세로 스크롤 내의 캐러셀'),
      ),
      body: ListView.builder(
        padding: EdgeInsets.symmetric(vertical: 16.0),
        itemBuilder: (BuildContext context, int index) {
          if(index % 2 == 0) {
            return _buildCarousel(context, index ~/ 2);
          }
          else {
            return Divider();
          }
        },
      ),
    );
  }

  Widget _buildCarousel(BuildContext context, int carouselIndex) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Text('캐러셀 $carouselIndex'),
        SizedBox(
          // 태블릿 지원을 위해 여기에 가로세로 비율을 사용할 수 있습니다
          height: 200.0,
          child: PageView.builder(
            // 캐러셀 스크롤 위치를 저장하기 위해 이 컨트롤러를 상태에 저장하세요
            controller: PageController(viewportFraction: 0.8),
            itemBuilder: (BuildContext context, int itemIndex) {
              return _buildCarouselItem(context, carouselIndex, itemIndex);
            },
          ),
        )
      ],
    );
  }

  Widget _buildCarouselItem(BuildContext context, int carouselIndex, int itemIndex) {
    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 4.0),
      child: Container(
        decoration: BoxDecoration(
          color: Colors.grey,
          borderRadius: BorderRadius.all(Radius.circular(4.0)),
        ),
      ),
    );
  }
}
반응형

댓글