flutter/조금 매운맛 (중급)

[flutter2.0] 3~5강 | 로그인과 주사위 앱 만들기

lgvv 2021. 8. 17. 13:44

✅이번 시간에는 로그인과 주사위 앱 만들기에 대해서 알아볼 예정이야. 

뭔가 생각보다 새로이 보는 것들이 많았고, 디자인 패턴이나 클린 코드에 대해서 플러터는 상당히 중요할 것 같다는 생각이 확 들었어.

코드를 보면서 그럼 함께 보도록 하자.

 

플러터 개발에 있어서, 코드를 쭉 읽어보면서 지나가자

 

✅플러터 화면 중 일부

화면 UI중 일부

 

 

✅main.dart

// main.dart
import 'package:flutter/material.dart';
import 'dice.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Dice game',
      home: LogIn(),
    );
  }
}

class LogIn extends StatefulWidget {
  @override
  _LogInState createState() => _LogInState();
}

class _LogInState extends State<LogIn> {
  TextEditingController controller1 =
      TextEditingController(); // 텍스트 필드에 읿력된 값을 읽어야 할때
  TextEditingController controller2 = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Log in'),
          backgroundColor: Colors.redAccent,
          centerTitle: true,
          leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
          actions: <Widget>[
            IconButton(icon: Icon(Icons.search), onPressed: () {})
          ],
        ),
        body: Builder( // 스캐폴드 메신저를 날리기 위해서 Builder가 필요해
          builder: (context) {
            return GestureDetector( // 화면 터치하는거 감지하게끔 - 이렇게 해서 키보드 밖에 터치지 작동하게끔 만들려고
              onTap: () {
                FocusScope.of(context).unfocus(); // 화면에 빈 공간 클릭하면 여기 하위에 걸리는 위젯들이 포커스 다 놓게끔 만들기
              },
              child: SingleChildScrollView(
                // 키보드가 화면을 가리는데 키보드가 올라오면서 스크롤이 가능하게끔 바꿔줌
                child: Column(
                  children: [
                    Padding(padding: EdgeInsets.only(top: 50)),
                    Center(
                      child: Image(
                        image: AssetImage('image/chef.gif'),
                        width: 170,
                        height: 190,
                      ),
                    ),
                    Form(
                      // 웹에서 Form 형식 보이던데, 데이터를 전달하기 위한 코드
                      child: Theme(
                        data: ThemeData(
                            primaryColor: Colors.teal,
                            inputDecorationTheme: InputDecorationTheme( // 입력하는 부분 커스텀
                                labelStyle: TextStyle(
                                    color: Colors.teal, fontSize: 15.0))),
                        child: Container(
                          padding: EdgeInsets.all(40.0),
                          child: Column(
                            children: [
                              TextField(
                                //autofocus: true, // 포커스 자동으로 잡기 - 키보드 내려가게 구현하려
                                controller: controller1,
                                decoration:
                                    InputDecoration(labelText: 'Enter "dice"'),
                                keyboardType:
                                    TextInputType.emailAddress, // 키보드 타입
                              ),
                              TextField(
                                controller: controller2,
                                decoration:
                                    InputDecoration(labelText: 'Enter Password'),
                                // 텍스트 필드 위의 레이블                        keyboardType: TextInputType.text, // 키보드 타입
                                obscureText: true, // 텍스트 필드 입력할 때 비밀번호 점으로 바뀌게끔
                              ),
                              SizedBox(
                                height: 40.0,
                              ),
                              ButtonTheme(
                                  // 버튼 데이터를 받기 위함.
                                  minWidth: 100, // 최소 너비
                                  height: 50,
                                  child: ElevatedButton(
                                    onPressed: () {
                                      if (controller1.text == 'dice' &&
                                          controller2.text == '1234') {
                                        Navigator.push(
                                            context,
                                            MaterialPageRoute(
                                                builder:
                                                    (BuildContext context) =>
                                                        Dice()));
                                      } else if (controller1.text != 'dice' &&
                                          controller2.text == '1234') {
                                        showSnackBar2(context);
                                      } else if (controller1.text == 'dice' &&
                                          controller2.text != '1234') {
                                        showSnackBar3(context);
                                      } else {
                                        showSnackBar(context);
                                      }
                                    },
                                    child: Icon(Icons.arrow_forward),
                                    style: ElevatedButton.styleFrom(
                                      primary: Colors.orangeAccent,
                                    ),
                                  ))
                            ],
                          ),
                        ),
                      ),
                    )
                  ],
                ),
              ),
            );
          },
        ));
  }
}

void showSnackBar(BuildContext context) {
  ScaffoldMessenger.of(context).showSnackBar(// 스캐폴드메신저 만들기
      // 가장 가까운 스캐폴드 찾아서 반환해
      SnackBar(
    // 스낵바
    content: Text('로그인 정보 다시 확인해'), // 내
    duration: Duration(seconds: 2),
    backgroundColor: Colors.blue,
  ));
}

void showSnackBar2(BuildContext context) {
  ScaffoldMessenger.of(context).showSnackBar(// 스캐폴드메신저 만들기
      // 가장 가까운 스캐폴드 찾아서 반환해
      SnackBar(
    // 스낵바
    content: Text('dice 철자 확인해'), //
    duration: Duration(seconds: 2),
    backgroundColor: Colors.blue,
  ));
}

void showSnackBar3(BuildContext context) {
  ScaffoldMessenger.of(context).showSnackBar(// 스캐폴드메신저 만들기
      // 가장 가까운 스캐폴드 찾아서 반환해
      SnackBar(
    // 스낵바
    content: Text('비밀번호 불일치'),
    duration: Duration(seconds: 5),
    backgroundColor: Colors.blue,
  ));
}

 

✅dice.dart

// dice.dart
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:fluttertoast/fluttertoast.dart';

class Dice extends StatefulWidget {
  @override
  _DiceState createState() => _DiceState();
}

class _DiceState extends State<Dice> {
  int leftDice = 1;
  int rightDice = 1;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.redAccent,
      appBar: AppBar(
        backgroundColor: Colors.redAccent,
        title: Text('Dice game'),
      ),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Padding(
            padding: EdgeInsets.all(32.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Expanded( // 화면 최대 길이로 요소 확
                    //flex: 2, // 웹에서 해봤으면 flex 통해서 이미지 비율 조정가능
                    child: Image.asset('image/dice$leftDice.png')),
                // 가로방향 끝까지 확장
                SizedBox(
                  width: 20,
                ),
                Expanded(child: Image.asset('image/dice$rightDice.png')),
                // 이미지 2개면 나눠서 가져감
              ],
            ),
          ),
          SizedBox(
            height: 20,
          ),
          ButtonTheme( // 버튼의 모양 같은거 조정할 때 이걸로 감쌈
            minWidth: 100.0,
            height: 60.0,
            child: ElevatedButton(
              onPressed: () {
                setState(() {
                  leftDice = Random().nextInt(6) + 1;
                  rightDice = Random().nextInt(6) + 1;
                });
                showToast('Left Dice $leftDice , Right Dice $rightDice');
              },
              child: Icon(Icons.play_arrow),
              style: ElevatedButton.styleFrom(
                primary: Colors.orangeAccent,
              ),
            ),
          )
        ],
      )),
    );
  }
}

void showToast(String message) {
  Fluttertoast.showToast(
    msg: message,
    backgroundColor: Colors.grey,
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.BOTTOM,
  );
}