본문 바로가기
개발/플러터(Flutter)

Flutter 위젯 탐방기 - 오늘의 위젯 정리하기[Cupertino]

by 수인분당선 2026. 1. 19.

1. CupertinoSliverNavigationBar

https://www.youtube.com/watch?v=xiTuAwvKxBY&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG

특징

  • iOS 디자인 가이드라인을 따르는 상단 앱바 제공
    • 스크롤을 내리면, Large Title이 자연스럽게 줄어들면서 middle 위치의 작은 타이틀로 전환됨
    • → iOS 기본 앱과 동일한 UX
  • 안드로이드의 AppBar안 CupertinoNavigationBar와는 달리 스크롤에 반응하는 동적 크기 변화(타이틀의 크기 자동 전환 등)를 지원

주의사항

- 기본적으로 stretch 효과를 지니고 있지 않기 떄문에 과한 확장 애니메이션 등을 기대할 수 없습니다. 

- CupertinoSliverNavigationBar는 일반 위젯이 아니라 Sliver이기 때문에 반드시 CustomScrollView 안에서 사용해야 합니다.

활용 예제

leading 좌측 아이콘 (뒤로가기, 프로필 등)
trailing 우측 액션 버튼 (추가, 설정 등)
middle 축소된 상태의 타이틀
largeTitle 확장된 상태의 타이틀

 

CustomScrollView(
	slivers: [
    	CupertinoSliverNavigationBar(
        	middle: Text("DashBook"),
            largeTitle: Text("dashbook"),
            leading:Icon(CupertinoIcons.person_2),
            trailing: Icon(CupertinoIcons.add),
          	automaticallyImplyLeading: true, //뒤로가기버튼 자동 여부 pop이 가능하면 자동으로 뒤로가기 아이콘 생성
        )
    ]
)

 

 


2. CupertinoRadio

https://www.youtube.com/watch?v=D0xwcz2IqAY&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=2

 

특징

  • Material의 Radio와 같은 개념을 지님
  • 여러 옵션 중 하나만 선택해야할 때 사용
  • ios 환경에 맞는 옵션 선택 구성요소
  • 제네릭 타입 <T>를 사용함

주의사항

  • 단독 사용시 ux가 좋지 않기 때문에 보통은 ListTile계열과 함께 사용하는 것이 좋습니다.
  • groupValue과 T의 타입이 일치해야 합니다. groupValue가 nullable면, <T?>로 맞추는 것이 안전합니다.(타입 불일치로 인한 컴파일 에러 주의)

활용 예제

//일반적으로 enum을 사용하여 타입을 처리함
enum SingingCharacter {
	lafayette,
    jefferson
}

SingingCharacter? _character = SingingCharacter.lafayette  //그룹을 공유(하나만 선택되도록)

