A precise Android stopwatch with start, pause, reset, lap-time recording, and rotation safety.
Build an Android stopwatch that can start, pause, resume, and reset, and that can record lap times showing both the split (since the previous lap) and the running total. The timer must continue correctly even if the device is rotated.
| Tool / Library | Purpose |
|---|---|
| Android Studio | IDE |
| Java | Application logic |
| XML | UI layouts |
| AndroidX RecyclerView | Lap times list |
Handler + Runnable |
Periodic UI tick (~31 ms) |
| Material Components 1.12.0 | MaterialButton, MaterialCardView, MaterialToolbar |
| AGP 8.5.0 / Gradle 8.7 / JDK 17 | Build toolchain |
| Min SDK 24 • Target SDK 34 | API compatibility |
- Project setup — Empty Activity (Java), Material 3 DayNight theme.
- UI layout — large monospace timer display in a Material card, a 3-button row (Start / Hold / Resume, Lap, Reset), a "Lap times" header, and a
RecyclerViewfor laps with an empty-state text. - Time-keeping model — two long fields:
elapsedBeforeStart— accumulated milliseconds before the current run segmentstartedAt—System.currentTimeMillis()when the current segment started- Current elapsed =
running ? elapsedBeforeStart + (now - startedAt) : elapsedBeforeStart
- Tick loop — a
Handlerre-posts aRunnableevery 31 ms (centisecond resolution) that re-formatstvTimewhile running. - Primary button states — the same button cycles: Start → Hold → Resume, label switching based on current state. Lap is enabled only while running. Reset is enabled while running or after stopping.
- Lap recording — each Lap tap inserts the current elapsed time at the top of an
ArrayList<Long>; theRecyclerViewshows newest first with two columns per row: + split (this total − previous total) and total inHH:MM:SS.cs. - Rotation safety —
onSaveInstanceStatepersistselapsedBeforeStart,startedAt,runningflag, and the lap array as along[]. After rotation the activity rebuilds and resumes ticking from exactly the right moment. - Format helper —
format(long ms)returns a fixedHH:MM:SS.csstring usingString.format(Locale.US, …). - Cleanup —
onDestroyremoves the tick callback so no leaks occur.
A working stopwatch app featuring:
- Start / Hold (pause) / Resume / Reset controls
- Lap times recorded with both split and total
- HH:MM:SS.cs monospace display (centisecond precision)
- Rotation-safe via
onSaveInstanceState - Material 3 card UI + Day/Night auto theme
- Enabled/disabled button states matching the stopwatch state
java/com/intern/stopwatch/
└── MainActivity.java # tick handler + RecyclerView LapAdapter
res/layout/
├── activity_main.xml # timer card + 3-button row + RV
└── item_lap.xml # Lap n | +split | total
- Tap Start → timer runs.
- Tap Lap a few times → split & total appear in the list.
- Tap Hold → freezes at the current time; button becomes Resume.
- Tap Resume → continues exactly where it paused.
- Rotate the screen → still ticking from the right instant.
- Tap Reset → everything zeroed out.