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); } }
关键逻辑说明
- 输入处理:用
StringBuilder记录用户输入的数字,限制最大长度为6(对应最大时间99h59m59s),避免无效输入。 - 时间转换:将输入的数字串视为总秒数,通过除法和取余拆分出时、分、秒,自动实现从右往左填充的效果(比如输入123=1*60+23 → 00h 01m 23s)。
- 样式处理:通过
RelativeSizeSpan缩小"h/m/s"的字号,保持单个TextView的布局简洁,避免多TextView的同步问题。 - 退格与00键:退格键删除最后一位,00键追加两个0(若剩余长度不足则补满),完全匹配Google Clock的交互逻辑。
内容的提问来源于stack exchange,提问作者codec123
相关产品推荐
相关产品推荐

