Flutter

[Flutter] 비만도 테스트(BMI Test)

에릭 Kim 2022. 6. 22. 14:18
반응형

Key Points

  • Validation의 활용

: 좀 더 복잡한 Validation은 package를 활용하여 설정할 수 있지만, 간단한 실습에서는 GlobalKey만 정의해줘도 Validation을 활용할 수 있습니다. 

  • TextFormField 값의 활용을 위한 TextEditingController

: TextFormField 혹은 TextField 위젯에 입력된 값은 TextEditingController를 사용하면 좀 더 간편하게 활용할 수 있습니다. 

  • Dispose 메소드

: Controller에서 활용한 객체가 제거될 때 변수에 할당된 메모리를 해제하기 위해서는 꼭 dispose 메소드를 사용하여야 합니다. ( 한번의 BMI 테스트가 끝나면, 값이 초기화 되어서 Main으로 돌아옴)

 

bmi_main.dart

import 'package:flutter/material.dart';

import 'BMI_result.dart';

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

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

class _BmiMainState extends State<BmiMain> {
  final _formKey = GlobalKey<FormState>(); // Validation을 위한 key 생성

  final _heightController =
      TextEditingController(); // textfield 관리를 위한 controller 생성
  final _weightController =
      TextEditingController(); // // textfield 관리를 위한 controller 생성

  @override
  void dispose() {
    // Controller 객체가 제거될 때 변수에 할당된 메모리를 해제하기 위해 dispose 메소드 사용

    _heightController.dispose();
    _weightController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar:
            AppBar(title: Text("BMI Test"), backgroundColor: Colors.lightGreen),
        body: Container(
            padding: const EdgeInsets.all(16),
            child: Form(
                key: _formKey,
                child: Column(
                  children: [
                    TextFormField(
                      decoration: InputDecoration(
                        // 외각선, 힌트 설정
                        border: OutlineInputBorder(),
                        hintText: 'Height',
                      ),
                      controller: _heightController,
                      keyboardType: TextInputType.number,
                      validator: (value) {
                        // 공백의 제거한 입력 값이 empty면, error 표시
                        if (value!.trim().isEmpty) {
                          return 'Input Height';
                        }
                        return null;
                      },
                    ),
                    SizedBox(
                      height: 16,
                    ),
                    TextFormField(
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        hintText: 'Weight',
                      ),
                      controller: _weightController,
                      keyboardType: TextInputType.number,
                      validator: (value) {
                        // 공백을 제거한 입력 값이 empty면, error 표시
                        if (value!.trim().isEmpty) {
                          return 'Input Weight';
                        }
                        return null;
                      },
                    ),
                    Container(
                        margin: const EdgeInsets.only(top: 16),
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            RaisedButton(
                              color: Colors.lightGreen,
                              onPressed: () {
                                if (_formKey.currentState!.validate()) {
                                  Navigator.push(
                                    context,
                                    MaterialPageRoute(
                                        builder: (context) => BmiResult(
                                            double.parse(
                                                // 문자열을 double 타입으로 받기 위해 double parse 함수 사용
                                                _heightController.text.trim()),
                                            double.parse(_weightController.text
                                                .trim()))),
                                  );
                                }
                              },
                              child: Text("Test"),
                            ),
                          ],
                        ))
                  ],
                ))));
  }
}

 

bmi_result.dart

import 'package:flutter/material.dart';

class BmiResult extends StatelessWidget {
  final double height; // 변수 생성
  final double weight;

  BmiResult(this.height, this.weight);

  @override
  Widget build(BuildContext context) {
    final bmi = weight / ((height / 100) * (height / 100)); // BMI  계산식
    print('bmi:$bmi');

    // double _showBmi(double bmi) {
    //   var show = bmi;
    //   return show;
    // }

    String _calcBmi(double bmi) {
      // BMI 구간을 나누는 메서드 생성
      var result = 'Underweight';
      if (bmi >= 35) {
        result = 'High obesity';
      } else if (bmi >= 30) {
        result = "Stage 2 obesity";
      } else if (bmi >= 25) {
        result = "stage 1 obesity";
      } else if (bmi >= 23) {
        result = 'Overweight';
      } else if (bmi >= 18.5) {
        result = 'Normal';
      }
      return result;
    }

    Widget _buildIcon(double bmi) {
      // BMI 구간에 따른 아이콘을 반환하는 메서드 생성.
      if (bmi >= 23) {
        return Icon(
          Icons.sentiment_very_dissatisfied,
          color: Colors.red,
          size: 100,
        );
      } else if (bmi >= 18.5) {
        return Icon(
          Icons.sentiment_satisfied,
          color: Colors.green,
          size: 100,
        );
      } else {
        return Icon(
          Icons.sentiment_dissatisfied,
          color: Colors.orange,
          size: 100,
        );
      }
    }

    return Scaffold(
        appBar:
            AppBar(title: Text("BMI Test"), backgroundColor: Colors.lightGreen),
        body: Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              _calcBmi(bmi), // 계산된 결과 반환
              style: TextStyle(fontSize: 36),
            ),
            SizedBox(
              height: 16,
            ),
            _buildIcon(bmi),
            SizedBox(
              height: 16,   // 결과에 따른 아이콘 반환
            ),
            Text(
              // BMI 출력
              "bmi: ${bmi}",
              style: TextStyle(fontWeight: FontWeight.bold),
            )
          ],
        )));
  }
}
반응형