목차
- 사용된 기능 설명
- 사용 예시
✅ 사용된 기능 설명
- Stack() : 위젯들을 겹쳐서 쌓아 올리는 레이아웃 (= 중첩)
- CarouselSlider() : 화면에 슬라이드를 보여주고, 자동 재생·페이징·애니메이션 등을 설정
- carouselController : 슬라이더를 코드(버튼, 제스처 등)로 제어할 때 쓰는 컨트롤러를 전달 (컨트롤러로 특정 페이지로 이동, 현재 페이지 조회 등이 가능)
- items : 슬라이드로 보여줄 위젯들의 리스트. (주로, imageList.map(...).toList() 형태로 생성)
- options : 동작/모양을 설정하는 옵션 모음
- NetworkImage() : 웹(HTTP/HTTPS)에서 이미지를 가져와 표시
- AssetImage() : 앱 빌드에 포함한 로컬 에셋(프로젝트 assets/ 폴더)의 이미지를 사용 (pubspec.yaml에 assets를 등록 필수)
- imageList.map((imgLink) => ...).toList() : imageList의 각 URL을 받아서 각각을 슬라이드용 Widget으로 변환하여 List<Widget>을 만드는 코드 (imgLink는 imageList 안의 개별 URL)
- CarouselOptions() : 슬라이더의 동작을 지정하는 위젯
- viewportFraction : 한 슬라이드가 뷰포트(화면) 너비를 차지하는 비율. (1.0이면 한 페이지 전체를 채움 (디폴트 : 0.8))
- autoPlay : 이미지를 자동으로 넘길지 여부
- autoPlayInterval : 자동으로 넘기는 시간
- onPageChanged : 페이지 변경 시 콜백
- index : 새 페이지 인덱스
- reason : 자동 재생/터치/프로그램적 이동 등 변경 원인
- animateToPage() : CarouselSlider / PageController / TabController 같은 “페이지 단위로 스크롤되는 위젯”을 제어할 때 쓰이는 메서드로써, 특정 페이지(index)로 애니메이션 효과와 함께 이동시켜주는 메서드
** jumpToPage() : 순간이동하듯 바로 페이지를 바꿈
** animateToPage() : 부드럽게 스크롤 애니메이션이 적용 - withOpacity(double opacity) : 해당 객체의 투명도 설정 (0.0(완전 투명) ~ 1.0(완전 불투명))
- imageList.asMap() : 리스트를 Map 형태로 변환 (key = index, value = 리스트 값)
- imageList.asMap().entries : Map의 (key, value) 쌍들을 추출
** 예시 1 : MapEntry(0, "img1"), MapEntry(1, "img2"), MapEntry(2, "img3"))
** 예시 2 :
var fruits = ["apple", "banana", "cherry"];
fruits.asMap().entries.forEach((entry) {
print("index: ${entry.key}, value: ${entry.value}");
});
✅ 사용 예시
1️⃣ pubspec.yaml 설정

2️⃣ main.dart (import)

3️⃣ main.dart (전역 변수)

4️⃣ main.dart (body)

5️⃣ main.dart (sliderWidget)

6️⃣ main.dart (sliderIndicator)

