티스토리 뷰

플러터는 ios 스타일의 위젯을 cupertino 라는 패키지로 제공한다. 

pubspec.yaml 파일을 보면 cupertino_icons 라는 설정값이 보이는데 패키지는 플러터가 기본으로 제공하는 ios 아이콘 묶음이다. 

 

dependencies 설정 : pubspec.yaml 파일에서 dependencies 설정은 누군가 이미 구현해 놓은 패키지를 가져와서 사용할 수 있도록 하는 방법

 

CupuertinoMain.dart 예제코드

import 'package:flutter/cupertino.dart';

import 'animalItem.dart';
import 'iosSub/cupertinoFirstPage.dart';
import 'iosSub/cupertinoSecondPage.dart';


List<Animal> favoriteList = List.empty(growable: true);

class CupertinoMain extends StatefulWidget {  
@override
State<StatefulWidget> createState() {
return _CupertinoMain();
}
}  // _CupertinoMain 클래스를 반환한다.


class _CupertinoMain extends State<CupertinoMain> {
CupertinoTabBar? tabBar;
List<Animal> animalList = List.empty(growable: true);


@override
void initState() {
super.initState();
tabBar = CupertinoTabBar(items: <BottomNavigationBarItem>[  
BottomNavigationBarItem(icon: Icon(CupertinoIcons.home)),
BottomNavigationBarItem(icon: Icon(CupertinoIcons.add)),
]);

//_CupertinoMain 클래스에서 initState() 함수를 재정의한다. 여기서 tabBar를 통해서 탭바에서 각 탭에 표시할 아이콘을 추가한다. 쿠퍼티노 디자인에서는 CupertinIcons.add 와 같이 사용한다. 

animalList.add(
Animal(animalName: "", kind: "곤충", imagePath: "repo/images/bee.png"));
animalList.add(Animal(
animalName: "고양이", kind: "포유류", imagePath: "repo/images/cat.png"));
animalList.add(Animal(
animalName: "젖소", kind: "포유류", imagePath: "repo/images/cow.png"));
animalList.add(Animal(
animalName: "강아지", kind: "포유류", imagePath: "repo/images/dog.png"));
animalList.add(Animal(
animalName: "여우", kind: "포유류", imagePath: "repo/images/fox.png"));
animalList.add(Animal(
animalName: "원숭이", kind: "영장류", imagePath: "repo/images/monkey.png"));
animalList.add(Animal(
animalName: "돼지", kind: "포유류", imagePath: "repo/images/pig.png"));
animalList.add(Animal(
animalName: "늑대", kind: "포유류", imagePath: "repo/images/wolf.png"));

} // 위에서 생성한 animalList에 Animal 객체를 차례로 추가시킨다. 

@override
Widget build(BuildContext context) {
return CupertinoApp(
home: CupertinoTabScaffold(tabBar: tabBar!, tabBuilder: (context , value){
if(value == 0){
return CupertinoFirstPage(animalList: animalList,);
}else{
return CupertinoSecondPage(animalList: animalList,);
}}),
);}} 

// build() 함수에서는 반환 값으로 MaterialApp이 아닌 CupertinoApp을 반환한다. -> ios 스타일

// CupertinoApp의 home 에서 CupertinoTabScaffold 를 선언하여 여기에 tabBar와 tabBuilder를 넣어준다. 

// 탭은 두개이므로 각 탭을 누르면 tabBuilder에서 value가 0이나 1을 반환하고 이 값을 이용해서 탭의 로직을 처리한다. 

 

lib 폴더 -> iosSub 폴더 -> cupertinoFirstPage / cupertinoSecondPage 다트 파일 생성

cupertinoFirstPage.dart 파일

cupertinoMain에서 만든 동물 리스트를 상속받아서 리스트뷰로 화면에 출력한다. 

 

import 'package:flutter/cupertino.dart';
import '../animalItem.dart';
import '../cupertinoMain.dart';

 

//동물 리스트를 보여주는 클래스로 StatelessWidget 상속받음 


