Flutter - Cupertino 위젯(1)

유의선·2024년 3월 7일

쿠퍼티노(Cupertino)는 애플에서 사용하는 디자인 지침이다.
이전 리스트뷰 프로젝트를 쿠퍼티노 위젯을 이용해 iOS 스타일로 바꾸어보았다.

pubspec.yaml을 보면 cupertino_icons 라는 패키지가 제공하는 iOS 아이콘 묶음이 존재하는 것을 알 수 있다.

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2

이전 리스트뷰 프로젝트lib 폴더에 cupertinoMain.dart라는 이름으로 새 다트 파일을 만들었다.

import 'package:flutter/cupertino.dart';

class CupertinoMain extends StatefulWidget {
  
  State<StatefulWidget> createState() {
    throw UnimplementedError();
  }
  
}

import를 통해 cupertino 패키지를 불러왔다.
그리고 StatefulWidget 클래스를 상속하는 CupertinoMain 클래스를 작성했다.


화면을 구성하는 기본 골격을 만들었다.

CupertinoMain 클래스의 createState()에서 반환할 _CupertinoMain 클래스를 생성하였다.

class _CupertinoMain extends State<CupertinoMain> {
  
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoTabScaffold(tabBar: null, tabBuilder: null,),
    );
  }
  
}

iOS 스타일에선 MaterialApp이 아닌 CupertinoApp을 반환한다.
CupertinoApphome에서 CupertinoTabScaffold를 선언하였다.


탭바를 만들어보았다.

class _CupertinoMain extends State<CupertinoMain> {
  CupertinoTabBar? tabBar;
  
  ...

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

CupertinoTabBar를 하나 만든 후 initState() 함수에서 정의하였다.
아이콘은 쿠퍼티노 디자인을 사용하기 위해 CupertinoIcons를 사용하였다.


정의한 탭바를 CupertinoTabScaffold 안의 tabBar에 넣고, tabBuilder에서 각 탭을 어떻게 표시할지 작성하였다.

  
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoTabScaffold(
          tabBar: tabBar!,
          tabBuilder: (context, value) {
            if (value == 0) {
              return Container(
                child: Center(
                  child: Text('cupertino tab 1'),
                ),
              );
            } else {
              return Container(
                child: Center(
                  child: Text('cupertino tab 2'),
                ),
              );
            }
          }),
    );
  }

탭은 2개이므로 각 탭을 누르면 tabBuilder에서 value가 0 또는 1을 반환한다. 이 값을 이용해 어느 탭이 눌렸는지 판단한다.
각 탭이 눌렸을 때 그 탭의 번호를 Text로 띄워주도록 하였다.


main.dart 파일을 수정해 CupertinoMain() 을 보여주도록 하였다.

import './cupertinoMain.dart';

void main() {
  runApp(CupertinoMain());
}

쿠퍼티노 디자인의 아이콘이 보이는 것을 확인할 수 있다.


이전에 만든 리스트뷰를 iOS 스타일로 만들어 추가해보았다.

먼저 cupertinoMain.dart 파일에 동물 목록을 추가하고,
List를 선언한 후
initState() 함수에서 리스트에 아이템을 추가하였다.

import 'animalItem.dart';

...

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

	...
}

  
  void initState() {
    super.initState();

    tabBar = CupertinoTabBar(items: <BottomNavigationBarItem>[
      BottomNavigationBarItem(icon: Icon(CupertinoIcons.home)),
      BottomNavigationBarItem(icon: Icon(CupertinoIcons.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"));
  }
}

lib 폴더에 iosSub 폴더를 새로 만들고 cupertinoFirstPage.dart 파일을 만들었다.

StatelessWidget을 상속받는 CupertinoFirstPage 클래스를 생성하였다.

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

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

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

  
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('동물 리스트'),
      ),
      child: ListView.builder(
          itemBuilder: (context, index) {
            return 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,
                  )
                ],
              ),
            );
          },
          itemCount: animalList.length),
    );
  }
}

cupertinoMain 에서 만든 동물 리스트를 상속받아 ListView로 화면에 출력한다.
이전에 만든 firstPage.dart와 비슷하지만 쿠퍼티노 위젯에는 Card 위젯이 없다. 따라서 Container를 사용해 위젯을 배치하였다.
또한 appBar 위젯도 없어 대신 navigationBar를 사용하였다.


cupertinoMain.dart 파일에서 build() 함수가 CupertinoFirstPage를 반환하도록 하였다.

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

0개의 댓글