본문 바로가기

Flutter  학습/오준석의 플러터 생존코딩 학습 및 요약

5. 기본 위젯 -2

차례:

더보기

5.1 입력용 위젯

  • TextField
  • CheckBox와 Switch
  • Radio와 RadioListTile
  • DropDownButton

5.2 다이얼로그 

  • AlertDialog
  • DatePicker
  • GestureDetector와 InkWell

5.3 이벤트

  • GestureDetector와 InkWell

5.4 애니매이션

  • Hero
  • AnimatedContainer
  • SliverAppBar와 SliverFillRemaining
  •  

5.1 입력용 위젯

5.1.1 TextField

글자를 입력받는 위젯. 

    return Column(
      children: [
        TextField(
          decoration: InputDecoration(labelText: '여기에 입력하세요'),
        ),
        TextField(
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            labelText: '여기에 입력하세요',
          ),
        ),
      ],
    );
  • InputDecoration클래스는  힌트 메시지나 외곽선등의 꾸밈 효과를 간단히 추가 할수 있다.
    • labelText :  힌트
    • border : OutlineInputBorder()  : 외곽선

5.1.2 checkedBox 와 Switch

설정 화면 등에 많이 쓰이는 체크박스, 라디오 버튼, 스위치를 표현하는 위젯.

onChanged 이벤트는 체크값이 변할 때마다 발생하는데, 변경된 값이 value 인수로 넘어온다. 그리고 setState() 함수를 통해 value 프로퍼티에 지정한 변수 값을 변경하여 UI를 다시 그립니다. 

    return Column(
      children: [
        Checkbox(
          value: isChecked,
          onChanged: (value){
            setState(() {
              isChecked = value!;
            });
          },
        ),
        Switch(
          value: isChecked,
          onChanged: changed,
        ),
      ],
    );

5.1.3 Radio와 RadioListTile

선택 그룹중 하나를 선택할 때 사용하는 위젯입니다. 어디까지를 터치 영역을 볼 것이냐에 따라서 Radio, RadioListTile을 사용할수 있다.

    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ListTile(
              title: Text('남자'),
              leading: Radio(
                value: Gender.MAN,
                groupValue: _gender,
                onChanged: (value) {
                  setState(() {
                    _gender = value!;
                  });
                },
              ),
            ),
            ListTile(
              title: Text('여자'),
              leading: Radio(
                value: Gender.WOMEN,
                groupValue: _gender,
                onChanged: (value) {
                  setState(() {
                    _gender = value!;
                  });
                },
              ),
            ),
            SizedBox(
              height: 40,
            ),
            RadioListTile(
              title: Text("남자"),
              value: Gender.MAN,
              groupValue: _gender,
              onChanged: (value) {
                setState(() {
                  _gender = value!;
                });
              },
            ),
            RadioListTile(
              title: Text("여자"),
              value: Gender.WOMEN,
              groupValue: _gender,
              onChanged: (value) {
                setState(() {
                  _gender = value!;
                });
              },
            ),
          ],
        ),
      ),
    );
  • RadioListTile의 경우 가로 전체가 터치 영역이 됩니다.

5.1.4 DropDownButton

여러 아이템중 하나를 고를 수 있는 드랍 박스 형태의 위젯.

    return DropdownButton(
      // isExpanded: true,
      value: _selectedValue,
      items: _valueList.map(
        (value) {
          return DropdownMenuItem(
            value: value,
            child: Text(value),
          );
        },
      ).toList(),
      onChanged: (value) {
        setState(() {
          _selectedValue = value!;
        });
      },
    );

5.2 다이얼로그

5.2.1 AlertDialog

showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('제목'),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Text('Alert Dialog 입니다'),
                Text('OK를 눌러 닫습니다.'),
              ],
            ),
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text('OK'),
            ),
            TextButton(
              style: TextButton.styleFrom(
                foregroundColor: Colors.red, // foreground
                backgroundColor: Colors.white,
              ),
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text('Cancel'),
            ),
          ],
        );
      },
    );
  • title : 제목 영역
  • content : 내용 영역
  • actions : button들과 버튼 클릭시 화면 전환을 담당하는 Navigator 클래스 호출

5.2.2 DatePicker

