Design-loving front-end engineer
Ryong
Design-loving front-end engineer
전체 방문자
오늘
어제
    • Framework
    • React
      • Concept
      • Library
      • Hook
      • Component
      • Test
    • NodeJS
    • Android
      • Concept
      • Code
      • Sunflower
      • Etc
    • Flutter
      • Concept
      • Package
    • Web
    • Web
    • CSS
    • Language
    • JavaScript
    • TypeScript
    • Kotlin
    • Dart
    • Algorithm
    • Data Structure
    • Programmers
    • Management
    • Git
    • Editor
    • VSCode
    • Knowledge
    • Voice
Design-loving front-end engineer

Ryong

[ Flutter ] 쿠퍼티노 디자인
Flutter/Concept

[ Flutter ] 쿠퍼티노 디자인

2021. 12. 29. 16:03

쿠퍼티노 기본 UI

💬  쿠퍼티노 디자인에서는 AppBar 대신 CupertinoNavigationBar를 사용하며 CupertinoSwitch, CupertinoButton 등을 사용한다.

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CupertinoNavigationBar(
        middle: Text('쿠퍼티노 디자인'),
      ),
      body: Column(
        children: <Widget>[
          CupertinoSwitch(
            value: _isOn,
            onChanged: (bool value) {
              setState(() {
                _isOn = value;
              });
            },
          ),
          CupertinoButton(
            borderRadius: BorderRadius.circular(16.0),
            color: Colors.orange,
            child: Text('쿠퍼티노 AlertDialog'),
            onPressed: () {
              // 클릭 이벤트
            },
          ),
          CupertinoButton(
            child: Text('쿠퍼티노 Picker'),
            onPressed: () {
              // 클릭 이벤트
            },
          ),
        ],
      ),
    );
  }
}

💬  CupertinoNavigationBar 위젯은 머티리얼 AppBar 위젯에 대응한다.

💬  leading, middle, trailing 프로퍼티는 각각 왼쪽, 가운데, 오른쪽 영역을 나타내며 middle 프로퍼티에는 주로 제목을 표시한다.

💬  CupertinoSwitch는 머티리얼 Switch와 사용 방법이 동일하다. 쿠퍼티노 디자인에서는 체크박스나 라디오 버튼이 따로 없고 스위치만 사용한다.

💬  머티리얼 디자인의 ElevatedButton 버튼에 대응하는 것으로 쿠퍼티노에서는 CupertinoButton 위젯이 제공된다.

    ◻️  기본 형태는 버튼 형태가 없는 글자만 있는 버튼이다.

    ◻️  borderRadius 프로퍼티를 설정하여 외곽선을 얼마나 둥글게 할지 설정할 수 있다.

 

CupertinoAlertDialog

showDialog(
  context: context,
  builder: (context) => CupertinoAlertDialog(
    title: [위젯],
    content: [위젯],
    actions: <Widget>[
      CupertinoDialogAction(...생략...),
      CupertinoDialogAction(...생략...),
    ],
  ),
);

_showCupertinoDialog() {
  showDialog(
    context: context,
    builder: (context) => CupertinoAlertDialog(
      title: Text('제목'),
      content: Text('내용'),
      actions: <Widget>[
        CupertinoDialogAction(
          child: Text('Cancel'),
        ),
        CupertinoDialogAction(
          child: Text('Ok'),
          onPressed: () {
            Navigator.of(context).pop();  // 다이얼로그 닫기
          },
        ),
      ],
    ),
  );
}

 

CupertinoPicker

💬  iOS에서 자주 사용되는 피커로, 위 아래로 스크롤하고 피커 바깥을 클릭하면 선택한 값이 적용된다.

showCupertinoModalPopup(
  context: context,
  builder: (context) => Container(
    height: [double 값],        // 피커의 높이를 정해 줌
    child: CupertinoPicker(
      children: <Widget>[...],
      itemExtent: [double 값],  // 표시할 항목의 높이
      onSelectedItemChanged: (int value) {
        // 선택된 항목의 인덱스 value를 처리
      },
    ),
  ),
);

💬  기본적으로 전체 화면 크기가 되므로 Container 위젯으로 감싸고 높이를 조절하면 하단의 일부가 되도록 할 수 있다.

