ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Flutter: 로그인 & 주사위 게임 실습
    공부 기록/Flutter 2021. 11. 27. 18:37
    728x90

    https://www.youtube.com/watch?v=mQX_kJKnZzk&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=3

    SingleChildScrollView 위젯은. 키보드 입력 시 화면이 잘려보이기 때문에 스크롤할 수 있도록 Column위젯을 해당 위젯으로 감쌈. 

     

    https://flutter.dev/docs/cookbook/forms/text-field-changes#2-use-a-texteditingcontroller

     

    Handle changes to a text field

    How to detect changes to a text field.

    docs.flutter.dev

    TextEditingController: 텍스트 폼에 입력한 데이터를 가지고 오는

    생성자 생성한 후에 해당 변수 이름을 TextForm의 인자로 전달해주어야 함: controller: {NAME} -> 해당 텍스트폼에 입력한 데이터를 가지고옴

     

    복습 18, 19, 22  -> done

     

    https://www.youtube.com/watch?v=mmR2u8TgoCk&list=PLQt_pzi-LLfoOpp3b-pnnLXgYpiFEftLB&index=7 

    키보드가 아닌 화면을 누르면 키보드가 사라지는 기능을 구현해보자. 이럴 때 GestureDetecter 위젯 사용.(사용자의 행동을 감지하는 위젯 . 길게 누르기 연속 두번 누르기 등의 액션)

    화면의 빈 곳이 사용자의 액션에 반응하는 버튼처럼 작동해야하므로 SingleChildScroolView에 위젯으로 감싸고, 

     그 중에서 빈 화면을 탭했을 때 반응하는 기능을 위해 onTap() method 이용.

    텍스트 필드는 다음 Focus와 관련이 있다. 무엇일까?

    FocusScope.of(context): 이것을 통해 현재 텍스트 필드와 연결되어 있는 포커스 노드를 찾을 수 있다. (참고)
    그리고 unfucs() method가 포커스를 없애고 키보드를 사라지게 한다. 

     

    FocusScope class - widgets library - Dart API

    A FocusScope is similar to a Focus, but also serves as a scope for its descendants, restricting focus traversal to the scoped controls. For example a new FocusScope is created automatically when a route is pushed, keeping the focus traversal from moving to

    api.flutter.dev

     body: Builder(
              builder: (context){
              return GestureDetector(
                onTap: (){  // 사용자가 빈 곳을 누를때 작동하는 함수
                  FocusScope.of(context).unfocus(); // 해당 포커스의 범위가 포커스에서 해제된다(unfocus)
                },

    포커스를 받는 텍스트 필드가 없어야 올라와있는 키보드를 내려가게 할 수 있다? 

     

    Colum이나 Row 위젯 내의 요소를 정렬할때는 mainAxisAlignment를 이용하자. 

          body: Center(
            child: Column(
              // crossAxisAlignment:  CrossAxisAlignment.center, -> 이거 대신 Row widget에서 한번 더 정렬해주어야함.
              mainAxisAlignment: MainAxisAlignment.center, // 주축 정렬 설정, 즉 cloum의 주축인 세로축 정렬 설정 -> 중앙
              children: <Widget> [
                Row(
                  mainAxisAlignment: MainAxisAlignment.center, // 가로축으로 중앙
                  children: [
                    Image.asset('image/dice1.png')
                    // Image(   이렇게 구현하는 것보다 위와 같이 Image.asset을 이용하면 더 간단 
                    //   image: AssetImage('image/dice1.png'),
                    //   width: 300.0,
                    //   //alignment: Alignment.center -> 가운데 정렬이 이거라고 생각했는 Colmun 위젯에서 정렬은 mainAxisAlignment 위젯을 사용해야함
                    // )
                  ],

    Expanded 위젯은 해당 공간(여기서는 Row)에 맞도록 요소를 확장하는 기능을 한다. Row에 두 개의 이미지를 배치하고 그 이미지들이 Row내에 가득차도록 확장.

    flex 속성을 이용할 수도 있음

    둘의 간격을 조정하려면 Padding widget으로 감싸기

     

    마지막으로 left/rightDice 변수를 선언하고, Random함수를 이용하여 임의의 숫자가 나오도록 한다. 이 때 dart: math;를 임포트해주어야 한다.

    import 'dart:math';
    
    class _DiceState extends State<Dice> {
    
      int leftDice = 1;
      int rightDice = 1;
      
    .
    .
    
    onPressed: (){
     setState( () {
       leftDice = Random().nextInt(6) + 1;
       rightDice = Random().nextInt(6) + 1;
     });
     showToast("Left dice: {$leftDice}, Right dice: {$rightDice}");
     },

    임의의 숫자에 따라 보여지는 이미지들도 다르게 보이도록 Expanded(child: Image.asset('image/dice$leftDice.png')) 으로 변경해준다. 이 때는 {}을 안 써줘도 되는군.

    dice.dart 파일의 전체 코드

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'dart:math';
    import 'package:fluttertoast/fluttertoast.dart'; // toast 메시지 구현을 위한 라이브러리
    
    class Dice extends StatefulWidget {
      @override
      State<Dice> 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(
              // crossAxisAlignment:  CrossAxisAlignment.center, -> 이거 대신 Row widget에서 한번 더 정렬해주어야함.
              mainAxisAlignment: MainAxisAlignment.center, // 주축 정렬 설정, 즉 Column 주축인 세로축 정렬 설정 -> 중앙
              children: <Widget> [
                Padding( // 주사위가 있는 Row의 간격을 조절하기 위하여 Padding widget으로 감쌈
                  padding: EdgeInsets.all(32.0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center, // 가로축으로 중앙정렬
                    children: [
                      Expanded(child: Image.asset('image/dice$leftDice.png')),
                      SizedBox(width: 20.0,), // 주사위 사이에 간격 조절
                      Expanded(child: Image.asset('image/dice$rightDice.png'))
                    ],
                  ),
                ),
                SizedBox(
                  width: 60.0,
                ),
                ButtonTheme(
                  minWidth: 88.0,
                  height: 60.0,
                  buttonColor: Colors.orangeAccent,
                  hoverColor: Colors.white,
                  child: ElevatedButton(
                    child: Icon(
                      Icons.play_arrow,
                      color: Colors.white,
                      size: 50.0,
                    ),
                     onPressed: (){
                      setState( () {
                        leftDice = Random().nextInt(6) + 1;
                        rightDice = Random().nextInt(6) + 1;
                      });
                      showToast("Left dice: {$leftDice}, Right dice: {$rightDice}");
                      },
                   ),
                  ),
              ],
            )
          ),
        );
      }
    }
    
    void showToast(String msg){
      Fluttertoast.showToast(
        msg: msg,
        backgroundColor: Colors.white,
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.TOP_LEFT);
    }

     

    이로써 샘플앱을 드디어 완성했다 :)
    너무나 쉽게 그리고 가장 기본적인 개념들도 잘 잡아주신 코딩쉐프님 덕에 이번 실습은 포기하지 않고 끝까지 할 수 있게되었다. 감사합니다!!!

    댓글

Designed by Tistory.