class CupertinoFirstPage extends StatelessWidget {
final List<Animal> animalList;  

const CupertinoFirstPage({Key? key, required this.animalList})
: super(key: key);

@override
Widget build(BuildContext context) { 
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar( // 쿠퍼티노에서는 카드 위젯이 없음 , 앱바 위젯도 없음
middle: Text('동물 리스트'),
),
child: ListView.builder(  
itemBuilder: (context, index) {
return GestureDetector(
child: Container(
padding: EdgeInsets.all(5),
height: 100,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Image.asset( // 이미지 파일 불러오기 
animalList[index].imagePath,
fit: BoxFit.contain,
width: 80,
height: 80,
),
Text(animalList[index].animalName) // 해당 동물이름 출력 
],
),
Container( // 동물 리스트를 검정색 줄로 공간 구분하기  
height: 2,
color: CupertinoColors.black,
)
],
),
) ,
onTap: (){ //onTap 이벤트를 통해서 이미지 클릭시 Dialog 보여준다. 
showCupertinoDialog(context: context, builder: (context){
return CupertinoAlertDialog(
title: Text(animalList[index].animalName),
);
});
},
onLongPress: (){ //길게 누르면 해당 이벤트 실행됨 
print('add fav');
favoriteList.add(Animal(animalName: animalList[index].animalName, kind: animalList[index].kind, imagePath: animalList[index].imagePath)) // cupertinoMain 에서 생성한 favoriteList에 탭을 길게 누를 시 해당 동물 객체를 리스트에 추가한다. 
},
);
},
itemCount: animalList.length, // 리스트 길이만큼 반복 
));
}
}

 

cupertinoSecondPage.dart 파일

세그먼트 위젯 ?

- 머티리얼의 라디오 버튼처럼 여럿 중 하나를 선택할 수 있는 ios 스타일 위젯

 

import 'package:flutter/cupertino.dart';

import '../animalItem.dart';

class CupertinoSecondPage extends StatefulWidget {
final List<Animal> animalList;

const CupertinoSecondPage({Key? key,required this.animalList}) : super(key: key);

@override
State<StatefulWidget> createState() {
return _CupertinoSecondPage();
}
}

class _CupertinoSecondPage extends State<CupertinoSecondPage> {
TextEditingController? _textController// 텍스트 필드를 사용하기위한 컨트롤러 선언 
int _kindChoice = 0;
bool _flyExist = false;
String? _imagePath;

Map<int, Widget> segmentWidgets = {
0: SizedBox( // 영역을 만들어주는 위젯
child: Text('양서류', textAlign: TextAlign.center),
width: 80,
),
1: SizedBox(
child: Text('포유류', textAlign: TextAlign.center),
width: 80,
),
2: SizedBox(
child: Text(
'파충류',
textAlign: TextAlign.center,
),
width: 80,
)
}

 

// Map 은 정수형 키와 위젯형 값을 쌍으로 해서 구성되며 위젯에 원하는 형태의 위젯을 넣으면 된다. 

// 예에 사용한 SizeBox는 영역을 만들어 주는 위젯으로 Map에 값에 넣은 위젯이다. 

// 참고로 텍스트만 넣으면 세그먼트가 너무 좁아서 width로 너비를 직접 입력해줘야한다. 

 

 


@override
void initState() {
super.initState();
_textController = TextEditingController();
}

@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('동물 추가'),
),
child: Container(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10),
child: CupertinoTextField( // ios 스타일의 입력 창
controller: _textController,
keyboardType: TextInputType.text,
maxLines: 1,
),
),


CupertinoSegmentedControl(  //세그먼트 위젯 사용 -> 동물의 종류를 선택하는 항목
padding: EdgeInsets.only(bottom: 20, top: 20),
groupValue: _kindChoice, // 0으로 초기화
children: segmentWidgets, //앞에서 Map으로 선언한 세그먼트위젯 객체를 children에 넣어줌
onValueChanged: (int? value) {

// 값이 바뀌었을 때 동작할 이벤트를 정의한다. 여기에서는 선택된 value값을 _kindChoice에 넣어준다. 
setState(() {
_kindChoice = value!;
});
}),


Row(
children: <Widget>[
Text('날개가 존재합니까?'),


CupertinoSwitch(
value: _flyExist,
onChanged: (value) {
setState(() {
_flyExist = value;
});
})
],
mainAxisAlignment: MainAxisAlignment.center,
),


Container(
height: 100, // 가로 리스트 뷰에서 height 크기 설정하는거 중요함!
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
GestureDetector(
child: Image.asset('repo/images/cow.png', width: 80),
onTap: () { // 이벤트를 통해 선택된 동물의 이미지 저장
_imagePath = 'repo/images/cow.png';
},
),
GestureDetector(
child: Image.asset('repo/images/pig.png', width: 80),
onTap: () {
_imagePath = 'repo/images/pig.png';
},
),
GestureDetector(
child: Image.asset('repo/images/bee.png', width: 80),
onTap: () {
_imagePath = 'repo/images/bee.png';
},
),
GestureDetector(
child: Image.asset('repo/images/cat.png', width: 80),
onTap: () {
_imagePath = 'repo/images/cat.png';
},
),
GestureDetector(
child: Image.asset('repo/images/fox.png', width: 80),
onTap: () {
_imagePath = 'repo/images/fox.png';
},
),
GestureDetector(
child: Image.asset('repo/images/monkey.png', width: 80),
onTap: () {
_imagePath = 'repo/images/monkey.png';
},),],),),


