Skip to content

Commit 870f5de

Browse files
authored
fix: add landscape layout for stopwatch (#217)
* fix: add landscape layout for stopwatch * docs: add comment about optimization * docs: changelog * fix: add some padding between lap items * fix: hide laps list when empty
1 parent ece3154 commit 870f5de

5 files changed

Lines changed: 159 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Changed
1111

1212
- Replaced lap text button with an icon button
13+
- Updated stopwatch layout animation
1314
- Updated translations
1415

1516
### Fixed
1617

1718
- Fixed inaccuracy in stopwatch over long durations ([#207])
1819
- Fixed text jitter in clock, stopwatch, and timer ([#11])
20+
- Fixed invisible stopwatch laps in landscape mode ([#107])
1921

2022
## [1.2.1] - 2025-05-08
2123

@@ -85,5 +87,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8587
[1.0.0]: https://github.com/FossifyOrg/Clock/releases/tag/1.0.0
8688

8789
[#11]: https://github.com/FossifyOrg/Clock/issues/11
90+
[#107]: https://github.com/FossifyOrg/Clock/issues/107
8891
[#158]: https://github.com/FossifyOrg/Clock/issues/158
8992
[#207]: https://github.com/FossifyOrg/Clock/issues/207

app/src/main/kotlin/org/fossify/clock/fragments/StopwatchFragment.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ import org.fossify.clock.models.Lap
2727
import org.fossify.commons.dialogs.PermissionRequiredDialog
2828
import org.fossify.commons.extensions.applyColorFilter
2929
import org.fossify.commons.extensions.beGone
30-
import org.fossify.commons.extensions.beInvisible
3130
import org.fossify.commons.extensions.beInvisibleIf
32-
import org.fossify.commons.extensions.beVisible
3331
import org.fossify.commons.extensions.beVisibleIf
3432
import org.fossify.commons.extensions.flipBit
3533
import org.fossify.commons.extensions.getColoredBitmap
@@ -82,7 +80,7 @@ class StopwatchFragment : Fragment() {
8280
}
8381

8482
stopwatchLap.setOnClickListener {
85-
stopwatchSortingIndicatorsHolder.beVisible()
83+
setShowLaps(true)
8684
Stopwatch.lap()
8785
updateLaps()
8886
scrollToTop()
@@ -108,9 +106,11 @@ class StopwatchFragment : Fragment() {
108106
setupViews()
109107
Stopwatch.addUpdateListener(updateListener)
110108
updateLaps()
111-
binding.stopwatchSortingIndicatorsHolder.beVisibleIf(Stopwatch.laps.isNotEmpty())
112109
if (Stopwatch.laps.isNotEmpty()) {
113110
updateSorting(Lap.sorting)
111+
setShowLaps(true)
112+
} else {
113+
setShowLaps(false)
114114
}
115115

116116
if (requireContext().config.toggleStopwatch) {
@@ -191,7 +191,7 @@ class StopwatchFragment : Fragment() {
191191
stopwatchReset.beGone()
192192
stopwatchLap.beGone()
193193
stopwatchTime.text = 0L.formatStopwatchTime(false)
194-
stopwatchSortingIndicatorsHolder.beInvisible()
194+
setShowLaps(false)
195195
}
196196
}
197197

@@ -244,7 +244,7 @@ class StopwatchFragment : Fragment() {
244244
}
245245
}
246246

247-
private fun updateLaps() = lifecycleScope.launch {
247+
private fun updateLaps() = viewLifecycleOwner.lifecycleScope.launch {
248248
stopwatchAdapter?.submitList(
249249
withContext(Dispatchers.Default) {
250250
val laps = ArrayList(Stopwatch.laps)
@@ -267,11 +267,18 @@ class StopwatchFragment : Fragment() {
267267
}
268268
}
269269

270+
private fun setShowLaps(showLaps: Boolean) {
271+
binding.stopwatchSortingIndicatorsHolder.beVisibleIf(showLaps)
272+
binding.stopwatchList.beVisibleIf(showLaps)
273+
}
274+
270275
private val updateListener = object : Stopwatch.UpdateListener {
271276
override fun onUpdate(totalTime: Long, lapTime: Long, useLongerMSFormat: Boolean) {
272277
binding.stopwatchTime.text = totalTime.formatStopwatchTime(useLongerMSFormat)
273278
latestLapTime = lapTime
274279
latestTotalTime = totalTime
280+
// We just update the list everytime for simplicity.
281+
// dafa9e0ad88fdf77c19b91caec0683a3a87b8f50 would be more efficient.
275282
updateLaps()
276283
}
277284

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:app="http://schemas.android.com/apk/res-auto"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:id="@+id/stopwatch_fragment"
6+
android:layout_width="match_parent"
7+
android:layout_height="match_parent"
8+
android:animateLayoutChanges="true">
9+
10+
<org.fossify.clock.views.AutoFitTextView
11+
android:id="@+id/stopwatch_time"
12+
android:layout_width="0dp"
13+
android:layout_height="wrap_content"
14+
android:autoSizeMaxTextSize="@dimen/stopwatch_text_size"
15+
android:autoSizeMinTextSize="@dimen/extra_big_text_size"
16+
android:autoSizeStepGranularity="2sp"
17+
android:autoSizeTextType="uniform"
18+
android:background="?attr/selectableItemBackground"
19+
android:fontFeatureSettings="tnum"
20+
android:gravity="center_horizontal"
21+
android:includeFontPadding="false"
22+
android:maxLines="1"
23+
android:padding="@dimen/small_margin"
24+
android:textSize="@dimen/stopwatch_text_size"
25+
app:layout_constraintBottom_toBottomOf="parent"
26+
app:layout_constraintEnd_toStartOf="@id/stopwatch_list"
27+
app:layout_constraintStart_toStartOf="parent"
28+
app:layout_constraintTop_toTopOf="parent"
29+
tools:text="01:30:00" />
30+
31+
<androidx.constraintlayout.widget.ConstraintLayout
32+
android:id="@+id/stopwatch_sorting_indicators_holder"
33+
android:layout_width="wrap_content"
34+
android:layout_height="wrap_content"
35+
android:layout_marginTop="@dimen/small_margin"
36+
android:visibility="invisible"
37+
app:layout_constraintBottom_toTopOf="@id/stopwatch_list"
38+
app:layout_constraintEnd_toEndOf="@id/stopwatch_list"
39+
app:layout_constraintStart_toStartOf="@id/stopwatch_list"
40+
app:layout_constraintTop_toTopOf="parent"
41+
tools:visibility="visible">
42+
43+
<ImageView
44+
android:id="@+id/stopwatch_sorting_indicator_1"
45+
android:layout_width="@dimen/lap_time_size"
46+
android:layout_height="wrap_content"
47+
android:visibility="invisible"
48+
app:layout_constraintEnd_toStartOf="@+id/stopwatch_sorting_indicator_2"
49+
app:layout_constraintHorizontal_chainStyle="packed"
50+
app:layout_constraintStart_toStartOf="parent" />
51+
52+
<ImageView
53+
android:id="@+id/stopwatch_sorting_indicator_2"
54+
android:layout_width="@dimen/lap_time_size"
55+
android:layout_height="wrap_content"
56+
android:visibility="invisible"
57+
app:layout_constraintEnd_toStartOf="@+id/stopwatch_sorting_indicator_3"
58+
app:layout_constraintStart_toEndOf="@+id/stopwatch_sorting_indicator_1"
59+
app:layout_constraintTop_toTopOf="parent" />
60+
61+
<ImageView
62+
android:id="@+id/stopwatch_sorting_indicator_3"
63+
android:layout_width="@dimen/lap_time_size"
64+
android:layout_height="wrap_content"
65+
android:visibility="invisible"
66+
app:layout_constraintEnd_toEndOf="parent"
67+
app:layout_constraintStart_toEndOf="@+id/stopwatch_sorting_indicator_2"
68+
app:layout_constraintTop_toTopOf="parent" />
69+
70+
</androidx.constraintlayout.widget.ConstraintLayout>
71+
72+
<org.fossify.commons.views.MyRecyclerView
73+
android:id="@+id/stopwatch_list"
74+
android:layout_width="0dp"
75+
android:layout_height="0dp"
76+
android:layout_marginEnd="@dimen/section_margin"
77+
android:layout_marginBottom="@dimen/medium_margin"
78+
android:clipToPadding="false"
79+
android:overScrollMode="ifContentScrolls"
80+
android:scrollbars="vertical"
81+
android:visibility="gone"
82+
app:layoutManager="org.fossify.commons.views.MyLinearLayoutManager"
83+
app:layout_constraintBottom_toBottomOf="parent"
84+
app:layout_constraintEnd_toStartOf="@id/stopwatch_play_pause"
85+
app:layout_constraintStart_toEndOf="@id/stopwatch_time"
86+
app:layout_constraintTop_toBottomOf="@+id/stopwatch_sorting_indicators_holder"
87+
tools:itemCount="18"
88+
tools:listitem="@layout/item_lap"
89+
tools:visibility="visible" />
90+
91+
<ImageView
92+
android:id="@+id/stopwatch_play_pause"
93+
android:layout_width="@dimen/stopwatch_button_size"
94+
android:layout_height="@dimen/stopwatch_button_size"
95+
android:layout_marginEnd="@dimen/section_margin"
96+
android:padding="@dimen/activity_margin"
97+
android:src="@drawable/ic_play_vector"
98+
app:layout_constraintBottom_toBottomOf="parent"
99+
app:layout_constraintEnd_toEndOf="parent"
100+
app:layout_constraintStart_toEndOf="@id/stopwatch_list"
101+
app:layout_constraintTop_toTopOf="parent" />
102+
103+
<ImageView
104+
android:id="@+id/stopwatch_reset"
105+
android:layout_width="@dimen/stopwatch_button_small_size"
106+
android:layout_height="@dimen/stopwatch_button_small_size"
107+
android:background="?attr/selectableItemBackgroundBorderless"
108+
android:padding="@dimen/normal_margin"
109+
android:src="@drawable/ic_reset_vector"
110+
android:visibility="gone"
111+
app:layout_constraintBottom_toBottomOf="parent"
112+
app:layout_constraintEnd_toEndOf="@id/stopwatch_play_pause"
113+
app:layout_constraintStart_toStartOf="@id/stopwatch_play_pause"
114+
app:layout_constraintTop_toBottomOf="@id/stopwatch_play_pause"
115+
tools:visibility="visible" />
116+
117+
<ImageView
118+
android:id="@+id/stopwatch_lap"
119+
android:layout_width="@dimen/stopwatch_button_small_size"
120+
android:layout_height="@dimen/stopwatch_button_small_size"
121+
android:background="?attr/selectableItemBackgroundBorderless"
122+
android:contentDescription="@string/lap"
123+
android:padding="@dimen/normal_margin"
124+
android:src="@drawable/ic_stopwatch_vector"
125+
android:visibility="gone"
126+
app:layout_constraintBottom_toTopOf="@id/stopwatch_play_pause"
127+
app:layout_constraintEnd_toEndOf="@id/stopwatch_play_pause"
128+
app:layout_constraintStart_toStartOf="@id/stopwatch_play_pause"
129+
app:layout_constraintTop_toTopOf="parent"
130+
tools:visibility="visible" />
131+
132+
</androidx.constraintlayout.widget.ConstraintLayout>
133+

app/src/main/res/layout/fragment_stopwatch.xml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44
xmlns:tools="http://schemas.android.com/tools"
55
android:id="@+id/stopwatch_fragment"
66
android:layout_width="match_parent"
7-
android:layout_height="match_parent">
7+
android:layout_height="match_parent"
8+
android:animateLayoutChanges="true">
89

910
<org.fossify.clock.views.AutoFitTextView
1011
android:id="@+id/stopwatch_time"
1112
android:layout_width="match_parent"
1213
android:layout_height="wrap_content"
1314
android:layout_marginTop="@dimen/normal_margin"
15+
android:layout_marginBottom="@dimen/small_margin"
1416
android:autoSizeMaxTextSize="@dimen/stopwatch_text_size"
1517
android:autoSizeMinTextSize="@dimen/extra_big_text_size"
1618
android:autoSizeStepGranularity="2sp"
@@ -22,17 +24,19 @@
2224
android:maxLines="1"
2325
android:padding="@dimen/small_margin"
2426
android:textSize="@dimen/stopwatch_text_size"
27+
app:layout_constraintBottom_toTopOf="@id/stopwatch_sorting_indicators_holder"
2528
app:layout_constraintEnd_toEndOf="parent"
2629
app:layout_constraintStart_toStartOf="parent"
2730
app:layout_constraintTop_toTopOf="parent"
31+
app:layout_goneMarginBottom="@dimen/stopwatch_button_size"
2832
tools:text="01:30:00" />
2933

3034
<androidx.constraintlayout.widget.ConstraintLayout
3135
android:id="@+id/stopwatch_sorting_indicators_holder"
3236
android:layout_width="match_parent"
3337
android:layout_height="wrap_content"
34-
android:layout_marginTop="@dimen/small_margin"
3538
android:visibility="invisible"
39+
app:layout_constraintBottom_toTopOf="@id/stopwatch_list"
3640
app:layout_constraintTop_toBottomOf="@+id/stopwatch_time"
3741
tools:visibility="visible">
3842

@@ -73,19 +77,19 @@
7377
android:clipToPadding="false"
7478
android:overScrollMode="ifContentScrolls"
7579
android:scrollbars="vertical"
80+
android:visibility="gone"
7681
app:layoutManager="org.fossify.commons.views.MyLinearLayoutManager"
7782
app:layout_constraintBottom_toTopOf="@+id/stopwatch_play_pause"
7883
app:layout_constraintEnd_toEndOf="parent"
7984
app:layout_constraintStart_toStartOf="parent"
8085
app:layout_constraintTop_toBottomOf="@+id/stopwatch_sorting_indicators_holder"
81-
tools:listitem="@layout/item_lap" />
86+
tools:listitem="@layout/item_lap"
87+
tools:visibility="visible" />
8288

8389
<ImageView
8490
android:id="@+id/stopwatch_play_pause"
8591
android:layout_width="@dimen/stopwatch_button_size"
8692
android:layout_height="@dimen/stopwatch_button_size"
87-
android:layout_alignParentBottom="true"
88-
android:layout_centerHorizontal="true"
8993
android:layout_marginBottom="@dimen/big_margin"
9094
android:padding="@dimen/activity_margin"
9195
android:src="@drawable/ic_play_vector"
@@ -98,7 +102,6 @@
98102
android:id="@+id/stopwatch_reset"
99103
android:layout_width="@dimen/stopwatch_button_small_size"
100104
android:layout_height="@dimen/stopwatch_button_small_size"
101-
android:layout_toStartOf="@+id/stopwatch_play_pause"
102105
android:background="?attr/selectableItemBackgroundBorderless"
103106
android:padding="@dimen/normal_margin"
104107
android:src="@drawable/ic_reset_vector"

app/src/main/res/layout/item_lap.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
android:layout_width="match_parent"
77
android:layout_height="wrap_content"
88
android:gravity="center_horizontal"
9+
android:paddingVertical="@dimen/small_margin"
910
android:paddingLeft="@dimen/activity_margin">
1011

1112
<org.fossify.commons.views.MyTextView

0 commit comments

Comments
 (0)