Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีสร้างนาฬิกาดิจิตอลกับ TextView บน Android

การสร้างนาฬิกาดิจิตอล (Digital Clock) ด้วย TextView บน Android

ตัวอย่างนี้สาธิตการสร้างนาฬิกาดิจิตอลที่แสดงเวลาจริง (Real-time) พร้อมเอฟเฟกต์กะพริบ (Blinking) ของเครื่องหมาย ":" ระหว่างชั่วโมงและนาที โดยใช้ Handler และ Thread

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

สร้างโปรเจกต์ Android ใหม่ใน Android Studio

ขั้นตอนที่ 2: เพิ่มฟอนต์ (Optional - สำหรับลุกลักษนดิจิตอล)

ดาวน์โหลดฟอนต์ Orbitron (Digital style) วางไว้ที่ res/font/orbitron.ttf

ขั้นตอนที่ 3: ออกแบบ Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:gravity="center"
    android:background="#000000">

    <TextView
        android:id="@+id/tvClock"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="80sp"
        android:textStyle="bold"
        android:textColor="#00FF00"
        android:fontFamily="@font/orbitron"
        android:letterSpacing="0.1"
        tools:text="12:34" />
</LinearLayout>

ขั้นตอนที่ 4: MainActivity.java

package com.example.myapplication;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {
    private TextView tvClock;
    private Handler handler;
    private Runnable clockRunnable;
    private boolean isColonVisible = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvClock = findViewById(R.id.tvClock);
        handler = new Handler(Looper.getMainLooper());

        // เริ่มต้นนาฬิกา
        startClock();
    }

    private void startClock() {
        clockRunnable = new Runnable() {
            @Override
            public void run() {
                updateTime();
                // อัปเดตทุก 500ms เพื่อให้เครื่องหมาย : กะพริบ
                handler.postDelayed(this, 500);
            }
        };
        handler.post(clockRunnable);
    }

    private void updateTime() {
        // ใช้ SimpleDateFormat สำหรับจัดรูปแบบเวลา
        SimpleDateFormat sdf = new SimpleDateFormat(isColonVisible ? "HH:mm" : "HH mm", Locale.getDefault());
        String time = sdf.format(new Date());
        tvClock.setText(time);

        // สลับสถานะเครื่องหมาย :
        isColonVisible = !isColonVisible;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // สำคัญ: หยุด Handler เพื่อป้องกัน Memory Leak
        if (handler != null && clockRunnable != null) {
            handler.removeCallbacks(clockRunnable);
        }
    }
}

คำอธิบายการทำงาน

1. Handler + Runnable สำหรับ Periodic Update

handler.postDelayed(runnable, 500);
  • Handler ผูกกับ Main Thread (UI Thread) - ปลอดภัยสำหรับอัปเดต View
  • postDelayed รัน Runnable หลังจาก delay (ms) แล้ว Runnable เองจองครั้งถัดไป → Loop
  • 500ms = ครึ่งวินาที → ทำให้ ":" กะพริบทุก 0.5 วินาที

2. SimpleDateFormat รูปแบบเวลา

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm", Locale.getDefault());
  • HH : ชั่วโมง 24 ชม. (00-23)
  • mm : นาที (00-59)
  • ss : วินาที (00-59) - เพิ่มได้หากต้องการแสดงวินาที
  • สลับระหว่าง "HH:mm" และ "HH mm" เพื่อสร้างเอฟเฟกต์กะพริบ

3. การจัดการ Memory Leak

@Override
protected void onDestroy() {
    handler.removeCallbacks(clockRunnable);
    super.onDestroy();
}
  • ต้องลบ callback ทั้งหมดเมื่อ Activity ถูกทำลาย
  • มิฉะนั้น Handler จะยังคงรันต่อไป แม้ Activity จบแล้ว → Leak

การปรับปรุงแบบ Modern (API 26+ - java.time)

// ใช้ java.time (API 26+) แทน SimpleDateFormat (เก่า/ไม่ thread-safe)
private void updateTimeModern() {
    LocalTime now = LocalTime.now();
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(isColonVisible ? "HH:mm" : "HH mm");
    tvClock.setText(now.format(formatter));
    isColonVisible = !isColonVisible;
}

การเพิ่มฟีเจอร์เพิ่มเติม

1. แสดงวินาที (ไม่กะพริบ)

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
// handler.postDelayed(this, 1000); // อัปเดตทุก 1 วินาที

2. แสดงวันที่พร้อมกัน

SimpleDateFormat sdf = new SimpleDateFormat("EEE, MMM d, HH:mm", Locale.getDefault());
// ผลลัพธ์: Fri, Mar 15, 14:30

3. ใช้ TextClock Widget (API 17+ - 簡單ที่สุด)

<TextClock
    android:id="@+id/textClock"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:format12Hour="hh:mm:ss a"
    android:format24Hour="HH:mm:ss"
    android:textSize="80sp"
    android:textColor="#00FF00" />
  • TextClock จัดการเวลาและการอัปเดตอัตโนมัติ ไม่ต้องเขียนโค้ด Java
  • รองรับ 12/24 ชั่วโมง, Timezone, Formatting

การปรับแต่งลุกลักษณ์ (Styling)

  • สี: android:textColor="#00FF00" (เขียว螢光), #FF0000 (แดง), #FFFFFF (ขาว)
  • พื้นหลัง: android:background="#000000" สีดำคลาสสิค
  • เงา (Glow): ใช้ android:shadowColor, android:shadowRadius, android:shadowDx/Dy
  • ฟอนต์: ใช้ฟอนต์ Monospace หรือ Digital style (Orbitron, DS-Digital, Roboto Mono)

กรณีการใช้งานจริง

  • แอปนาฬิกา/แจ้งเตือน
  • Dashboard แสดงเวลาจริง
  • Kiosk/Display board
  • Stopwatch/Timer apps