날짜를 선택할 때 사용하는 위젯.

    showDatePicker(
            context: context,
            initialDate: DateTime.now(),
            firstDate: DateTime(2020),
            lastDate: DateTime.now())
        .then((pickedDate) {
      if (pickedDate == null) {
        return;
      }
      setState(() {
        _selectedDate = pickedDate;
      });
    });

5.2.3 TimePicker

시간을 선택할 때 사용하는 위젯.

  TimeOfDay? _selectedTime;

  void _presentTimePicker() {
    showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    ).then((pickedTime) {
      if (pickedTime == null) {
        return;
      }
      setState(() {
        _selectedTime = pickedTime;
      });
    });

5.3 이벤트

5.3.1 GestureDetector와 InkWell

글자나 그림 같이 이벤트 프로퍼티가 없는 위젯에 클릭 이벤트를 적용하고 싶을때 사용하는 위젯.

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        GestureDetector(
          onTap: () {
            print('GestureDetector 클릭!!');
          },
          child: const Text(' 클릭 Me!!'),
        ),
        SizedBox(
          height: 50,
        ),
        InkWell(
          onTap: (){
            print('InkWell 클릭!!');
          },
          child: const Text('클릭 Me!!'),
        ),
      ],
    );

5.4 애니메이션

5.4.1 Hero

Hero 위젯은 화면 전환시 자연스럽게 연결되는 애니메이션을 지원합니다. 이전 화면으로 돌아갈 때도 자연스럽게 애니메이션이 동작.

import 'package:flutter/material.dart';

class MyHero extends StatefulWidget {
  @override
  State<MyHero> createState() => _MyHeroState();
}

class _MyHeroState extends State<MyHero> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const HeroDetailPage()),
          );
        },
        child: Hero(
          tag: 'image',
          child: Image.asset(
            'assets/dog.png',
            width: 100,
            height: 100,
          ),
        ),
      ),
    );
  }
}

class HeroDetailPage extends StatelessWidget {
  const HeroDetailPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Hero Detail'),
      ),
      body: Hero(
        tag: 'image',
        child: Image.asset('assets/dog.png'),
      ),
    );
  }
}

 

5.4.2 AnimatedContainer

AnimatedContainer 위젯은 한 화면내에서  setState() 함수를 호출하여 화면을 새로 그릴 때 변경된 프로퍼티에 의해 애니매이션되도록 해줍니다.

class _MyAnimatedContainerState extends State<MyAnimatedContainer> {
  var _size = 100.0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          final random = Random();
          setState(() {
            _size = random.nextInt(200).toDouble() + 100;
          });
        },
        child: AnimatedContainer(
          duration: Duration(seconds: 1),
          width: _size,
          height: _size,
          child: Image.asset('assets/dog.png'),
          curve: Curves.fastOutSlowIn,
        ),
      ),
    );
  }
}

5.5 쿠퍼티노 디자인

!!! 아이폰스러운 디자인 !!!

class _MyCupertinoState extends State<MyCupertino> {
  var _isOn = false;

  _showCupertionDialog() {
    showDialog(
      context: context,
      builder: (context) => CupertinoAlertDialog(
          title: Text('제목'),
          content: Text('내용'),
          actions: [
            CupertinoDialogAction(
              child: Text('Cancel'),
            ),
            CupertinoDialogAction(
              child: Text('Ok'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            )
          ]),
    );
  }

  _showCupertinoPicker() async {
    final _items = List.generate(10, (i) => i);
    var result = _items[0];

    await showCupertinoModalPopup(
        context: context,
        builder: (context) => Container(
              height: 200.0,
              child: CupertinoPicker(
                children: _items.map((e) => Text('No. $e')).toList(),
                itemExtent: 50.0,
                onSelectedItemChanged: (int value) {
                  result = _items[value];
                },
              ),
            ));
    print(result);
  }

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

'Flutter  학습 > 오준석의 플러터 생존코딩 학습 및 요약' 카테고리의 다른 글

4. 기본 위젯 - 1  (0) 2023.02.20
3. 프로젝트 구조와 앱 구조  (0) 2023.02.20
2. Dart 문법  (0) 2023.02.20
1. Flutter 란?  (0) 2023.02.20