小项目开发——Timer + TimerTask 实现数字时钟

目录

小项目开发——Timer + TimerTask 实现数字时钟

1. 题目

Timer+TimerTask实现数字时钟.

◼ 期望最终效果:


2. 结构分析

◼ 主要分为 3 个大模块:导航栏背景时钟.

◼ 当然,与这 3 大模块相关的小模块也有许多.


3. 模块思维导图

在这里插入图片描述


4. Layout

◼ Android 开发首先应设计好页面布局(activity_my_digital_clock.xml).

◼ 布局idcl_wzy_digitalclock.

⑴ 视图

◼ 主要是 时钟模块 的6个TextView

⑵ 导航栏 LOGO

◼ 在这个网站上寻找到了时钟 LOGO 资源:Search results for Clock - Flaticon.

◼ 并将图片资源 icon_clock.png 导入到了 res/drawable 中.

◼ 同时编写了相应的 clock.xml 文件,将其修改为白色以适配导航栏的背景色.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <bitmap android:src="@drawable/icon_clock" android:tint="@color/white" />
    </item>
</layer-list>

在这里插入图片描述

⑶ Android 七段数码管字体

◼ 在这个网站上寻找到了字体资源:DS-Digital Font | dafont.com.

◼ 并将字体资源 ds_digi.TTF 导入到了 res/font 文件夹中.

◼ 然后在 xml 文件的组件中以如下方式使用该字体.

android:fontFamily="@font/ds_digi"

在这里插入图片描述

⑷ 代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/cl_wzy_digitalclock"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyDigitalClockActivity">

    <TextView
        android:id="@+id/tv_time_hmin"
        android:layout_width="296dp"
        android:layout_height="131dp"
        android:fontFamily="@font/ds_digi"
        android:gravity="center"
        android:text="00:00"
        android:textSize="130sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.139"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.305" />

    <TextView
        android:id="@+id/tv_week"
        android:layout_width="50dp"
        android:layout_height="36dp"
        android:layout_marginTop="4dp"
        android:text="Week"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.243"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_time_hmin"
        app:layout_constraintVertical_bias="0.007" />

    <TextView
        android:id="@+id/tv_AMorPM"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="13dp"
        android:text="AM"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toEndOf="@+id/tv_time_hmin"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.3" />

    <TextView
        android:id="@+id/tv_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="xxxx/xx/xx"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.566"
        app:layout_constraintStart_toEndOf="@+id/tv_week"
        app:layout_constraintTop_toBottomOf="@+id/tv_time_hmin"
        app:layout_constraintVertical_bias="0.017" />

    <TextView
        android:id="@+id/tv_time_second"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/ds_digi"
        android:text="00"
        android:textSize="48sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.13"
        app:layout_constraintStart_toEndOf="@+id/tv_time_hmin"
        app:layout_constraintTop_toBottomOf="@+id/tv_AMorPM"
        app:layout_constraintVertical_bias="0.018" />

    <TextView
        android:id="@+id/tv_timezone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="92dp"
        android:text="北京时间"
        android:textSize="20sp"
        app:layout_constraintBottom_toTopOf="@+id/tv_time_hmin"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

</androidx.constraintlayout.widget.ConstraintLayout>

5. Activity

◼ 文件名:MyDigitalClockActivity.java

⑴ 私有成员变量

private ConstraintLayout clClock; // 布局
private TextView mTimezoneTv; // 时区名
private TextView mHminTv, mSecondTv; // 时间文本
private TextView mAMorPMTv; // 上下午文本
private TextView mWeekTv; // 周数文本
private TextView mDataTv; // 日期文本
private Timer mTimer; // Timer 对象
private TimeZone mTimeZone; // 设置时区
private Calendar mCalendar; // 日历类对象
private ActionBar actionBar; // ActionBar 对象

⑵ 自定义初始化函数

◼ API

/*
 * 对只用初始化一次的类成员初始化
 */
public void init() {
    clClock = (ConstraintLayout) findViewById(R.id.cl_wzy_digitalclock);
    mTimezoneTv = (TextView) findViewById(R.id.tv_timezone);
    mHminTv = (TextView) findViewById(R.id.tv_time_hmin);
    mSecondTv = (TextView) findViewById(R.id.tv_time_second);
    mAMorPMTv = (TextView) findViewById(R.id.tv_AMorPM);
    mWeekTv = (TextView) findViewById(R.id.tv_week);
    mDataTv = (TextView) findViewById(R.id.tv_data);
    mTimer = new Timer();
    mTimeZone = TimeZone.getTimeZone("GMT+8:00"); // 北京时间
    actionBar = getSupportActionBar(); // 获取 ActionBar
} // end init

⑶ 导航栏模块

◼ API

/*
 * 自定义导航栏样式
 */
public void setActionBar() {
    actionBar.setTitle("  MyDigitalClock——WZY"); // 设置标题
    actionBar.setDisplayShowHomeEnabled(true);
    actionBar.setLogo(R.drawable.clock); // 设置 LOGO
    actionBar.setDisplayUseLogoEnabled(true);
} // end setActionBar

