[flutter] 디지털 시계 만들기

wonsama(71)
Published in
#zzan
Words
180
Reading
1 min
Listen
Play
7y

190830_스팀잇표지.002.jpeg

0. 참조 링크

Screenshot_1574786078.png

참조 : 플러터 바이너리 시계 만들기 - 파이어 쉽

아래 예제 소스를 잘 붙여만 넣어도 위 스샷처럼 이쁜 디지털 시계를 만들어 폰에 넣어서 다닐 수 있습니다 :) 아 이뽀 ~ ( 물론 이해하여 나만의 소스로 만들어 보는 것이 중요 하겠지만요 ㅜㅜ )

1. 초기 설정

1.1. 기본 시작 소스

intl 은 추가적으로 패키지를 추가 해줘야 한다. pubspec.yml 에 추가해주도록 한다.

file : pubspec.yaml

https://pub.dev/packages/intl

intl: ^0.16.0

file : main.dart

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show SystemChrome, DeviceOrientation;
import 'package:intl/intl.dart' show DateFormat;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Clock(),
      ),
    );
  }
}

1.2. 강제로 가로모드로 동작하도록 설정

SystemChrome 를 통해 화면 방향을 설정한다. (landscapeRight, landscapeLeft) 방향만 허가함.

void main() {
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeRight,
    DeviceOrientation.landscapeLeft,
  ]);
  runApp(MyApp());
}

2. Time 관련 설정하기

2.1. clock tick 초단위 흐름 만들기

DateTime 클래스를 활용하여 1초 단위로 시간을 주기적으로 업데이트 처리해주도록 한다.

class Clock extends StatefulWidget {
  Clock({Key key}) : super(key: key);

  @override
  _ClockState createState() => _ClockState();
}
class _ClockState extends State<Clock> {

  DateTime _now = DateTime.now(); // or BinaryTime see next step

  // Tick the clock
  @override
  void initState() {
    Timer.periodic(Duration(seconds: 1), (v) {
      setState(() {
        _now = DateTime.now(); // or BinaryTime see next step
      });
    });
    
    super.initState();
  }
}

2.2. 정수형을 이진수(바이너리)로 바꿔주기

시계는 기본적으로 14:23:55 or hh:mm:ss 와 같은 형태로 보여진다. BinaryTime 이라는 커스텀 클래스를 만들어서 UI에서 2진수 형태로 자릿수가 보여지도록 구성한다.

/// Utility class to access values as binary integers
class BinaryTime {
  List<String> binaryIntegers;

  BinaryTime() {
    DateTime now = DateTime.now();
    String hhmmss = DateFormat("Hms").format(now).replaceAll(':', '');

    binaryIntegers = hhmmss
        .split('')
        .map((str) => int.parse(str).toRadixString(2).padLeft(4, '0'))
        .toList();
  }

  get hourTens => binaryIntegers[0];
  get hourOnes => binaryIntegers[1];
  get minuteTens => binaryIntegers[2];
  get minuteOnes => binaryIntegers[3];
  get secondTens => binaryIntegers[4];
  get secondOnes => binaryIntegers[5];
}

3. 시계 UI

3.1. 2진수 형태 디지털 표현하기

이전에 만들어 놓은 Clock 클래스에 build 부분을 구성하며 해당 값을 위에 만들어 놓은 BinaryTime 이진수 변환기에 매칭 시켜 초기화 시켜준다. 또한 Timer.periodic 를 통해 초단위로 작업이 동작하도록 한다.

class Clock extends StatefulWidget {
  Clock({Key key}) : super(key: key);

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

class _ClockState extends State<Clock> {
  BinaryTime _now = BinaryTime();

  // Tick the clock
  @override
  void initState() {
    Timer.periodic(Duration(seconds: 1), (v) {
      setState(() {
        _now = BinaryTime();
      });
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(50),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          // Columns for the clock
          ClockColumn(
            binaryInteger: _now.hourTens,
            title: 'H',
            color: Colors.blue,
            rows: 2,
          ),
          ClockColumn(
            binaryInteger: _now.hourOnes,
            title: 'h',
            color: Colors.lightBlue,
          ),
          ClockColumn(
            binaryInteger: _now.minuteTens,
            title: 'M',
            color: Colors.green,
            rows: 3,
          ),
          ClockColumn(
            binaryInteger: _now.minuteOnes,
            title: 'm',
            color: Colors.lightGreen,
          ),
          ClockColumn(
            binaryInteger: _now.secondTens,
            title: 'S',
            color: Colors.pink,
            rows: 3,
          ),
          ClockColumn(
            binaryInteger: _now.secondOnes,
            title: 's',
            color: Colors.pinkAccent,
          ),
        ],
      ),
    );
  }
}

3.2. 개별 시계 열 만들기

각 열은 4개의 셀로 나눠있으며 해당 값은 2진수 형태로 표현된다. 만약이 셀이 활성화 되면 지정한 색상을 표현한다.

/// Column to represent a binary integer.
class ClockColumn extends StatelessWidget {
  String binaryInteger;
  String title;
  Color color;
  int rows;
  List bits;

  ClockColumn({this.binaryInteger, this.title, this.color, this.rows = 4}) {
    bits = binaryInteger.split('');
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        ...[
          Container(
            child: Text(
              title,
              style: Theme.of(context).textTheme.display1,
            ),
          )
        ],
        ...bits.asMap().entries.map((entry) {
          int idx = entry.key;
          String bit = entry.value;

          bool isActive = bit == '1';
          int binaryCellValue = pow(2, 3 - idx);

          return AnimatedContainer(
            duration: Duration(milliseconds: 475),
            curve: Curves.ease,
            height: 40,
            width: 30,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(5)),
              color: isActive
                  ? color
                  : idx < 4 - rows
                      ? Colors.white.withOpacity(0)
                      : Colors.black38,
            ),
            margin: EdgeInsets.all(4),
            child: Center(
              child: isActive
                  ? Text(
                      binaryCellValue.toString(),
                      style: TextStyle(
                        color: Colors.black.withOpacity(0.2),
                        fontSize: 18,
                        fontWeight: FontWeight.w700,
                      ),
                    )
                  : Container(),
            ),
          );
        }),
        ...[
          Text(
            int.parse(binaryInteger, radix: 2).toString(),
            style: TextStyle(fontSize: 30, color: color),
          ),
          Container(
            child: Text(
              binaryInteger,
              style: TextStyle(fontSize: 15, color: color),
            ),
          )
        ]
      ],
    );
  }
}

기타

혹시 A RenderFlex overflowed by 25 pixels on the bottom. 이런 유사 메시지가 나왔다면 EdgeInsets.all(25) (50->25) 이런 식으로 처리하면 됩니다.

맺음말

[flutter] 디지털 시계 만들기 | Ecency