CupertinoButton( // ios 스타일의 버튼 위젯
child: Text('동물 추가하기'),
onPressed: () { 
widget.animalList.add(Animal(
animalName: _textController!.value.text,
kind: getKind(_kindChoice),
imagePath: _imagePath!,
flyExist: _flyExist));
})
],
mainAxisAlignment: MainAxisAlignment.center,
),),),);}

getKind(int kindChoice) {
switch (kindChoice) {
case 0:
return "양서류";
case 1:
return "파충류";
case 2:
return "포유류";
}}}

main.dart 클래스

main 클래스에서 MaterialApp의  home을 CupertinoMain()으로 설정해 준다. 

 

cupertinoFirstPage
cupertinoSecondPage

 

그 밖의 쿠퍼티노 위젯 

 

1. 버튼 CupertinoButton

일반  FlaButton이나 RaisedButton과 같은 기느으이 ios 스타일의 버튼 

 

CupertinoButton(
  child: Text('button'),
  color: Colors.blue,
  onpressed:()
)

 

2. 로딩 표시기 

CupertinoActivityIndicator 위젯은 ios 스타일의 로딩 표시기 입니다. radius 속성을 이용해 크기를 조절할 수 있다.

 

child: Center(
  child: CupertinoActvityIndicator(
  radius: 20, //크기를 의미 
    )  
)

 

3. 알림창 CupertinoAlertDialog

CupertinoAlertDialog 는 iso 스타일의 알림창

 

CupertinoButton(
  child: Text('dialog'),
  onPressed: () {
    showCupertinoDialog(
        context: context,
      builder: (context){
        return CupertinoAlertDialog(
        title: Text('Cupertino'),
          content: Text('쿠퍼티노 스타일의 위젯'),
          actions: [
            CupertinoButton(
            child: Text('확인'),
              onPressed: (){
                Navigator.of(context).pop();
              })])})})

 

4. 액션시트 CupertinoActionSheet

안드로이드는 알림창으로 다양한 동작을 구현할 수 있다면, ios는 알림창 이외에 하단에 표시되는 액션시트를 이용해 선택사항을 나열할 수 있다. 이떄는 showCupertinoModalPopup() 함수를 통해 CupuertinoActionSheet를 호출한다. 

 

showCupertinoMadalPopup(context: context, builder: (context){
 return CupertinoActionSheet(
  title: Text('Action'),
   message: Text('좋아하는 색은'),
   actions: [
     CupertinoButton(child: Text('Red'), onPressed: (){}),
     CupurtinoButton(child: Text('Blue'), onPressed: (){}),
   ],
   cancelButton: CupertinoButton(child: Text('취소'), onPressed(){
     Navigator.of(context).pop();
   })
 );
});

 

 

5. 피커 CupertinoPicker

ios에서는 화면 하단에 표시되는 창이 많은 편이다. 그중에서 피커는 스크롤을 이용해 이벤트를 처리하는데, 액션시트처럼 showCuprtinoMadalPopup() 함수로 호출한다. 보통 피커를 사용할 떄는 컨테이너로 높이를 정하고 이 높이를 가득채우는 Expanded() 함수를 호출해 스크롤하는 쿠퍼티노피커의 길이를 최대한 길게 설정한다.

 

6. 내비게이션바 CupertinoNavigationVar

내비게이션바를 표시하는 CupertinoNavigationBar는 스캐폴드에서 appBar 위치에 사용하는 위젯이다. 

 

appBar : CupertinoNavigatorBar(
  leading: CupertinoButton(child: Icon(Icons.arrow_back_is_ios), 
            onPressed(){}),
  middle: Text('Cupertino Design'),
  trailing: CupertinoButton(child: Icon(Icons.exit_to_app), onPressed(){}),
),

 

7. 슬라이더 CupertinoSlider

ios 스타일의 슬라이더로 기존의 머티리얼의 슬라이더와 사용법은 동일하다.  

 

CupertinoSlider(
  value: _value,
  onChanged: (index){
    setState((){
      _value = index;
    });
  },
  max:100,
  min: 1,
),
Text(_value.toString())

 

'플러터 앱 스터디 일지' 카테고리의 다른 글

플러터 스터디 chap 8  (0) 2021.10.06
플러터 스터디 chap 7  (0) 2021.10.06
플러터 스터디 chap 5  (0) 2021.09.27
플러터 스터디 chap 4  (0) 2021.09.26
플러터 스터디 chap 3  (0) 2021.09.26
댓글
공지사항