💬  CupertinoPicker 위젯의 itemExtent 프로퍼티는 표시할 아이템의 높이값을 지정한다.

💬  onSelectedItemChanged 프로퍼티에 작성한 함수는 피커의 바깥 부분을 클릭했을 때 피커가 닫히면서 호출된다.

💬  이때 호출되는 함수의 인수인 value는 선택된 값의 인덱스 번호이다.

_showCupertinoPicker() async {
  // 0부터 9까지의 숫자 리스트 생성
  final _items = List.generate(10, (i) => i);
  var result = _items[0];  // 기본값 0
  
  await showCupertinoModalPopup(
    context: context,
    builder: (context) => Container(
      height: 200.0,  // 피커 높이는 200
      child: CupertinoPicker(
        children: _items.map((e) => Text('No. $e')).toList(),  // 0부터 9까지의 숫자 표시
        itemExtent: 50.0,  // 항목 1개의 높이는 50
        onSelectedItemChanged: (int value) {
          result = _items[value];
        },
      ),
    ),
  );
  print(result);
}

💬  피커에 0부터 9까지의 숫자를 표시하고 원하는 숫자를 선택한 후 피커 바깥을 클릭하면 결과를 출력한다.

💬  showCupertinoModalPopup() 함수는 Future 타입을 반환하기 때문에 await 키워드를 사용하여 피커가 닫힐 때까지 대기한 후 result 변수의 값을 출력한다.

💬  await 키워드를 사용하려면 메서드 선언시 async 키워드를 사용해야 한다.

 

전체 코드

더보기
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CupertinoNavigationBar(
        middle: Text('쿠퍼티노 디자인'),
      ),
      body: Column(
        children: <Widget>[
          CupertinoSwitch(
            value: _isOn,
            onChanged: (bool value) {
              setState(() {
                _isOn = value;
              });
            },
          ),
          CupertinoButton(
            borderRadius: BorderRadius.circular(16.0),
            color: Colors.orange,
            child: Text('쿠퍼티노 AlertDialog'),
            onPressed: () {
              _showCupertinoDialog();
            },
          ),
          CupertinoButton(
            child: Text('쿠퍼티노 Picker'),
            onPressed: () {
              _showCupertinoPicker();
            },
          ),
        ],
      ),
    );
  }

  _showCupertinoDialog() {
    showDialog(
      context: context,
      builder: (context) => CupertinoAlertDialog(
        title: Text('제목'),
        content: Text('내용'),
        actions: <Widget>[
          CupertinoDialogAction(
            child: Text('Cancel'),
          ),
          CupertinoDialogAction(
            child: Text('Ok'),
            onPressed: () {
              Navigator.of(context).pop();  // 다이얼로그 닫기
            },
          ),
        ],
      ),
    );
  }

  _showCupertinoPicker() async {
    // 0부터 9까지의 숫자 리스트 생성
    final _items = List.generate(10, (i) => i);
    var result = _items[0];  // 기본값 0

    await showCupertinoModalPopup(
      context: context,
      builder: (context) => Container(
        height: 200.0,  // 피커 높이는 200
        child: CupertinoPicker(
          children: _items.map((e) => Text('No. $e')).toList(),  // 0부터 9까지의 숫자 표시
          itemExtent: 50.0,  // 항목 1개의 높이는 50
          onSelectedItemChanged: (int value) {
            result = _items[value];
          },
        ),
      ),
    );
    print(result);
  }
}
저작자표시 (새창열림)

'Flutter > Concept' 카테고리의 다른 글

[ Flutter ] Web 배포 using GitHub  (0) 2022.01.07
[ Flutter ] 화면 이동  (0) 2021.12.29
[ Flutter ] 애니메이션  (0) 2021.12.29
[ Flutter ] 다이얼로그  (0) 2021.12.29
[ Flutter ] 버튼  (0) 2021.12.28
    'Flutter/Concept' 카테고리의 다른 글
    • [ Flutter ] Web 배포 using GitHub
    • [ Flutter ] 화면 이동
    • [ Flutter ] 애니메이션
    • [ Flutter ] 다이얼로그
    Design-loving front-end engineer
    Design-loving front-end engineer
    디자인에 관심이 많은 모바일 앱 엔지니어 Ryong입니다.

    티스토리툴바