//원하는 유형을 넣어 처리(<T> 값임)
CupertinoRadio<SingingCharacter>(
	value: SingingCharacter.lafayette, //값 이름
    groupValue: _character, //그룹
    onChanged: (SingingCharacter? value){...}, //선택 시 실행함수
    activeColor: Colors.purple, //활성화 색상
    inactiveColor: Colors.purple, //비활성화 색상
    fillColor: Colors.purple, //채우기 색상
)
CupertinoRadio<SingingCharacter?(
	value: SingingCharacter.jefferson,
    groupValue: _character,
    onChanged: (SingingCharacter? value){
    	//상태 변경을 넣어줘용
    	setState(() {
        	_character = value;
        }
    }
)

//만약 레이블을 추가하고싶다면 CupertinoListTile를 상위로 하여 함께 사용하는 것을 추천

 


3. CupertinoSheetRoute

https://www.youtube.com/watch?v=5H-WvH5O29I&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=3

특징

  • ios스타일의 모달 뷰
    • 화면 하단에서 올라오며, 기존 화면을 완전히 덮지 않음
  • push나 직접 호출을 통해 불러올 수 있음
    •  기존의 창 위에 새 시트를 쌓거나 시트 내에서 새 페이지로 이동하는 등의 작업을 처리
  • CupertinoSheetRoute를 통해 중첩 네비게이션이 가능하여 경로 간 원활한 전환이 가능함
  • 사용자가 아래로 스크롤하면 중첩된 경로를 포함한 시트를 닫을 수 있음
  • pop나 popSheet로 닫을 수 있음

주의사항

- 딥 링크나 상태 복원과 같은 복잡한 사용 사례의 경우 해당 위젯은 사용하지 않는 것을 권장합니다.

 

//기본 사용 예제
Navigator.of(context).push(
	CupertinoSheetRoute<void>(
    	builder: (BuildContext context) {
        	return SomePage();
        }
    )
);

//showCupertinoSheet(권장)
showCupertinoSheet(
	context: context,
    userNestedNavigation: true, //중첩된 네비게이터가 있는 CupertinoSheetRoute를 얻을 수 있음
    pageBuilder: (BuildContext context) {
    	return SomePage(
        	CupertinoButton(
            	onPressed: ()=>
                	Navigator.of(context).push(someRoute);
                    showCupertinoSheet(...)
            )
        );
    }
);

//앱 최상위 네비게이터에 시트를 띄우고 싶을때, 사용
Navigator.of(context, rootNavigator:true).push(CupertinoSheetRoute(...));


Navigator.of(context, rootNavigator:true).pop(); //최상위 네비게이터 기준 POP
CupertinoSheetRoute.popSheet(context); //현재 열린 Sheet만 안전하게 닫음(시트 구조가 복잡할 때 이 방식을 권장)

 


4. CupertinoSlidingSegmentedControl

https://www.youtube.com/watch?v=esnBf6V4C34&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=4

 

특징

  • 여러 옵션에서 값을 선택할 수 있으며, ios환경에 어우러지는 가로형 버튼 목록
  • TabBar와 같은 페이지 전환 보다는 상태 전환에 초점을 둠.
  • 자식 노드의 정렬된 맵을 통해 분할 제어를 처리
    • 값은 Widget로 어떤 위젯이든 가능하고,  키값은 T로 자유롭게 입력
  • 선택되지 않은 키값을 입력 시, onChange를 통해 상태 변경 및 작업 처리(함수 update...참고)
  • Map에 표시된 순서대로 목록이 표시됨
  • 크기는 자식 위젯의 높이에 따라 결정됨
  • 너비는 가장 [넓은 자식 요소의 고유 너비 or 사용 가능한 가로 공간을 자식 요소 수로 나눈 값] 중 더 작은 값으로 선택됨

주의사항

  • 세그먼트의 수가 많아지면 가독성이 떨어질 수 있으므로, 2~4개 정도를 권장합니다.
  • 페이지 전환 용도로 사용할 경우, ios UX와 어긋나므로 지양할 것을 추천합니다
enum Emotion { happy, sad, shocked }
Emotion _selectedEmotion = Emotion.happy;

sementsMap = <T,Widget>{
	Emotion.happy : Image(...),
	Emotion.sad : Image(...),
	Emotion.shocked : Image(...),
    
    
}

void updateSelectedEmotion(Emotion? value) {
	if(value!=null) {
    	setState(() {
        	_selectedEmotion = value;
        })l
    }
}

CupertinoSlidingSegmentedControl<Emotion>(
	children: segmentsMap,
    groupValue: _selectedEmotion,
    onValueChanged: updateSelectedEmotion,
    padding: EdgeInsets.all(10),
    thumbColor: pastelBlue, //썸네일색상
    backgroundColor: pastePurple,
    disabledChildren:{ //특정 세그먼트 비활성화
    	Emotion.sad,
        ...,
    },
)

 


5. CupertinoCheckbox

https://www.youtube.com/watch?v=ua54JU7k1Us&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=5

 

특징

  • -  체크가 가능한 다중 선택용 체크박스
  • 목록에서 여러 옵션을 선택해야 하는 경우에 사용함

주의사항

  • ios에서는 체크박스를 너무 많이 사용하게 된다면 체크박스보다는, 스위치형 토글을 사용할 것을 권장하고 있습니다.
  • tristate: true인데 value를 null 처리하지 않으면 UX적으로 의미 없는 상태가 될 수 있습니다.
  • radio와 마찬가지로, 단독 사용시 ux가 좋지 않기 때문에 보통은 ListTile계열과 함께 사용하는 것이 좋습니다.
bool? _isChecked = true; //true, false, null가능

CupertinoCheckbox(
	checkColor: CupertinoColors.activeOrange,
    value: _isChecked,
    tristate: true, //true로 설정해야함
    fillColor: WidgetStateProperty<Color?>fromMap({ 
    	WidgetState.selected: Colors.purple,
        ...
    });
    activeColor: CupertinoColors.activeBlue, //모든 컬러를 통일하고 싶을 떄, 사용
    onChanged: (bool? value){...} //토글 시 수행할 작업
);

 


6. CupertinoSwitch

https://www.youtube.com/watch?v=24tg_N4sdMQ&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=6

 

특징

  • 토글 위젯으로, 탭 뿐 아니라 드래그 제스쳐도 지원
  • apple의 사용자 인터페이스 가이드라인에서는 작은 화면이나 사용자의 주의를 특정 컨트롤로 유도하고자 할 때 사용할 것을 권장
    • ios에서 가장 표준적인 토글 컨트롤
  • 스위치 온오프 여부, 선택 시 실행되는 함수 콜백 총 두가지를 필수 값으로 받음
  • 테마가 활성화된 경우, 트랙 색상은 테마의 기본 색상과 일치함
  • 테두리를 넣거나 이미지를 삽입하는 등의 커스텀 또한 가능함

주의사항

  • 단순 선택(여러개 중 하나)이나 다중 선택 개념에는 부적합합니다.
  • 비동기 작업(API호출 등)을 연결할 경우에는 실패 시의 상태 롤백 처리가 별도로 필요합니다.
  • 이전 위젯들과 같은 이유로 단독 사용보다는 ListTile계열과 함께 사용하는 것이 권장됩니다.
//아래 두가지처럼 테마가 설정되어있는 경우 해당 테마 색상을 따름
CupertinoApp -> applyThemeToAll: true
or
CupertinoSwitch->applyTheme: true


bool isSelected = false;

CupertinoSwitch(
	value: isSelected, //필수
    onChanged: (bool? value) { //필수
    	setState(() {
        	isSelected = value ?? false;
        });
    },
    activeTrackColor: CupertinoColors.systemPurple, //기본 트랙의 스타일
    inactiveTrackColor:CupertinoColors.systemPurple, //기본 트랙의 스타일
    thumbColor:CupertinoColors.systemPurple,//엄지손가락 색상
    inactiveThumbColor:CupertinoColors.systemPurple,
);

 


추가적으로 계속해서 내용을 추가할 예정임미다!!!