Android手机简易计时器(Chronometer实现)

一、关于Chronometer

在Android的SDK中,为我们提供了一个计时器,这个计时器称为Chronometer。其拥有以下方法:

1、getBase():返回时间;
2、setBase(long base):设置计时器的起始时间;
3、start():开始计时;
4、stop():停止计时;
5、setFormat(String format):设置显示时间的格式;
6、setOnChronometerTickListener(Chronometer.OnChronometerTickListener listener):为计时器绑定监听事件。

注意点:我们在使用Chronometer的stop方法时,只是停止刷新计时器的时间显示,在后台并没有停止计时。我们再次恢复计时时,并不是从我们刚才停下的时间开始计时。为了实现真正的恢复计时,我们可以设置一个变量用于记录停止计时的时间。当我们再次恢复计时时,使用当SystemClock.elapsedRealtime()减去该变量,跳过已经记录时间即可。

二、activity_main.xml文件

整体布局为LinearLayout线性布局,第一个LinearLayout中包含Chronomete计时器用来显示时间;第二个LinearLayout包括四个时间控制按钮分别为:开始计时按钮begin,停止计时按钮end,恢复计时按钮goon和重置计时按钮reset。布局预览效果如下:
在这里插入图片描述
实际运行效果图如下:
在这里插入图片描述
activity_main.xml的源代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:gravity="center_horizontal">
    <Chronometer
        android:id="@+id/timer"
        android:textSize="25pt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/begin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="开始计时"/>

        <Button
            android:id="@+id/end"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="停止计时" />
        <Button
            android:id="@+id/goon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="恢复计时"/>
        <Button
            android:id="@+id/reset"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="重置计时"/>
    </LinearLayout>
</LinearLayout>

三、MainActivity.java文件

1、定义变量

Chronometer ch;//计时器
Button begin;//开始计时按钮
Button end;//结束计时按钮
Button goon;//继续计时按钮
Button reset;//重置计时按钮
long recordingTime;//记录总时间

2、在onCreate方法中获取各按钮id和计时器Chronometer id(注意要与xml文件id名一一对应)

ch=(Chronometer)findViewById(R.id.timer);
begin=(Button)findViewById(R.id.begin);
end=(Button)findViewById(R.id.end);
goon=(Button)findViewById(R.id.goon);
reset=(Button)findViewById(R.id.reset);

3、设置四个计时按钮的监听事件
(1)开始计时按钮begin监听事件

begin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ch.setBase(SystemClock.elapsedRealtime()-recordingTime);//SystemClock.elapsedRealtime()获取的是系统开机到现在的时间,不能被修改
                ch.start();//开始计时
                begin.setEnabled(false);
                end.setEnabled(true);
                goon.setEnabled(false);
                reset.setEnabled(true);
            }
        });

(2)结束计时按钮end监听事件

end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ch.stop();//停止计时
                recordingTime=SystemClock.elapsedRealtime()-ch.getBase();//保存当前停止的时间
                begin.setEnabled(false);
                goon.setEnabled(true);
                end.setEnabled(false);
                reset.setEnabled(true);
            }
        });

(3)恢复计时按钮goon监听事件

goon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ch.start();
                begin.setEnabled(false);
                end.setEnabled(true);
                goon.setEnabled(false);
                reset.setEnabled(true);
            }
        });

(4)重置计时按钮reset监听事件

reset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                recordingTime=0;//将当前时间置为0
                ch.start();
                ch.setBase(SystemClock.elapsedRealtime());
                begin.setEnabled(false);
                goon.setEnabled(false);
                end.setEnabled(true);
                reset.setEnabled(false);
            }
        });

注意点:各按钮监听事件中的setEnabled()函数:当setEnable(false)将控件能完全禁用,颜色会变灰色,无法响应任何触发事件;当setEnable(true)相当于激活按钮,可以通过触摸或点击产生触发事件。

其中完整MainActivity.java的源代码如下:

package com.wp.timer;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;

