DotIndicator#
캐러셀, 온보딩 화면 등에서 현재 페이지 위치를 점으로 표시하는 인디케이터 컴포넌트입니다.
Live Preview#
Web
Flutter
Loading Flutter...
class DotIndicatorDefaultExample extends StatefulComponent {
const DotIndicatorDefaultExample({super.key});
@override
State<DotIndicatorDefaultExample> createState() =>
_DotIndicatorDefaultExampleState();
}
class _DotIndicatorDefaultExampleState
extends State<DotIndicatorDefaultExample> {
int _index = 2;
@override
Component build(BuildContext context) {
return CoDotIndicator(
index: _index,
length: 5,
onChanged: (v) => setState(() => _index = v),
);
}
}
class DotIndicatorDefaultExample extends StatefulWidget {
const DotIndicatorDefaultExample({super.key});
@override
State<DotIndicatorDefaultExample> createState() =>
_DotIndicatorDefaultExampleState();
}
class _DotIndicatorDefaultExampleState
extends State<DotIndicatorDefaultExample> {
int _index = 2;
@override
Widget build(BuildContext context) {
return CoDotIndicator(
index: _index,
length: 5,
onChanged: (v) => setState(() => _index = v),
);
}
}
사용 시기 (When to Use)#
이 컴포넌트를 사용하세요:
- 캐러셀이나
PageView에서 현재 페이지 위치를 표시할 때 - 온보딩 화면에서 전체 단계 중 현재 위치를 안내할 때
- 슬라이드나 갤러리에서 탐색 위치 표시와 함께 클릭으로 직접 이동을 제공할 때
대신 다른 컴포넌트를 사용하세요:
Steps: 완료/진행 중/미완료 상태가 있는 단계별 진행 상황을 표시할 때Progress: 진행률을 퍼센트로 표시할 때Pagination: 페이지 번호 목록 탐색이 필요할 때
기본 사용법 (Basic Usage)#
// 기본 인디케이터
CoDotIndicator(
count: 5,
activeIndex: currentPage,
)
// 색상 지정
CoDotIndicator(
count: 3,
activeIndex: currentPage,
activeColor: Colors.blue,
inactiveColor: Colors.grey.shade300,
)
// 크기 지정
CoDotIndicator(
count: 4,
activeIndex: currentPage,
size: 10,
activeSize: 14,
)
// PageView와 연동
PageView(
onPageChanged: (index) => setState(() => currentPage = index),
children: pages,
),
CoDotIndicator(
count: pages.length,
activeIndex: currentPage,
)
// 기본 인디케이터 (index/length 파라미터 사용)
CoDotIndicator(
index: currentPage,
length: 5,
)
// 커스텀 색상
CoDotIndicator(
index: currentPage,
length: 3,
activeColor: '#3b82f6', // blue-500
inactiveColor: '#d1d5db', // gray-300
)
// 크기 스타일 지정
CoDotIndicator(
index: currentPage,
length: 4,
style: [DotIndicator.lg],
)
// 페이지 연동 (onChanged 콜백)
CoDotIndicator(
index: currentPage,
length: pages.length,
onChanged: (newIndex) => handlePageChange(newIndex),
style: [DotIndicator.md, DotIndicator.horizontal],
)
Props / Parameters#
| 속성 | 타입 | 기본값 | 설명 |
|---|---|---|---|
count | int | 필수 | 총 페이지(점) 수 |
activeIndex | int | 필수 | 현재 활성 인덱스 |
activeColor |
Color? |
null |
활성 점 색상 (기본값: 테마 primary) |
inactiveColor |
Color? |
null |
비활성 점 색상 (기본값: 테마 outline) |
size |
double |
8.0 |
비활성 점 크기 (px) |
activeSize |
double? |
null |
활성 점 크기 (기본값: size와 동일) |
spacing | double | 6.0 | 점 간격 (px) |
onDotTap |
void Function(int index)? |
null |
점 클릭 시 페이지 이동 핸들러 |
변형 (Variants)#
기본형#
동일한 크기의 점으로 활성/비활성을 색상으로 구분합니다.
CoDotIndicator(count: 4, activeIndex: 0)
크기 강조형#
활성 점의 크기를 키워 위치를 강조합니다.
CoDotIndicator(
count: 4,
activeIndex: 0,
size: 8,
activeSize: 12,
)
동작 스펙 (Behavior)#
인터랙션#
- 점 클릭:
onDotTap이 있으면 해당 인덱스로 페이지 이동 콜백 호출 activeIndex변경: 외부에서 상태 변경 시 활성 점 업데이트
상태 전환#
- 활성 → 비활성:
activeIndex변경 시 즉시 또는 애니메이션으로 전환 - 비활성 → 활성: 색상 또는 크기 변화
애니메이션#
- 활성 점 전환: 색상/크기 변화 200ms ease-in-out
AnimatedContainer를 통한 부드러운 크기 변화 지원
사용 가이드라인 (Usage Guidelines)#
✅ Do#
PageView와 함께 연동
Column(
children: [
Expanded(
child: PageView(
onPageChanged: (index) => setState(() => _currentPage = index),
children: onboardingPages,
),
),
Padding(
padding: EdgeInsets.only(bottom: 24),
child: CouiCoDotIndicator(
count: onboardingPages.length,
activeIndex: _currentPage,
onDotTap: (index) => pageController.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
),
),
),
],
)
PageView와 연동하여 현재 페이지를 실시간으로 반영하고 점 클릭으로 직접 이동할 수 있게 합니다.
❌ Don't#
10개 이상의 점 사용 금지
// ❌ 너무 많은 점
CouiCoDotIndicator(
count: 15, // 너무 많음
activeIndex: currentPage,
)
점이 너무 많으면 현재 위치 파악이 어렵고 터치 타겟이 작아집니다. 5개 이하를 권장하며, 그 이상은 Pagination 사용을 고려하세요.
✅ Do#
크기 강조형으로 활성 상태를 명확하게 표시
CouiCoDotIndicator(
count: 4,
activeIndex: currentPage,
size: 8,
activeSize: 14,
activeColor: Theme.of(context).colorScheme.primary,
inactiveColor: Theme.of(context).colorScheme.outlineVariant,
)
크기와 색상을 모두 변경하면 색각 이상 사용자도 활성 상태를 인식할 수 있습니다.
❌ Don't#
onDotTap 없이 점만 표시 시 탭 영역을 작게 두지 않기
// ❌ 작은 점을 클릭 가능하게 만들 때 충분한 터치 영역 미확보
CouiCoDotIndicator(
count: 4,
activeIndex: currentPage,
size: 4, // 너무 작음
onDotTap: handleDotTap,
)
터치 타겟이 너무 작으면 모바일에서 클릭하기 어렵습니다. onDotTap이 있을 때는 size를 최소 8px 이상으로 설정하세요.
✅ Do#
현재 페이지를 명확히 강조하세요.
CouiCoDotIndicator(
count: totalPages,
currentIndex: currentPageIndex,
activeDotSize: 12,
inactiveDotSize: 8,
activeColor: Theme.of(context).colorScheme.primary,
)
활성 도트를 크기와 색상으로 강조하면 사용자가 현재 위치를 한눈에 파악할 수 있습니다.
❌ Don't#
도트 개수가 너무 많으면 DotIndicator를 사용하지 마세요.
// ❌ 20개 페이지에 도트 인디케이터
CouiCoDotIndicator(
count: 20, // 너무 많은 도트
currentIndex: currentIndex,
)
도트가 너무 많으면 UI가 지저분해지고 정보 전달이 어렵습니다. 5개 이상이면 숫자(1/10) 형태의 인디케이터를 고려하세요.
접근성 (Accessibility)#
키보드 인터랙션#
| 키 | 동작 |
|---|---|
← / → | (onDotTap 있을 때) 이전/다음 점으로 포커스 이동 |
Enter / Space | 포커스된 점 클릭 |
Tab | 다음 인터랙티브 요소로 이동 |
스크린 리더#
- Flutter:
Semantics로 현재 위치 전달 ('페이지 2 / 5') -
Web:
role="tablist"+ 각 점에role="tab",aria-selected적용
터치 타겟#
onDotTap있을 때 각 점의 최소 터치 영역: 44x44dp (패딩으로 보장)
크로스 플랫폼 차이점 (Platform Differences)#
| 항목 | Flutter | Web |
|---|---|---|
| 클래스명 | CouiDotIndicator | DotIndicator |
| 애니메이션 | AnimatedContainer | CSS transition |
| 클릭 이벤트 | GestureDetector.onTap | onClick |
관련 컴포넌트 (Related Components)#
- Carousel: 내장 인디케이터가 있는 캐러셀 컴포넌트 (DotIndicator 통합)
- Steps: 단계 완료 상태가 있는 진행 표시가 필요할 때
- Progress: 퍼센트 기반 진행률 표시에 사용
조합 예제#
// DotIndicator + Carousel 외부 연동
Stack(
alignment: Alignment.bottomCenter,
children: [
CouiCarousel(
items: items,
showIndicator: false,
onChanged: (index) => setState(() => currentPage = index),
),
Positioned(
bottom: 16,
child: CouiCoDotIndicator(
count: items.length,
activeIndex: currentPage,
activeColor: Colors.white,
inactiveColor: Colors.white.withOpacity(0.5),
),
),
],
)