注:改了一下原题目预期实现效果的导航栏效果.

⑷ 背景模块

◼ 在 白天 时:背景颜色白色,所有 字体颜色黑色

◼ 在 夜晚 时,背景颜色黑色,所有 字体颜色白色.

注:这是我自己加的一个小功能(详见6. 最终效果).

◼ API

API说明
setAllTextViewColor一次性修改所有TextView的字体颜色
changeLayoutColor根据当前小时数改变背景颜色和字体颜色
/*
 * 一次性修改所有 TextView 的字体颜色
 *
 * @Param color 字体颜色
 */
public void setAllTextViewColor(int color) {
    // 将所有的 TextView 保存在数组中
    TextView[] textViews = new TextView[]{mTimezoneTv, mHminTv, mSecondTv, mAMorPMTv, mWeekTv, mDataTv};
    /* 循环遍历数组,依次设置字体颜色 */
    for (TextView textView : textViews) {
        textView.setTextColor(color);
    }
} // end setAllTextViewColor

/*
 * 根据当前小时数改变背景颜色和字体颜色
 *
 * @Param hour 当前小时数
 */
public void changeLayoutColor(int hour) {
    if (hour >= 6 && hour < 18) {
        /* 如果是白天,设置背景颜色为白色,字体颜色为黑色 */
        clClock.setBackgroundColor(Color.WHITE);
        setAllTextViewColor(Color.BLACK);
    } else {
        /* 如果是夜晚,设置背景颜色为黑色,字体颜色为白色 */
        clClock.setBackgroundColor(Color.BLACK);
        setAllTextViewColor(Color.WHITE);
    }
} // end changeLayoutColor

⑸ 时钟模块

◼ API

API说明
getCurrentHminTime获取当前时间的小时和分钟数
getCurrentSecondTime获取当前时间的秒数
getCurrentAMorPM显示当前时间是上午还是下午
getCurrentWeek获取周数
getCurrentData获取日期
updateClockTask使用TimerTask更新时钟
onDestroy关闭定时器,防止内存泄露
/*
 * 获取当前时间的小时和分钟数
 */
public String getCurrentHminTime() {
    int hour = mCalendar.get(Calendar.HOUR_OF_DAY); // HOUR_OF_DAY:24小时制
    int min = mCalendar.get(Calendar.MINUTE);
    changeLayoutColor(hour); // 改变页面背景和字体颜色
    return String.format(Locale.CHINA, "%02d:%02d", hour, min);
} // end getCurrentHminTime

/*
 * 获取当前时间的秒数
 */
public String getCurrentSecondTime() {
    int second = mCalendar.get(Calendar.SECOND);
    return String.format(Locale.CHINA, "%02d", second);
} // end getCurrentSecondTime

/*
 * 显示当前时间是上午还是下午
 */
public String getCurrentAMorPM() {
    if (mCalendar.get(Calendar.AM_PM) == Calendar.AM) {
        return "AM"; // 上午
    } else {
        return "PM"; // 下午
    }
} // end getCurrentAMorPM

/*
 * 获取周数
 */
public String getCurrentWeek() {
    String[] weeks = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
    int week = mCalendar.get(Calendar.DAY_OF_WEEK) - 1;
    return weeks[week];
} // end getCurrentWeek

/*
 * 获取日期
 */
public String getCurrentData() {
    int year = mCalendar.get(Calendar.YEAR);
    int month = mCalendar.get(Calendar.MONTH) + 1; // Calendar.MONTH:0~11
    int day = mCalendar.get(Calendar.DAY_OF_MONTH);
    return String.format(Locale.CHINA, "%d/%d/%d", year, month, day);
} // end getCurrentData

/*
 * 使用 TimerTask 更新时钟
 */
public void updateClockTask() {
    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            runOnUiThread(() -> {
                /* 更新 Calendar 和 TextView */
                mCalendar = Calendar.getInstance(mTimeZone);
                mHminTv.setText(getCurrentHminTime());
                mSecondTv.setText(getCurrentSecondTime());
                mAMorPMTv.setText(getCurrentAMorPM());
                mWeekTv.setText(getCurrentWeek());
                mDataTv.setText(getCurrentData());
            }); // end runOnUiThread
        } // end run
    }; // end new TimerTask()
    mTimer.schedule(timerTask, 0, 1000); // 每秒更新一次时钟
} // end updateClockTask

/*
 * 关闭定时器,防止内存泄露
 */
protected void onDestroy() {
    super.onDestroy();
    mTimer.cancel();
    mTimer = null;
} // end onDestroy

⑹ onCreate

◼ API

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

    init(); // 初始化
    setActionBar(); // 自定义导航栏样式
    updateClockTask(); // 更新时钟
} // end onCreate

6. 最终效果

在这里插入图片描述


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值