public class MainActivity extends AppCompatActivity{
    Chronometer ch;//计时器
    Button begin;//开始计时按钮
    Button end;//结束计时按钮
    Button goon;//继续计时按钮
    Button reset;//重置计时按钮
    long recordingTime;//记录总时间
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ch=(Chronometer)findViewById(R.id.timer);
        begin=(Button)findViewById(R.id.begin);
        end=(Button)findViewById(R.id.end);
        goon=(Button)findViewById(R.id.goon);
        reset=(Button)findViewById(R.id.reset);
        begin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ch.setBase(SystemClock.elapsedRealtime()-recordingTime);//SystemClock.elapsedRealtime()获取的是系统开机到现在的时间,不能被修改
                ch.start();//开始计时
                begin.setEnabled(false);
                end.setEnabled(true);
                goon.setEnabled(false);
                reset.setEnabled(true);
            }
        });
        end.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ch.stop();//停止计时
                recordingTime=SystemClock.elapsedRealtime()-ch.getBase();//保存当前停止的时间
                begin.setEnabled(false);
                goon.setEnabled(true);
                end.setEnabled(false);
                reset.setEnabled(true);
            }
        });
        goon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ch.start();
                begin.setEnabled(false);
                end.setEnabled(true);
                goon.setEnabled(false);
                reset.setEnabled(true);
            }
        });
        reset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                recordingTime=0;//将当前时间置为0
                ch.start();
                ch.setBase(SystemClock.elapsedRealtime());
                begin.setEnabled(false);
                goon.setEnabled(false);
                end.setEnabled(true);
                reset.setEnabled(false);
            }
        });
        ch.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {//为Chronomter绑定事件监听器
            @Override
            public void onChronometerTick(Chronometer chronometer) {
                if(SystemClock.elapsedRealtime()-ch.getBase()>3600*1000)//若计时超过了3600s=1 h即停止计时
                {
                    ch.stop();
                    begin.setEnabled(true);
                    end.setEnabled(false);
                    goon.setEnabled(false);
                }
            }
        });
    }
}

四、运行效果展示

1、开始计时
在这里插入图片描述
2、停止计时
在这里插入图片描述
恢复计时和重置技术效果展示不明显,可以自行实现观察效果。

