Flutter Cookbook (Animation, Design)

Updated:

Flutter Cookbook

1.Animation

Animate the properties of a container

  • Container 를 사용해서 그 안의 영역의 width, height, background color, padding, borders 등 을 조절해서 만들수 있습니다

  • 예시로 floting button 을 누르게 되면 container 의 크기, 색, radius 가 랜덤으로 마뀌는 animatedContainer 생성

Check point!

  • StatefulWidget 에서 default 값을 설정합니다

  • 위에 default 로 선언된 값을 animatedContainer 를 사용해서 그 값을 적용합니다

  • 버튼을 누를때 마다 그 값들이 바뀔 수 있도록 setState(){} 에서 각 값을 random 값으로 설정 해 줍니다

import 'dart:math';
import 'package:flutter/material.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 AnimatedContainerApp(),
    );
  }
}

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

  @override
  _AnimatedContainerAppState createState() => _AnimatedContainerAppState();
}

class _AnimatedContainerAppState extends State<AnimatedContainerApp> {
  // 초기 변수 값 선언
  double _width = 50;
  double _height = 50;
  Color _color = Colors.green;
  BorderRadiusGeometry _borderRadius = BorderRadius.circular(8);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('AnimatedContainer Demo'),
        ),
        body: Center(
          // AnimatedContainer 생성
          child: AnimatedContainer(
            // 각 크기의 값을 변수 값에 대입
            width: _width,
            height: _height,
            decoration: BoxDecoration(
              color: _color,
              borderRadius: _borderRadius,
            ),
            // 얼마동안 animation 의 시간 설정함
            duration: const Duration(seconds: 1),
            // 에니메이션 effect 의 값을 설정합니다
            curve: Curves.fastOutSlowIn,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          // 버튼을 클릭 할 때 변수 값 설정
          onPressed: () {
            // setState 를 사용해서 onPressed 될때 마다 새로운 value 값이 설정 될 수 있도록 값을 설정함
            setState(() {
              // random 변수 값 생성
              final random = Random();

              // 0 ~ 300 까지의 랜덤 값이 double 형태로 나올 수 있게 함
              _width = random.nextInt(300).toDouble();
              _height = random.nextInt(300).toDouble();

              // color 도 마찬가지로 RGBO 이 256 안에서 random 값이 나오게 설정함
              _color = Color.fromRGBO(
                random.nextInt(256),
                random.nextInt(256),
                random.nextInt(256),
                1,
              );

              // border 값 random 값 설정
              _borderRadius =
                  BorderRadius.circular(random.nextInt(100).toDouble());
            });
          },
          child: const Icon(Icons.play_arrow),
        ),
      ),
    );
  }
}

Kapture 2021-10-27 at 15 33 52

Fade a widget in and out

  • AnimatedOpacity widget 을 사용해서 투명도 에니메이션을 사용할 수 있습니다

Check point!

  • fade in and out 용 Container 생성

  • StatefulWidget 생성 및 설정

  • action button 생성 및 설정

  • Fade in and out 설정


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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // bool type 의 visible 변수 생성
  bool _visible = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Opacity Demo'),
      ),
      body: Center(
        // AnumatedOpacity 생성
        child: AnimatedOpacity(
          // _visible 이 true 이면 opacity 1.0 (fully visible).
          // _visible 이 false 이면 opacity 0.0 (invisible).
          opacity: _visible ? 1.0 : 0.0,
          duration: const Duration(milliseconds: 500),
          // 초록색 container 는 animatedOpacity widget 의 child 에 위치 해야 함
          child: Container(
            width: 200.0,
            height: 200.0,
            color: Colors.green,
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // pressed 할때 마다 ture / false 를 변경 하는 setState
          setState(() {
            _visible = !_visible;
          });
        },
        // 버튼을 길게 눌렀을때 tooltip 의 text 표시
        tooltip: 'Toggle Opacity',
        child: const Icon(Icons.flip),
      ),
    );
  }
}

Kapture 2021-10-27 at 15 59 55

2.Design

Add a Drawer to a screen

  • 햄버거 버튼을 누르면 좌 / 우측에서 drawer 가 스크린에 나타 나게 하는 기능 만들기 입니다.

