You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:带11键的计时器输入实现(求Java代码)

实现Google Clock风格的计时器输入UI

核心思路

用单个TextView统一显示时间格式,通过StringBuilder记录用户输入的数字串,将数字串转换为总秒数后拆分出时、分、秒,最后用SpannableString缩小"h/m/s"的字号,避免多TextView的逻辑混乱。


布局文件(activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <!-- 显示时间的TextView -->
    <TextView
        android:id="@+id/tv_time_display"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="00h 00m 00s"
        android:textSize="48sp"
        android:layout_marginBottom="32dp"/>

    <!-- 数字键盘 -->
    <GridLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="3"
        android:rowCount="4">

        <Button
            android:id="@+id/btn_1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="1"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="2"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="3"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="4"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_5"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="5"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_6"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="6"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_7"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="7"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_8"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="8"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_9"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="9"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_00"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="00"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_0"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="0"
            android:textSize="24sp"/>

        <Button
            android:id="@+id/btn_backspace"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_columnWeight="1"
            android:text="←"
            android:textSize="24sp"/>
    </GridLayout>
</LinearLayout>

Java代码(MainActivity.java)

import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.RelativeSizeSpan;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tvTimeDisplay;
    private StringBuilder inputDigits = new StringBuilder();
    // 最多支持6位数字(对应99h59m59s)
    private static final int MAX_INPUT_LENGTH = 6;

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

        tvTimeDisplay = findViewById(R.id.tv_time_display);

        // 绑定所有按钮点击事件
        findViewById(R.id.btn_1).setOnClickListener(this);
        findViewById(R.id.btn_2).setOnClickListener(this);
        findViewById(R.id.btn_3).setOnClickListener(this);
        findViewById(R.id.btn_4).setOnClickListener(this);
        findViewById(R.id.btn_5).setOnClickListener(this);
        findViewById(R.id.btn_6).setOnClickListener(this);
        findViewById(R.id.btn_7).setOnClickListener(this);
        findViewById(R.id.btn_8).setOnClickListener(this);
        findViewById(R.id.btn_9).setOnClickListener(this);
        findViewById(R.id.btn_0).setOnClickListener(this);
        findViewById(R.id.btn_00).setOnClickListener(this);
        findViewById(R.id.btn_backspace).setOnClickListener(this);

        // 初始化显示
        updateTimeDisplay();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_backspace) {
            // 退格:删除最后一位数字
            if (inputDigits.length() > 0) {
                inputDigits.deleteCharAt(inputDigits.length() - 1);
            }
        } else if (id == R.id.btn_00) {
            // 输入00:追加两个0,不超过最大长度
            if (inputDigits.length() + 2 <= MAX_INPUT_LENGTH) {
                inputDigits.append("00");
            } else {
                // 剩余位置不足时,只补到最大长度
                int remaining = MAX_INPUT_LENGTH - inputDigits.length();
                for (int i = 0; i < remaining; i++) {
                    inputDigits.append("0");
                }
            }
        } else {
            // 输入单个数字:追加数字,不超过最大长度
            Button btn = (Button) v;
            String digit = btn.getText().toString();
            if (inputDigits.length() < MAX_INPUT_LENGTH) {
                inputDigits.append(digit);
            }
        }
        // 更新显示
        updateTimeDisplay();
    }

    private void updateTimeDisplay() {
        // 计算总秒数:空输入时为0
        long totalSeconds = inputDigits.length() == 0 ? 0 : Long.parseLong(inputDigits.toString());

        // 拆分时、分、秒
        int hours = (int) (totalSeconds / 3600) % 100;
        int minutes = (int) (totalSeconds / 60) % 60;
        int seconds = (int) totalSeconds % 60;

        // 格式化基础文本
        String timeText = String.format("%02dh %02dm %02ds", hours, minutes, seconds);

        // 用SpannableString缩小"h/m/s"的字号(设为原字号的60%)
        SpannableString spannable = new SpannableString(timeText);
        // 标记h的位置:第2位(0索引)
        spannable.setSpan(new RelativeSizeSpan(0.6f), 2, 3, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 标记m的位置:第6位
        spannable.setSpan(new RelativeSizeSpan(0.6f), 6, 7, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 标记s的位置:第10位
        spannable.setSpan(new RelativeSizeSpan(0.6f), 10, 11, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);

        // 更新TextView
        tvTimeDisplay.setText(spannable);
    }
}

关键逻辑说明

  1. 输入处理:用StringBuilder记录用户输入的数字,限制最大长度为6(对应最大时间99h59m59s),避免无效输入。
  2. 时间转换:将输入的数字串视为总秒数,通过除法和取余拆分出时、分、秒,自动实现从右往左填充的效果(比如输入123=1*60+23 → 00h 01m 23s)。
  3. 样式处理:通过RelativeSizeSpan缩小"h/m/s"的字号,保持单个TextView的布局简洁,避免多TextView的同步问题。
  4. 退格与00键:退格键删除最后一位,00键追加两个0(若剩余长度不足则补满),完全匹配Google Clock的交互逻辑。

内容的提问来源于stack exchange,提问作者codec123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 18:46:17