很高兴回答您的问题。以下是一份基于Android简易倒计时APP的设计与实现的代码: 1. 设计界面 首先,我们需要在布局文件中设计界面。我们可以使用TabLayout和ViewPager来创建不同的选项卡,每个选项卡对应不同的功能。在计时器选项卡中,我们可以使用Chronometer控件来显示倒计时。在闹钟选项卡中,我们可以使用TimePicker控件来设置闹钟时间。在世界时钟选项卡中,我们可以使用Spinner控件来选择不同的城市。在秒表选项卡中,我们可以使用Chronometer控件来显示计时。 2. 编写逻辑代码 接下来,我们需要编写逻辑代码。我们可以使用广播接收器来接收系统发送的闹钟广播,从而触发闹钟功能。我们还可以使用SQLite数据库来存储用户设置的闹钟信息。 我们可以在MainActivity中创建四个Fragment,分别对应不同的选项卡。在每个Fragment中,我们可以编写相应的逻辑代码。 计时器选项卡代码示例: ``` public class TimerFragment extends Fragment { private Chronometer chronometer; private Button startButton, pauseButton, resetButton; public TimerFragment() {} @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_timer, container, false); chronometer = view.findViewById(R.id.chronometer); startButton = view.findViewById(R.id.start_button); pauseButton = view.findViewById(R.id.pause_button); resetButton = view.findViewById(R.id.reset_button); startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chronometer.start(); } }); pauseButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chronometer.stop(); } }); resetButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chronometer.setBase(SystemClock.elapsedRealtime()); } }); return view; } } ``` 闹钟选项卡代码示例: ``` public class AlarmFragment extends Fragment { private TimePicker timePicker; private Button setButton, cancelButton; private AlarmManager alarmManager; private PendingIntent alarmIntent; public AlarmFragment() {} @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_alarm, container, false); timePicker = view.findViewById(R.id.time_picker); setButton = view.findViewById(R.id.set_button); cancelButton = view.findViewById(R.id.cancel_button); alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); Intent intent = new Intent(getActivity(), AlarmReceiver.class); alarmIntent = PendingIntent.getBroadcast(getActivity(), 0, intent, 0); setButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, timePicker.getHour()); calendar.set(Calendar.MINUTE, timePicker.getMinute()); calendar.set(Calendar.SECOND, 0); long timeInMillis = calendar.getTimeInMillis(); if (System.currentTimeMillis() < timeInMillis) { alarmManager.set(AlarmManager.RTC_WAKEUP, timeInMillis, alarmIntent); Toast.makeText(getActivity(), "闹钟设置成功", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getActivity(), "无效的闹钟时间", Toast.LENGTH_SHORT).show(); } } }); cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { alarmManager.cancel(alarmIntent); Toast.makeText(getActivity(), "闹钟已取消", Toast.LENGTH_SHORT).show(); } }); return view; } } ``` 世界时钟选项卡代码示例: ``` public class WorldClockFragment extends Fragment { private Spinner citySpinner; private TextView timeTextView; public WorldClockFragment() {} @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_world_clock, container, false); citySpinner = view.findViewById(R.id.city_spinner); timeTextView = view.findViewById(R.id.time_text_view); ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.city_array, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); citySpinner.setAdapter(adapter); citySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String city = parent.getItemAtPosition(position).toString(); TimeZone timeZone = TimeZone.getTimeZone(getTimeZoneId(city)); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.setTimeZone(timeZone); String time = sdf.format(new Date()); timeTextView.setText(time); } @Override public void onNothingSelected(AdapterView<?> parent) {} }); return view; } private String getTimeZoneId(String city) { switch (city) { case "北京": return "Asia/Shanghai"; case "伦敦": return "Europe/London"; case "纽约": return "America/New_York"; default: return ""; } } } ``` 秒表选项卡代码示例: ``` public class StopwatchFragment extends Fragment { private Chronometer chronometer; private Button startButton, pauseButton, resetButton; public StopwatchFragment() {} @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_stopwatch, container, false); chronometer = view.findViewById(R.id.chronometer); startButton = view.findViewById(R.id.start_button); pauseButton = view.findViewById(R.id.pause_button); resetButton = view.findViewById(R.id.reset_button); startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chronometer.setBase(SystemClock.elapsedRealtime()); chronometer.start(); } }); pauseButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chronometer.stop(); } }); resetButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { chronometer.setBase(SystemClock.elapsedRealtime()); } }); return view; } } ``` 3. 编写广播接收器 我们需要编写一个广播接收器来接收系统发送的闹钟广播。在接收到广播后,我们可以弹出一个对话框或者播放一个铃声来提醒用户。 ``` public class AlarmReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "闹钟响了", Toast.LENGTH_SHORT).show(); } } ``` 4. 编写SQLite数据库代码 我们需要使用SQLite数据库来存储用户设置的闹钟信息。我们可以在创建闹钟时将信息存储到数据库中,在程序启动时读取数据库中的信息并设置闹钟。 ``` public class AlarmDbHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "alarm.db"; private static final int DATABASE_VERSION = 1; public AlarmDbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE alarms (" + "_id INTEGER PRIMARY KEY," + "hour INTEGER," + "minute INTEGER," + "enabled INTEGER" + ")"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS alarms"); onCreate(db); } public Cursor getAlarms() { SQLiteDatabase db = getReadableDatabase(); return db.query("alarms", null, null, null, null, null, null); } public long addAlarm(int hour, int minute, boolean enabled) { SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); values.put("hour", hour); values.put("minute", minute); values.put("enabled", enabled ? 1 : 0); return db.insert("alarms", null, values); } public void deleteAlarm(long id) { SQLiteDatabase db = getWritableDatabase(); db.delete("alarms", "_id=?", new String[] { String.valueOf(id) }); } } ``` 5. 总结 通过使用广播接收器和SQLite数据库技术,我们可以实现一个功能完善的倒计时APP。在实现过程中,我们需要注意以下几点: - 在接收系统广播时,需要在AndroidManifest.xml文件中注册相应的广播接收器。 - 在使用SQLite数据库时,需要注意线程安全问题,避免在UI线程中进行数据库操作。 - 在使用闹钟功能时,需要获取系统AlarmManager服务,生成一个PendingIntent对象,并使用AlarmManager.set()方法设置闹钟。 希望这份代码对您有所帮助!
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值