7️⃣ 테스트
✔️ 사용된 코드
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.blue),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _current = 0; // 현재 슬라이드를 체크하는 변수
final CarouselSliderController _controller = CarouselSliderController() ;
List imageList = [ // 인터넷에서 받은 이미지 사용 (.jpg(확장자) 필수)
"https://cdn.pixabay.com/photo/2024/09/07/02/34/penguins-9028827_1280.jpg",
"https://cdn.pixabay.com/photo/2018/11/09/02/20/animal-3803640_640.jpg",
"https://cdn.pixabay.com/photo/2020/06/04/05/44/cat-5257303_640.jpg",
"https://cdn.pixabay.com/photo/2020/07/05/15/01/cat-5373337_640.jpg",
"https://cdn.pixabay.com/photo/2021/04/22/06/40/duck-6198196_640.jpg",
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Crousel Slider Test"),
),
body: Column(
children: [
SizedBox(
height: 200,
child: Stack( // Stack() : 위젯들을 겹쳐서 쌓아 올리는 레이아웃 (중첩)
children: [
sliderWidget(),
sliderIndicator(),
]
),
),
Container(
padding: const EdgeInsets.all(20),
child: const Text("Welcome to the Carousel Slider app"),
),
],
),
);
}
Widget sliderWidget(){
return CarouselSlider( // CarouselSlider() : 화면에 슬라이드를 보여주고, 자동 재생·페이징·애니메이션 등을 설정
carouselController: _controller, // carouselController : 슬라이더를 코드(버튼, 제스처 등)로 제어할 때 쓰는 컨트롤러를 전달 (컨트롤러로 특정 페이지로 이동, 현재 페이지 조회 등이 가능)
items: imageList.map((imgLink) { // items : 슬라이드로 보여줄 위젯들의 리스트. (주로, imageList.map(...).toList() 형태로 생성)
return Builder(
builder: (context){
return SizedBox(
//width: MediaQuery.of(context).size.width,
width: MediaQuery.of(context).size.width,
child: Image(
fit: BoxFit.fill,
image: NetworkImage( // NetworkImage() : 웹(HTTP/HTTPS)에서 이미지를 가져와 표시 / AssetImage() : 앱 빌드에 포함한 로컬 에셋(프로젝트 assets/ 폴더)의 이미지를 사용 (pubspec.yaml에 assets를 등록해야 함)
imgLink,
),
),
);
},
);
}).toList(), // imageList.map((imgLink) => ...).toList() : imageList의 각 URL을 받아서 각각을 슬라이드용 Widget으로 변환하여 List<Widget>을 만드는 코드 (imgLink는 imageList 안의 개별 URL)
options: CarouselOptions( // options : 동작/모양을 설정하는 옵션 모음 / CarouselOptions() : 슬라이더의 동작을 지정하는 위젯
height: 300,
viewportFraction: 1.0, // viewportFraction : 한 슬라이드가 뷰포트(화면) 너비를 차지하는 비율. (1.0이면 한 페이지 전체를 채움 (디폴트 : 0.8))
autoPlay: true, // autoPlay : 이미지를 자동으로 넘길지 여부
autoPlayInterval: const Duration(seconds: 4), // autoPlayInterval : 자동으로 넘기는 시간
onPageChanged: (index, reason) { // onPageChanged : 페이지 변경 시 콜백. index는 새 페이지 인덱스, reason은 자동 재생/터치/프로그램적 이동 등 변경 원인
setState(() {
_current = index;
});
},
),
);
}
Widget sliderIndicator(){
return Align(
alignment: Alignment.bottomRight,
// 점자 형태의 Indicator
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: imageList.asMap().entries.map((entry){
return GestureDetector(
onTap: () => _controller.animateToPage(entry.key), // imageList 에 담긴 index 를 key 값으로 가져옴 / animateToPage() : 특정 페이지(index)로 애니메이션 효과와 함께 이동시켜주는 메서드.
child: Container(
width: 12,
height: 12,
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 4),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white.withOpacity(_current == entry.key ? 0.9 : 0.4), // withOpacity(double opacity) : 해당 객체의 투명도 설정 (0.0(완전 투명) ~ 1.0(완전 불투명))
),
),
);
}).toList(),
// imageList.asMap().entries.map((entry){ ... }).toList() 추가 설명
// 1. imageList.asMap() : 리스트를 Map 형태로 변환 (key = index, value = 리스트 값)
// 2. imageList.asMap().entries : Map의 (key, value) 쌍들을 추출 (ex. MapEntry(0, "img1"), MapEntry(1, "img2"), MapEntry(2, "img3"))
// 3. entry : 유저가 임의로 명명한 map 함수의 매개변수
// 4. 최종적으로 해당 코드는 "리스트의 인덱스(key)와 값(value)을 동시에 가져와서 위젯(또는 다른 객체) 리스트로 변환"하는 코드
),
/*
// 현재 슬라이더 / 전체 슬라이더
child: Padding(
padding: const EdgeInsets.all(8.0), // Indicator로 표기되는 텍스트 여백 주기
child: Text(
"${_current + 1} / ${imageList.length}", // 현재 슬라이드 인덱스 +1 / 전체 슬라이드
style: const TextStyle(
color: Colors.white,
fontSize: 13,
fontWeight: FontWeight.bold,
shadows: [ // 글자에 그림자 효과
Shadow( // Shadow() : 글자(Text) 또는 다른 UI 요소에 그림자를 표현하기 위한 클래스
offset: Offset(1,1), // offset : 그림자의 위치 이동값 (x, y)
blurRadius: 3, // blurRadius : 그림자가 얼마나 퍼져서 흐려질지
color: Colors.black54,
)
],
),
),
),
*/
);
}
}
'IT 언어 > Flutter' 카테고리의 다른 글
| [Flutter] Firebase 연동 및 이메일 로그인 [맥북💻] (0) | 2025.10.04 |
|---|---|
| [Flutter] ListView 페이지 스크롤 [맥북💻] (0) | 2025.09.30 |
| [Flutter] MVVM 패턴 (Consumer, ChangeNotifierProvider)[맥북💻] (0) | 2025.09.29 |
| [Flutter] Form 양식 제출 (GlobalKey, TextFormField, ModalRoute) [맥북💻] (0) | 2025.09.29 |
| [Flutter] 웹뷰 (webview_flutter) [맥북💻] (0) | 2025.09.28 |