Compare commits

...
13 Commits
Author SHA1 Message Date
kfj001 b30427d862 Merge pull request 'Fat square interesting buttons' (#3) from fat_square_interesting_buttons into main
Reviewed-on: http://192.168.1.74:30008/kfj001/bong_hit_timer_android/pulls/3
2026-05-26 13:24:59 -07:00
kfj001 eaaeb7fa35 fixes buttons on countdown screen 2026-05-26 13:24:08 -07:00
kfj001 6ba2f2cfdf fixes beeping to 3.2.1 cycle 2026-05-26 12:31:28 -07:00
kfj001andClaude Opus 4.7 51c7fa1464 Theme timer ring colors green instead of hardcoded purple
CountdownCanvasView ring progress and track now use themed color
resources (md_color_ring_progress/md_color_ring_track) instead of
hardcoded Material3 purple, so they stay green in both light and dark mode.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:52:50 -07:00
kfj001andClaude Opus 4.7 df9d92f116 Fix chip selection color green with correct color selector approach
- Replace broken chipBackground theme style with a color state-list
  selector (res/color/chip_duration_bg.xml) using chipBackgroundColor
  attribute directly on each Chip
- Green (#81C784) when checked, light gray (#E8E8E8) when unchecked
- Add minWidth="56dp" to give chips proper width

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:40:32 -07:00
kfj001 5b517f39d6 Merge branch 'worktree-soft-floating-stroustrup' into fat_square_interesting_buttons 2026-05-26 11:24:10 -07:00
kfj001andClaude Opus 4.7 b20208fb40 Make chip selection background green to match app theme
Add custom chip_duration_bg selector drawable (green when checked,
light gray when unchecked) and wire it through a ChipDuration chipStyle
in the theme. This overrides Material3's default purple checked state.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:24:10 -07:00
kfj001 9b733f2102 Merge branch 'worktree-soft-floating-stroustrup' into fat_square_interesting_buttons 2026-05-26 11:12:58 -07:00
kfj001andClaude Opus 4.7 0738fc466e Make chip selection color green to match app theme
Add colorPrimaryContainer and set it to the green shade used throughout the app.
This fixes the purplish checked state on Material3 suggestion chips.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:12:58 -07:00
kfj001 7491083e6a Merge branch 'worktree-soft-floating-stroustrup' into fat_square_interesting_buttons 2026-05-26 11:04:36 -07:00
kfj001andClaude Opus 4.7 13786f6c8e Make dropdown arrow white for better visibility on green button
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 11:04:35 -07:00
kfj001andClaude Opus 4.7 92952a2cf2 Convert timeout selector button from oval to rectangular pill shape
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-26 08:50:44 -07:00
kfj001 6de400753c Rounded and larger button treatment 2026-05-26 03:39:25 -07:00
30 changed files with 412 additions and 57 deletions
@@ -24,12 +24,12 @@ class CountdownCanvasView @JvmOverloads constructor(
isFakeBoldText = false
}
private val ringPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.parseColor("#6750A4")
color = ContextCompat.getColor(context, R.color.md_color_ring_progress)
style = Paint.Style.STROKE
strokeWidth = 16f
}
private val ringBgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
color = Color.parseColor("#D0BCFF")
color = ContextCompat.getColor(context, R.color.md_color_ring_track)
style = Paint.Style.STROKE
strokeWidth = 16f
}
@@ -18,8 +18,8 @@ class CountdownDialog(
private val prefs: SharedPreferences
) : Dialog(context) {
private lateinit var cvCountdown: CountdownCanvasView
private lateinit var btnStop: Button
private lateinit var btnRestart: Button
private lateinit var btnStop: View
private lateinit var btnRestart: View
private lateinit var btnDismiss: Button
private var timer: CountDownTimer? = null
private var toneGenerator: ToneGenerator? = null
@@ -61,14 +61,10 @@ class CountdownDialog(
val progress = millisUntilFinished.toFloat() / durationMillis
cvCountdown.setProgress(progress)
if (millisUntilFinished >= durationMillis) {
cvCountdown.setText(context.getString(R.string.countdown_text))
} else {
val secondsLeft = (millisUntilFinished / 1000).toInt() + 1
cvCountdown.setText(secondsLeft.toString())
}
val secondsLeft = (millisUntilFinished / 1000).toInt() + 1
cvCountdown.setText(secondsLeft.toString())
if (millisUntilFinished <= 3000 && millisUntilFinished > 1000) {
if (secondsLeft >= 1 && secondsLeft <= 3) {
playTone(ToneGenerator.TONE_PROP_BEEP)
if (prefs.getBoolean("vibration", true)) {
vibrator?.vibrate(50)
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="#81C784" />
<item android:color="#E8E8E8" />
</selector>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="40dp" />
<gradient
android:angle="270"
android:startColor="#81C784"
android:endColor="#4CAF50"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#A5D6A7" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="40dp" />
<gradient
android:angle="270"
android:startColor="#C8E6C9"
android:endColor="#A5D6A7"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#E8F5E9" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="40dp" />
<gradient
android:angle="270"
android:startColor="#66BB6A"
android:endColor="#388E3C"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#81C784" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_duration_disabled" android:state_enabled="false" />
<item android:drawable="@drawable/btn_duration_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/btn_duration_pressed" android:state_activated="true" />
<item android:drawable="@drawable/btn_duration_default" />
</selector>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#42A5F5"
android:endColor="#1565C0"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#90CAF9" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#90CAF9"
android:endColor="#64B5F6"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#BBDEFB" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#1E88E5"
android:endColor="#0D47A1"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#42A5F5" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_restart_disabled" android:state_enabled="false" />
<item android:drawable="@drawable/btn_restart_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/btn_restart_pressed" android:state_activated="true" />
<item android:drawable="@drawable/btn_restart_default" />
</selector>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#4CAF50"
android:endColor="#2E7D32"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#66BB6A" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#A5D6A7"
android:endColor="#81C784"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#C8E6C9" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#388E3C"
android:endColor="#1B5E20"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#4CAF50" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_start_disabled" android:state_enabled="false" />
<item android:drawable="@drawable/btn_start_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/btn_start_pressed" android:state_activated="true" />
<item android:drawable="@drawable/btn_start_default" />
</selector>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#EF5350"
android:endColor="#C62828"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#EF9A9A" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#EF9A9A"
android:endColor="#E57373"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#FFCDD2" />
</shape>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:width="120dp" android:height="120dp" />
<gradient
android:angle="270"
android:startColor="#E53935"
android:endColor="#B71C1C"
android:type="linear" />
<stroke
android:width="3dp"
android:color="#EF5350" />
</shape>
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/btn_stop_disabled" android:state_enabled="false" />
<item android:drawable="@drawable/btn_stop_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/btn_stop_pressed" android:state_activated="true" />
<item android:drawable="@drawable/btn_stop_default" />
</selector>
@@ -4,6 +4,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#6750A4"
android:fillColor="#FFFFFF"
android:pathData="M7.41,8.59L12,13.17l4.59,-4.58L18,10l-6,6 -6,-6z"/>
</vector>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4L17.65,6.35z"
android:strokeWidth="0" />
</vector>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFF"
android:pathData="M6,6h12v12H6z"
android:strokeWidth="0" />
</vector>
+30 -11
View File
@@ -110,15 +110,22 @@
</LinearLayout>
</LinearLayout>
<com.google.android.material.button.MaterialButton
<Button
android:id="@+id/btnDurationLabel"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="180dp"
android:layout_height="80dp"
android:layout_marginTop="32dp"
android:background="@drawable/btn_duration_selector"
android:text="@string/start_timer"
android:drawableEnd="@drawable/ic_keyboard_arrow_down"
app:cornerRadius="20dp" />
android:drawablePadding="8dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:textColor="#FFFFFF"
android:textSize="18sp"
android:textStyle="bold"
android:gravity="center"
android:includeFontPadding="false" />
<HorizontalScrollView
android:id="@+id/hsvDurationOptions"
@@ -139,6 +146,8 @@
style="@style/Widget.Material3.Chip.Suggestion.Elevated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="56dp"
app:chipBackgroundColor="@color/chip_duration_bg"
android:text="5s" />
<com.google.android.material.chip.Chip
@@ -146,7 +155,9 @@
style="@style/Widget.Material3.Chip.Suggestion.Elevated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="56dp"
android:checked="true"
app:chipBackgroundColor="@color/chip_duration_bg"
android:text="10s" />
<com.google.android.material.chip.Chip
@@ -154,6 +165,8 @@
style="@style/Widget.Material3.Chip.Suggestion.Elevated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="56dp"
app:chipBackgroundColor="@color/chip_duration_bg"
android:text="15s" />
<com.google.android.material.chip.Chip
@@ -161,19 +174,25 @@
style="@style/Widget.Material3.Chip.Suggestion.Elevated"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="56dp"
app:chipBackgroundColor="@color/chip_duration_bg"
android:text="30s" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
<com.google.android.material.button.MaterialButton
<Button
android:id="@+id/btnStart"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="16dp"
android:background="@drawable/btn_start_selector"
android:drawableTop="@drawable/ic_play_arrow"
android:gravity="center"
android:padding="16dp"
android:text="@string/start_timer"
app:cornerRadius="20dp"
app:icon="@drawable/ic_play_arrow" />
android:textColor="#FFFFFF"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
+66 -34
View File
@@ -5,47 +5,79 @@
android:layout_height="match_parent"
android:background="#80000000">
<com.example.countdowntimer.CountdownCanvasView
android:id="@+id/cvCountdown"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/buttonRow"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/buttonRow"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="48dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<FrameLayout
android:id="@+id/btnStop"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginEnd="16dp"
android:background="@drawable/btn_stop_selector"
android:clickable="true"
android:focusable="true">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:contentDescription="@string/stop_timer"
android:src="@drawable/ic_stop_square" />
</FrameLayout>
<FrameLayout
android:id="@+id/btnRestart"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:background="@drawable/btn_restart_selector"
android:clickable="true"
android:focusable="true">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:contentDescription="@string/restart_timer"
android:src="@drawable/ic_refresh_square" />
</FrameLayout>
</LinearLayout>
<Button
android:id="@+id/btnDismiss"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/btn_duration_selector"
android:gravity="center"
android:padding="16dp"
android:text="Dismiss"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.example.countdowntimer.CountdownCanvasView
android:id="@+id/cvCountdown"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/btnStop"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_margin="16dp" />
<Button
android:id="@+id/btnStop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Stop"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/btnRestart"
app:layout_constraintHorizontal_chainStyle="spread" />
<Button
android:id="@+id/btnRestart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Restart"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/btnStop"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
+2
View File
@@ -2,4 +2,6 @@
<resources>
<color name="color_gradient_start">#1B3A1B</color>
<color name="color_gradient_end">#0D1F0D</color>
<color name="md_color_ring_progress">#A5D6A7</color>
<color name="md_color_ring_track">#2E7D32</color>
</resources>
+1
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="md_theme_dark_primary">#A5D6A7</color>
<color name="md_theme_dark_primaryContainer">#2E7D32</color>
<color name="md_theme_dark_secondary">#869F7C</color>
<style name="Theme.CountdownTimer" parent="Theme.Material3.DayNight.NoActionBar">
+2
View File
@@ -3,4 +3,6 @@
<color name="color_gradient_start">#E8F5E9</color>
<color name="color_gradient_end">#C8E6C9</color>
<color name="color_icon_tint">#2E7D32</color>
<color name="md_color_ring_progress">#2E7D32</color>
<color name="md_color_ring_track">#81C784</color>
</resources>
+2
View File
@@ -11,4 +11,6 @@
<string name="settings">Settings</string>
<string name="vibration">Vibration</string>
<string name="sounds">Sounds</string>
<string name="stop_timer">Stop Timer</string>
<string name="restart_timer">Restart Timer</string>
</resources>
+2
View File
@@ -1,12 +1,14 @@
<resources>
<style name="Theme.CountdownTimer" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">@color/md_theme_light_primary</item>
<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
<item name="colorSecondary">@color/md_theme_light_secondary</item>
<item name="android:statusBarColor">@color/color_gradient_start</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<color name="md_theme_light_primary">#2E7D32</color>
<color name="md_theme_light_primaryContainer">#81C784</color>
<color name="md_theme_light_secondary">#4C6842</color>
<color name="md_theme_light_surface">#F1F8E9</color>
</resources>
+88
View File
@@ -0,0 +1,88 @@
# Goal: Redesign all buttons into bold, square, visually striking interactive elements
## Objective
Replace every basic/rectangular button in the app with larger, square-aspect-ratio buttons that have eye-catching visual design. The goal is to transform the UI from a generic Material 3 look into a distinctive, personality-rich interface that matches the playful "BONG HIT TIMER" brand.
## Current State
The app uses 4 visible buttons across 2 screens:
**MainActivity (home screen):**
- `btnDurationLabel` — outlined button showing selected duration (e.g. "10s") with a dropdown arrow. Uses `Widget.Material3.Button.OutlinedButton` with 20dp corners.
- `btnStart` — filled button labeled "Start Timer" with a play icon. Uses `Widget.Material3.Button` with 20dp corners.
**CountdownDialog (timer screen):**
- `btnStop` — plain Android `Button` labeled "Stop" (default styling, small)
- `btnRestart` — plain Android `Button` labeled "Restart" (default styling, small)
- `btnDismiss` — plain Android `Button` labeled "Dismiss" (currently gone, shows after timer completes)
## Design Requirements
### 1. Square Aspect Ratio
- Change all buttons from `wrap_content` rectangles to a fixed square size (e.g., `120dp` x `120dp` or `100dp` x `100dp`)
- Use `app:layout_constraintDimensionRatio="1:1"` where dynamic sizing is needed
- Buttons should feel substantial and tappable, not compact
### 2. Visual Interest — Each button should have its own personality
Create custom drawable backgrounds for each button type. Design ideas (pick the best approach):
- **Circular/spherical buttons** — Buttons that look like physical 3D balls or pucks. Use gradient fills with highlights/shadows to create a convex "pressable" look.
- **Neon/glow effect** — Since the app is a bong hit timer, a subtle neon glow that pulses or intensifies during countdown would be thematically appropriate.
- **Retro/gaming arcade style** — Bold colors, thick borders, pressed/active states that simulate physical button depression.
- **Gradient + icon centering** — For the timer screen, center the stop/restart icons prominently in the square buttons with bold gradient backgrounds.
### 3. Interactive States
Every button must have rich feedback:
- **Pressed/active state** — noticeable visual change (shrink, darker shade, or inner glow)
- **Default state** — visually engaging with gradients, shadows, or subtle animations
- **Disabled state** — reduced opacity but still recognizable
### 4. Icon Integration
Square buttons are perfect for icon-first design:
- **Stop button** — large centered pause/stop icon
- **Restart button** — large centered refresh/replay icon
- **Start button** — center the play icon, consider removing the text label since the icon is universal
- **Duration label** — consider a pill-shaped or circular chip that pulses when tapped
### 5. Color Palette
Stay within the existing green theme (`#2E7D32` primary, `#4C6842` secondary, `#E8F5E9`/`#C8E6C9` gradient) but push it further:
- Use the primary green for the start/positive actions
- A red/coral accent for stop
- A neutral or blue for restart/duration selection
- Consider gradient transitions within each button (e.g., green to darker green top-to-bottom for a 3D effect)
### 6. Shadow & Elevation
- Add drop shadows to all buttons for depth (use `app:strokeWidth="0dp"` and custom `rippleColor` for Material buttons)
- Create a `btn_square_default.xml` and `btn_square_pressed.xml` in `res/drawable/` for each button type
- The pressed state should visually simulate "pressing in" (reduced shadow, lighter/darker fill)
## Technical Implementation
### New drawable files to create (in `res/drawable/`):
- `btn_start_square.xml` — gradient + shadow drawable for start button
- `btn_start_square_pressed.xml` — pressed state variant
- `btn_stop_square.xml` — gradient + shadow drawable for stop button
- `btn_stop_square_pressed.xml` — pressed state variant
- `btn_restart_square.xml` — gradient + shadow drawable for restart button
- `btn_restart_square_pressed.xml` — pressed state variant
- `btn_duration_chip.xml` — drawable for duration selector
### Layout changes needed:
- `activity_main.xml`:
- `btnDurationLabel`: change to square dimensions, wrap text/icon in center, apply new drawable
- `btnStart`: change to square, center play icon, apply new drawable
- `dialog_countdown.xml`:
- `btnStop`: change from `Button` to `com.google.android.material.button.MaterialButton`, set square dimensions, apply drawable
- `btnRestart`: same treatment
- `btnDismiss`: same treatment, keep as gone by default
- Adjust the ConstraintLayout chain to accommodate square buttons (may need a horizontal chain with proper spacing)
### Code changes needed:
- `CountdownDialog.kt`: Set button backgrounds programmatically if needed, ensure clickable/pressable states work
- No changes to button click logic — only visual overhaul
## Constraints
- Use only Material 3 components already in the dependency (`com.google.android.material:material:1.11.0`)
- Traditional XML layouts — no Compose
- Minimum SDK 24 — no API 30+ features
- Keep the app's existing green aesthetic but make it bolder
- Maintain accessibility (minimum 48dp touch target, sufficient contrast)