Check point!

  • Scaffold 생성하기

  • Drawer 추가하기

  • Drawer 의 items 생성하기

  • Drawer 닫기 기능 만들기


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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Drawer Demo')),
      body: const Center(
        child: Text('My Page!'),
      ),
      // Drawer 위젯 생성
      drawer: Drawer(
        // Child 로 ListView 생성
        child: ListView(
          // 중요!! : ListView 의 padding 사이즈는 0 으로 맞춰 야 함
          padding: EdgeInsets.zero,
          children: [
            // DrawerHeader 색, text 설정
            const DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.blue,
              ),
              child: Text('Drawer Header'),
            ),
            ListTile(
              title: const Text('Item 1'),
              onTap: () {
                // 클릭할때 다른 state 로 넘어 갈 수 있게 state 설정함
                // 예를 들어 page1(); 하면 page1 state 로 넘어감
                // 그리고 나서 drawer 를 닫기 함
                Navigator.pop(context);
              },
            ),
            ListTile(
              title: const Text('Item 2'),
              onTap: () {
                // Update the state of th 갈 수 있게 state 설정함
                // 예를 들어 page2(); 하면 page2 state 로 넘어감
                // 그리고 나서 drawer 를 닫기 함
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}

Kapture 2021-10-27 at 16 21 16

Display a snackbar

  • 디스플레이 하단에 메세지를 띄우기 위한 기능으로 snackbar 라고 불립니다.

Check point!

  • Scaffold 생성

  • SnackBar 생성 및 설정

  • 부가적인 optional action 생성

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SnackBar Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // snackBar 디스플레이 표시를 위한 변수 선언
            final snackBar = SnackBar(
              content: const Text('Yay! A SnackBar!'),
              // Snackbar 의 action 버튼 생성 : SnackBarAction
              action: SnackBarAction(
                label: 'Undo',
                onPressed: () {
                  // Undo 를 눌렀을 경우에 action 설정
                },
              ),
            );
            // ScaffoldMessenger builder widget tree 를 연결해서 showSnackBar(snackBar) 연결해서 사용함
            ScaffoldMessenger.of(context).showSnackBar(snackBar);
          },
          child: const Text('Show SnackBar'),
        ),
      ),
    );
  }
}

Kapture 2021-10-27 at 16 41 44

Update the UI based on orientation

  • 사용자의 위치와의 따라 portrait, landscape mode 일때 display 의 colum 숫자가 변경되게 하기 위해 Orientation 위젯을 사용합니다

Check point!

  • GridView 에서 2개의 columns 설정 (as default setting)

  • OrientationBuilder 의 위젯을 사용하여 columns 숫자를 변경합니다 (위치 변경에 따라서 columns 의 display 숫자 다르게 설정)

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Orientation Demo')),
      // OrientationBuilder 생성
      body: OrientationBuilder(
        // builder 의 parameter 의 context, orientation 설정
        builder: (context, orientation) {
          return GridView.count(
            // Orientation 이 portrait 일경우 2 , landscape 일때 는 3 이 설정값이 되야 됨
            crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
            // 100개의 List 생성 및 그것에 맞게 index 번호 생성
            // Generate 100 widgets that display their index in the List.
            children: List.generate(100, (index) {
              return Center(
                child: Text(
                  'Item $index',
                  style: Theme.of(context).textTheme.headline4,
                ),
              );
            }),
          );
        },
      ),
    );
  }
}

Kapture 2021-10-27 at 17 19 13

Work with tabs

  • TabController 를 사용해서 상단에 tab menu 를 만들고, 아래 body 부분에 contents 가 표시되게 state 를 연결합니다

Check point!

  • TabController 생성

  • Tabs 생성

  • 각 tab 에 맞는 content 생성(주로 state 로 page routing 으로 연결 함)

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // DefaultTabController 생성
      home: DefaultTabController(
        // 길이는 3
        length: 3,
        // child 는 Scaffold 를 생성해서
        child: Scaffold(
          appBar: AppBar(
            // appBar 밑에 bottom 위치에 TabBar Widget 에서 Tab 들의 icon text 를 설정함
            bottom: const TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
              ],
            ),
            title: const Text('Tabs Demo'),
          ),
          // TabBarView 위젯을 통해서 body 부분에 content 작성함 (주로 State() 사용해서 다른 page 의 contents 를 연결해서 사용함)
          body: const TabBarView(
            children: [
              Icon(
                Icons.directions_car,
                size: 100.0,
              ),
              Icon(
                Icons.directions_transit,
                size: 100.0,
              ),
              Icon(
                Icons.directions_bike,
                size: 100.0,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Kapture 2021-10-27 at 17 45 39


🔶 🔷 📌 🔑

Reference

Categories:

Updated:

Leave a comment