Final
This commit is contained in:
parent
8450a791d5
commit
d9093ba007
@ -11,6 +11,7 @@ import com.example.workouttimer.ui.screens.RunningWorkoutScreen
|
||||
import com.example.workouttimer.ui.screens.SavedWorkoutsScreen
|
||||
import com.example.workouttimer.viewmodel.WorkoutViewModel
|
||||
import com.example.workouttimer.ui.screens.WorkoutEditorScreen
|
||||
import com.example.workouttimer.ui.screens.PreparationCountdownScreen
|
||||
|
||||
class AppNavigation(private val context: Context) {
|
||||
|
||||
@ -31,7 +32,12 @@ class AppNavigation(private val context: Context) {
|
||||
setScreen(
|
||||
HomeScreen(
|
||||
context = context,
|
||||
onShowWorkouts = { showSavedWorkouts() }
|
||||
onShowWorkouts = {
|
||||
showSavedWorkouts()
|
||||
},
|
||||
onCreateWorkout = {
|
||||
showCreateWorkout()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -101,20 +107,32 @@ class AppNavigation(private val context: Context) {
|
||||
context = context,
|
||||
workout = viewModel.currentWorkout,
|
||||
onStart = {
|
||||
viewModel.startWorkout()
|
||||
showRunningWorkout()
|
||||
showPreparationCountdown()
|
||||
},
|
||||
onBack = { showSavedWorkouts() }
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun showPreparationCountdown() {
|
||||
setScreen(
|
||||
PreparationCountdownScreen(
|
||||
context = context,
|
||||
onSkip = {
|
||||
viewModel.startWorkout()
|
||||
showRunningWorkout()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun showRunningWorkout() {
|
||||
setScreen(
|
||||
RunningWorkoutScreen(
|
||||
context = context,
|
||||
workout = viewModel.currentWorkout,
|
||||
exercise = viewModel.getCurrentExercise(),
|
||||
nextExercise = viewModel.getNextExercise(),
|
||||
exerciseNumber = viewModel.currentExerciseIndex + 1,
|
||||
onNextExercise = {
|
||||
viewModel.nextExercise()
|
||||
|
||||
@ -6,6 +6,7 @@ import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.domain.Workout
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class FinishedScreen(
|
||||
context: Context,
|
||||
@ -14,34 +15,33 @@ class FinishedScreen(
|
||||
) : LinearLayout(context) {
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setPadding(48, 48, 48, 48)
|
||||
AppStyle.applyGradientBackground(this)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = "Workout beendet!"
|
||||
title.textSize = 32f
|
||||
title.gravity = Gravity.CENTER
|
||||
title.text = "Workout\nDone"
|
||||
AppStyle.headline(title)
|
||||
addView(title)
|
||||
|
||||
val workoutText = TextView(context)
|
||||
workoutText.text = workout?.name ?: ""
|
||||
workoutText.textSize = 22f
|
||||
workoutText.gravity = Gravity.CENTER
|
||||
workoutText.text = workout?.name ?: "Training abgeschlossen"
|
||||
AppStyle.title(workoutText)
|
||||
AppStyle.setTextMargin(workoutText)
|
||||
addView(workoutText)
|
||||
|
||||
val summary = TextView(context)
|
||||
summary.text = "Gute Arbeit. Dein Workout wurde erfolgreich abgeschlossen."
|
||||
summary.textSize = 18f
|
||||
summary.gravity = Gravity.CENTER
|
||||
AppStyle.muted(summary)
|
||||
AppStyle.setTextMargin(summary)
|
||||
addView(summary)
|
||||
|
||||
val homeButton = Button(context)
|
||||
homeButton.text = "Zur Startseite"
|
||||
homeButton.text = "Zur Startseite -->"
|
||||
AppStyle.primaryButton(homeButton)
|
||||
homeButton.setOnClickListener {
|
||||
onBackHome()
|
||||
}
|
||||
|
||||
addView(title)
|
||||
addView(workoutText)
|
||||
addView(summary)
|
||||
addView(homeButton)
|
||||
}
|
||||
}
|
||||
@ -2,38 +2,70 @@ package com.example.workouttimer.ui.screens
|
||||
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Space
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class HomeScreen(
|
||||
context: Context,
|
||||
onShowWorkouts: () -> Unit
|
||||
onShowWorkouts: () -> Unit,
|
||||
onCreateWorkout: () -> Unit
|
||||
) : LinearLayout(context) {
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setPadding(48, 48, 48, 48)
|
||||
AppStyle.applyGradientBackground(this)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
val topSpace = Space(context)
|
||||
topSpace.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
AppStyle.dp(this, 90)
|
||||
)
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = "Workout Timer"
|
||||
title.textSize = 32f
|
||||
title.gravity = Gravity.CENTER
|
||||
title.gravity = Gravity.START
|
||||
AppStyle.headline(title)
|
||||
|
||||
val subtitle = TextView(context)
|
||||
subtitle.text = "Plane und starte dein Workout"
|
||||
subtitle.textSize = 18f
|
||||
subtitle.gravity = Gravity.CENTER
|
||||
subtitle.text = "Build your own rhythm."
|
||||
subtitle.gravity = Gravity.START
|
||||
AppStyle.muted(subtitle)
|
||||
AppStyle.setTextMargin(subtitle)
|
||||
|
||||
val button = Button(context)
|
||||
button.text = "Gespeicherte Workouts"
|
||||
button.setOnClickListener {
|
||||
onShowWorkouts()
|
||||
}
|
||||
val buttonSpace = Space(context)
|
||||
buttonSpace.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
AppStyle.dp(this, 32)
|
||||
)
|
||||
|
||||
val showWorkoutsCard = AppStyle.actionCard(
|
||||
context = context,
|
||||
text = "Gespeicherte Workouts",
|
||||
dark = true,
|
||||
onClick = onShowWorkouts
|
||||
)
|
||||
|
||||
val createWorkoutCard = AppStyle.actionCard(
|
||||
context = context,
|
||||
text = "Workout erstellen",
|
||||
dark = false,
|
||||
onClick = onCreateWorkout
|
||||
)
|
||||
|
||||
val bottomNote = TextView(context)
|
||||
bottomNote.text = "time based? rep based? your choice!"
|
||||
bottomNote.gravity = Gravity.START
|
||||
AppStyle.muted(bottomNote)
|
||||
AppStyle.setTextMargin(bottomNote)
|
||||
|
||||
addView(topSpace)
|
||||
addView(title)
|
||||
addView(subtitle)
|
||||
addView(button)
|
||||
addView(buttonSpace)
|
||||
addView(showWorkoutsCard)
|
||||
addView(createWorkoutCard)
|
||||
addView(bottomNote)
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class PauseScreen(
|
||||
context: Context,
|
||||
@ -13,28 +14,34 @@ class PauseScreen(
|
||||
) : LinearLayout(context) {
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setPadding(48, 48, 48, 48)
|
||||
AppStyle.applyGradientBackground(this)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = "Pause"
|
||||
title.textSize = 32f
|
||||
title.gravity = Gravity.CENTER
|
||||
AppStyle.headline(title)
|
||||
addView(title)
|
||||
|
||||
val info = TextView(context)
|
||||
info.text = "Atme kurz durch. Du kannst jederzeit weitermachen."
|
||||
AppStyle.muted(info)
|
||||
AppStyle.setTextMargin(info)
|
||||
addView(info)
|
||||
|
||||
val resumeButton = Button(context)
|
||||
resumeButton.text = "Weiter trainieren"
|
||||
resumeButton.text = "Weiter trainieren -->"
|
||||
AppStyle.primaryButton(resumeButton)
|
||||
resumeButton.setOnClickListener {
|
||||
onResume()
|
||||
}
|
||||
|
||||
val finishButton = Button(context)
|
||||
finishButton.text = "Workout beenden"
|
||||
AppStyle.secondaryButton(finishButton)
|
||||
finishButton.setOnClickListener {
|
||||
onFinish()
|
||||
}
|
||||
|
||||
addView(title)
|
||||
addView(resumeButton)
|
||||
addView(finishButton)
|
||||
}
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
package com.example.workouttimer.ui.screens
|
||||
|
||||
import android.content.Context
|
||||
import android.os.CountDownTimer
|
||||
import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class PreparationCountdownScreen(
|
||||
context: Context,
|
||||
onSkip: () -> Unit
|
||||
) : LinearLayout(context) {
|
||||
|
||||
private var remainingSeconds = 15
|
||||
private var timer: CountDownTimer? = null
|
||||
private val timerText = TextView(context)
|
||||
|
||||
init {
|
||||
AppStyle.applyGradientBackground(this)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = "Get\nReady"
|
||||
AppStyle.headline(title)
|
||||
addView(title)
|
||||
|
||||
val info = TextView(context)
|
||||
info.text = "Dein Workout startet gleich."
|
||||
AppStyle.muted(info)
|
||||
AppStyle.setTextMargin(info)
|
||||
addView(info)
|
||||
|
||||
timerText.gravity = Gravity.START
|
||||
AppStyle.timer(timerText)
|
||||
AppStyle.setTextMargin(timerText)
|
||||
addView(timerText)
|
||||
|
||||
val skipButton = Button(context)
|
||||
skipButton.text = "Jetzt starten -->"
|
||||
AppStyle.primaryButton(skipButton)
|
||||
skipButton.setOnClickListener {
|
||||
timer?.cancel()
|
||||
onSkip()
|
||||
}
|
||||
addView(skipButton)
|
||||
|
||||
val extendButton = Button(context)
|
||||
extendButton.text = "+10 Sekunden"
|
||||
AppStyle.secondaryButton(extendButton)
|
||||
extendButton.setOnClickListener {
|
||||
remainingSeconds += 10
|
||||
restartTimer(onSkip)
|
||||
}
|
||||
addView(extendButton)
|
||||
|
||||
restartTimer(onSkip)
|
||||
}
|
||||
|
||||
private fun restartTimer(onFinished: () -> Unit) {
|
||||
timer?.cancel()
|
||||
timerText.text = remainingSeconds.toString()
|
||||
|
||||
timer = object : CountDownTimer(remainingSeconds * 1000L, 1000L) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
remainingSeconds = (millisUntilFinished / 1000L).toInt()
|
||||
timerText.text = remainingSeconds.toString()
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
timerText.text = "0"
|
||||
onFinished()
|
||||
}
|
||||
}
|
||||
|
||||
timer?.start()
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
timer?.cancel()
|
||||
}
|
||||
}
|
||||
@ -4,9 +4,11 @@ import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Space
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.domain.ExerciseTarget
|
||||
import com.example.workouttimer.domain.Workout
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class ReadyToStartScreen(
|
||||
context: Context,
|
||||
@ -16,36 +18,70 @@ class ReadyToStartScreen(
|
||||
) : LinearLayout(context) {
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
setPadding(48, 48, 48, 48)
|
||||
AppStyle.applyGradientBackground(this)
|
||||
|
||||
layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT
|
||||
)
|
||||
|
||||
gravity = Gravity.TOP
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = workout?.name ?: "Kein Workout ausgewählt"
|
||||
title.textSize = 28f
|
||||
title.gravity = Gravity.CENTER
|
||||
title.text = "Ready\nto Start"
|
||||
AppStyle.headline(title)
|
||||
|
||||
addView(title)
|
||||
val workoutName = TextView(context)
|
||||
workoutName.text = workout?.name ?: "Kein Workout ausgewählt"
|
||||
AppStyle.title(workoutName)
|
||||
AppStyle.setTextMargin(workoutName)
|
||||
|
||||
workout?.exercises?.forEach { exercise ->
|
||||
val exerciseText = TextView(context)
|
||||
exerciseText.text = "${exercise.name} - ${formatTarget(exercise.target)}"
|
||||
exerciseText.textSize = 18f
|
||||
addView(exerciseText)
|
||||
val exerciseList = LinearLayout(context)
|
||||
exerciseList.orientation = VERTICAL
|
||||
|
||||
workout?.exercises?.forEachIndexed { index, exercise ->
|
||||
|
||||
val card = LinearLayout(context)
|
||||
AppStyle.card(card)
|
||||
|
||||
val exerciseTitle = TextView(context)
|
||||
exerciseTitle.text = "${index + 1}. ${exercise.name}"
|
||||
AppStyle.title(exerciseTitle)
|
||||
|
||||
val target = TextView(context)
|
||||
target.text = formatTarget(exercise.target)
|
||||
AppStyle.body(target)
|
||||
|
||||
card.addView(exerciseTitle)
|
||||
card.addView(target)
|
||||
|
||||
exerciseList.addView(card)
|
||||
}
|
||||
|
||||
val spacer = Space(context)
|
||||
spacer.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
AppStyle.dp(this, 32)
|
||||
)
|
||||
|
||||
val startButton = Button(context)
|
||||
startButton.text = "Workout starten"
|
||||
startButton.text = "Workout starten -->"
|
||||
AppStyle.primaryButton(startButton)
|
||||
startButton.setOnClickListener {
|
||||
onStart()
|
||||
}
|
||||
|
||||
val backButton = Button(context)
|
||||
backButton.text = "Zurück"
|
||||
AppStyle.secondaryButton(backButton)
|
||||
backButton.setOnClickListener {
|
||||
onBack()
|
||||
}
|
||||
|
||||
addView(title)
|
||||
addView(workoutName)
|
||||
addView(exerciseList)
|
||||
addView(spacer)
|
||||
addView(startButton)
|
||||
addView(backButton)
|
||||
}
|
||||
|
||||
@ -5,110 +5,146 @@ import android.os.CountDownTimer
|
||||
import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Space
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.domain.Exercise
|
||||
import com.example.workouttimer.domain.ExerciseTarget
|
||||
import com.example.workouttimer.domain.Workout
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class RunningWorkoutScreen(
|
||||
context: Context,
|
||||
workout: Workout?,
|
||||
exercise: Exercise?,
|
||||
nextExercise: Exercise?,
|
||||
exerciseNumber: Int,
|
||||
onNextExercise: () -> Unit,
|
||||
onPause: () -> Unit
|
||||
) : LinearLayout(context) {
|
||||
|
||||
private var countDownTimer: CountDownTimer? = null
|
||||
private var timer: CountDownTimer? = null
|
||||
private val mainValueText = TextView(context)
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setPadding(48, 48, 48, 48)
|
||||
AppStyle.applyGradientBackground(this)
|
||||
gravity = Gravity.CENTER_VERTICAL
|
||||
|
||||
val workoutTitle = TextView(context)
|
||||
workoutTitle.text = workout?.name ?: "Workout läuft"
|
||||
workoutTitle.textSize = 22f
|
||||
workoutTitle.gravity = Gravity.CENTER
|
||||
val workoutLabel = TextView(context)
|
||||
workoutLabel.text = workout?.name ?: "Workout läuft"
|
||||
workoutLabel.gravity = Gravity.CENTER
|
||||
AppStyle.muted(workoutLabel)
|
||||
|
||||
val topSpace = Space(context)
|
||||
topSpace.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
AppStyle.dp(this, 28)
|
||||
)
|
||||
|
||||
val exerciseTitle = TextView(context)
|
||||
exerciseTitle.text = "Übung $exerciseNumber: ${exercise?.name ?: "-"}"
|
||||
exerciseTitle.textSize = 30f
|
||||
exerciseTitle.text = "${exerciseNumber}. ${exercise?.name ?: "-"}"
|
||||
exerciseTitle.gravity = Gravity.CENTER
|
||||
AppStyle.headline(exerciseTitle)
|
||||
|
||||
val targetText = TextView(context)
|
||||
targetText.text = exercise?.target?.let { formatTarget(it) } ?: ""
|
||||
targetText.textSize = 24f
|
||||
targetText.gravity = Gravity.CENTER
|
||||
val middleSpace = Space(context)
|
||||
middleSpace.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
AppStyle.dp(this, 26)
|
||||
)
|
||||
|
||||
val timerText = TextView(context)
|
||||
timerText.textSize = 36f
|
||||
timerText.gravity = Gravity.CENTER
|
||||
mainValueText.gravity = Gravity.CENTER
|
||||
AppStyle.timer(mainValueText)
|
||||
|
||||
val infoText = TextView(context)
|
||||
infoText.text = exercise?.info ?: ""
|
||||
infoText.textSize = 16f
|
||||
infoText.gravity = Gravity.CENTER
|
||||
val unitText = TextView(context)
|
||||
unitText.gravity = Gravity.CENTER
|
||||
AppStyle.title(unitText)
|
||||
|
||||
when (val target = exercise?.target) {
|
||||
is ExerciseTarget.Repetitions -> {
|
||||
mainValueText.text = target.reps.toString()
|
||||
unitText.text = "Wiederholungen"
|
||||
}
|
||||
|
||||
is ExerciseTarget.Duration -> {
|
||||
mainValueText.text = target.seconds.toString()
|
||||
unitText.text = "Sekunden"
|
||||
startTimer(target.seconds, onNextExercise)
|
||||
}
|
||||
|
||||
null -> {
|
||||
mainValueText.text = "-"
|
||||
unitText.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
val nextText = TextView(context)
|
||||
nextText.gravity = Gravity.CENTER
|
||||
nextText.text = if (nextExercise != null) {
|
||||
"Next: ${nextExercise.name} / ${formatTarget(nextExercise.target)}"
|
||||
} else {
|
||||
"Next: Workout done"
|
||||
}
|
||||
AppStyle.body(nextText)
|
||||
AppStyle.setTextMargin(nextText)
|
||||
|
||||
val buttonSpace = Space(context)
|
||||
buttonSpace.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
AppStyle.dp(this, 34)
|
||||
)
|
||||
|
||||
val nextButton = Button(context)
|
||||
nextButton.text = "Übung geschafft / Weiter"
|
||||
nextButton.text = if (exercise?.target is ExerciseTarget.Duration) {
|
||||
"Übung überspringen -->"
|
||||
} else {
|
||||
"Übung geschafft -->"
|
||||
}
|
||||
AppStyle.primaryButton(nextButton)
|
||||
nextButton.setOnClickListener {
|
||||
countDownTimer?.cancel()
|
||||
timer?.cancel()
|
||||
onNextExercise()
|
||||
}
|
||||
|
||||
val pauseButton = Button(context)
|
||||
pauseButton.text = "Pause"
|
||||
AppStyle.secondaryButton(pauseButton)
|
||||
pauseButton.setOnClickListener {
|
||||
countDownTimer?.cancel()
|
||||
timer?.cancel()
|
||||
onPause()
|
||||
}
|
||||
|
||||
addView(workoutTitle)
|
||||
addView(workoutLabel)
|
||||
addView(topSpace)
|
||||
addView(exerciseTitle)
|
||||
addView(targetText)
|
||||
addView(timerText)
|
||||
addView(infoText)
|
||||
addView(middleSpace)
|
||||
addView(mainValueText)
|
||||
addView(unitText)
|
||||
addView(nextText)
|
||||
addView(buttonSpace)
|
||||
addView(nextButton)
|
||||
addView(pauseButton)
|
||||
|
||||
if (exercise?.target is ExerciseTarget.Duration) {
|
||||
nextButton.text = "Überspringen"
|
||||
startCountdown(
|
||||
seconds = exercise.target.seconds,
|
||||
timerText = timerText,
|
||||
onFinished = onNextExercise
|
||||
)
|
||||
} else {
|
||||
timerText.text = ""
|
||||
}
|
||||
}
|
||||
|
||||
private fun startCountdown(
|
||||
seconds: Int,
|
||||
timerText: TextView,
|
||||
onFinished: () -> Unit
|
||||
) {
|
||||
timerText.text = "$seconds"
|
||||
private fun startTimer(seconds: Int, onFinished: () -> Unit) {
|
||||
mainValueText.text = seconds.toString()
|
||||
|
||||
countDownTimer = object : CountDownTimer(seconds * 1000L, 1000L) {
|
||||
timer = object : CountDownTimer(seconds * 1000L, 1000L) {
|
||||
override fun onTick(millisUntilFinished: Long) {
|
||||
val remainingSeconds = (millisUntilFinished / 1000L).toInt()
|
||||
timerText.text = remainingSeconds.toString()
|
||||
val remaining = (millisUntilFinished / 1000L).toInt()
|
||||
mainValueText.text = remaining.toString()
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
timerText.text = "0"
|
||||
mainValueText.text = "0"
|
||||
onFinished()
|
||||
}
|
||||
}
|
||||
|
||||
countDownTimer?.start()
|
||||
timer?.start()
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
countDownTimer?.cancel()
|
||||
timer?.cancel()
|
||||
}
|
||||
|
||||
private fun formatTarget(target: ExerciseTarget): String {
|
||||
|
||||
@ -4,8 +4,10 @@ import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.widget.Button
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import com.example.workouttimer.domain.Workout
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class SavedWorkoutsScreen(
|
||||
context: Context,
|
||||
@ -15,64 +17,72 @@ class SavedWorkoutsScreen(
|
||||
onEditWorkout: (Workout) -> Unit,
|
||||
onDeleteWorkout: (Workout) -> Unit,
|
||||
onBack: () -> Unit
|
||||
) : LinearLayout(context) {
|
||||
) : ScrollView(context) {
|
||||
|
||||
init {
|
||||
orientation = VERTICAL
|
||||
gravity = Gravity.CENTER_HORIZONTAL
|
||||
setPadding(48, 48, 48, 48)
|
||||
background = AppStyle.gradientDrawable()
|
||||
|
||||
val content = LinearLayout(context)
|
||||
AppStyle.applyGradientBackground(content)
|
||||
|
||||
content.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
|
||||
addView(content)
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = "Gespeicherte Workouts"
|
||||
title.textSize = 28f
|
||||
title.gravity = Gravity.CENTER
|
||||
|
||||
addView(title)
|
||||
title.text = "Saved\nWorkouts"
|
||||
AppStyle.headline(title)
|
||||
content.addView(title)
|
||||
|
||||
val createButton = Button(context)
|
||||
createButton.text = "Neues Workout erstellen"
|
||||
createButton.setOnClickListener {
|
||||
onCreateWorkout()
|
||||
}
|
||||
addView(createButton)
|
||||
createButton.text = "Neues Workout erstellen -->"
|
||||
AppStyle.primaryButton(createButton)
|
||||
createButton.setOnClickListener { onCreateWorkout() }
|
||||
content.addView(createButton)
|
||||
|
||||
workouts.forEach { workout ->
|
||||
val card = LinearLayout(context)
|
||||
AppStyle.card(card)
|
||||
|
||||
val workoutRow = LinearLayout(context)
|
||||
workoutRow.orientation = HORIZONTAL
|
||||
workoutRow.gravity = Gravity.CENTER
|
||||
val name = TextView(context)
|
||||
name.text = workout.name
|
||||
AppStyle.title(name)
|
||||
|
||||
val workoutButton = Button(context)
|
||||
workoutButton.text = workout.name
|
||||
workoutButton.setOnClickListener {
|
||||
onWorkoutSelected(workout)
|
||||
}
|
||||
val details = TextView(context)
|
||||
details.text = "${workout.exercises.size} Übungen"
|
||||
AppStyle.muted(details)
|
||||
|
||||
val startButton = Button(context)
|
||||
startButton.text = "Starten -->"
|
||||
AppStyle.primaryButton(startButton)
|
||||
startButton.setOnClickListener { onWorkoutSelected(workout) }
|
||||
|
||||
val editButton = Button(context)
|
||||
editButton.text = "Bearbeiten"
|
||||
editButton.setOnClickListener {
|
||||
onEditWorkout(workout)
|
||||
}
|
||||
AppStyle.secondaryButton(editButton)
|
||||
editButton.setOnClickListener { onEditWorkout(workout) }
|
||||
|
||||
val deleteButton = Button(context)
|
||||
deleteButton.text = "Löschen"
|
||||
deleteButton.setOnClickListener {
|
||||
onDeleteWorkout(workout)
|
||||
}
|
||||
deleteButton.text = "Workout löschen"
|
||||
AppStyle.secondaryButton(deleteButton)
|
||||
deleteButton.setOnClickListener { onDeleteWorkout(workout) }
|
||||
|
||||
workoutRow.addView(workoutButton)
|
||||
workoutRow.addView(editButton)
|
||||
workoutRow.addView(deleteButton)
|
||||
card.addView(name)
|
||||
card.addView(details)
|
||||
card.addView(startButton)
|
||||
card.addView(editButton)
|
||||
card.addView(deleteButton)
|
||||
|
||||
addView(workoutRow)
|
||||
content.addView(card)
|
||||
}
|
||||
|
||||
val backButton = Button(context)
|
||||
backButton.text = "Zurück"
|
||||
backButton.setOnClickListener {
|
||||
onBack()
|
||||
}
|
||||
|
||||
addView(backButton)
|
||||
AppStyle.secondaryButton(backButton)
|
||||
backButton.setOnClickListener { onBack() }
|
||||
content.addView(backButton)
|
||||
}
|
||||
}
|
||||
@ -12,56 +12,64 @@ import android.widget.TextView
|
||||
import com.example.workouttimer.domain.Exercise
|
||||
import com.example.workouttimer.domain.ExerciseTarget
|
||||
import com.example.workouttimer.domain.Workout
|
||||
import com.example.workouttimer.ui.theme.AppStyle
|
||||
|
||||
class WorkoutEditorScreen(
|
||||
context: Context,
|
||||
workoutToEdit: Workout?,
|
||||
onSave: (
|
||||
name: String,
|
||||
exercises: List<Exercise>
|
||||
) -> Unit,
|
||||
onSave: (name: String, exercises: List<Exercise>) -> Unit,
|
||||
onCancel: () -> Unit
|
||||
) : ScrollView(context) {
|
||||
|
||||
private val exercises = mutableListOf<Exercise>()
|
||||
private val exerciseListContainer = LinearLayout(context)
|
||||
private var editingIndex: Int? = null
|
||||
|
||||
init {
|
||||
exerciseListContainer.orientation = LinearLayout.VERTICAL
|
||||
}
|
||||
background = AppStyle.gradientDrawable()
|
||||
|
||||
init {
|
||||
val content = LinearLayout(context)
|
||||
content.orientation = LinearLayout.VERTICAL
|
||||
content.gravity = Gravity.CENTER_HORIZONTAL
|
||||
content.setPadding(48, 48, 48, 48)
|
||||
|
||||
AppStyle.applyGradientBackground(content)
|
||||
content.layoutParams = LayoutParams(
|
||||
LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
addView(content)
|
||||
|
||||
workoutToEdit?.exercises?.let {
|
||||
exercises.addAll(it)
|
||||
}
|
||||
workoutToEdit?.exercises?.let { exercises.addAll(it) }
|
||||
|
||||
val title = TextView(context)
|
||||
title.text = if (workoutToEdit == null) "Workout erstellen" else "Workout bearbeiten"
|
||||
title.textSize = 28f
|
||||
title.gravity = Gravity.CENTER
|
||||
title.text = if (workoutToEdit == null) "Create\nWorkout" else "Edit\nWorkout"
|
||||
AppStyle.headline(title)
|
||||
content.addView(title)
|
||||
|
||||
val workoutNameInput = EditText(context)
|
||||
workoutNameInput.hint = "Workout Name"
|
||||
workoutNameInput.setText(workoutToEdit?.name ?: "")
|
||||
AppStyle.input(workoutNameInput)
|
||||
content.addView(workoutNameInput)
|
||||
|
||||
val sectionTitle = TextView(context)
|
||||
sectionTitle.text = "Neue Übung"
|
||||
AppStyle.sectionTitle(sectionTitle)
|
||||
content.addView(sectionTitle)
|
||||
|
||||
val exerciseNameInput = EditText(context)
|
||||
exerciseNameInput.hint = "Übungsname"
|
||||
AppStyle.input(exerciseNameInput)
|
||||
content.addView(exerciseNameInput)
|
||||
|
||||
val targetGroup = RadioGroup(context)
|
||||
targetGroup.orientation = RadioGroup.HORIZONTAL
|
||||
targetGroup.gravity = Gravity.CENTER
|
||||
|
||||
val repsButton = RadioButton(context)
|
||||
repsButton.text = "Wiederholungen"
|
||||
AppStyle.body(repsButton)
|
||||
|
||||
val timeButton = RadioButton(context)
|
||||
timeButton.text = "Zeit"
|
||||
AppStyle.body(timeButton)
|
||||
|
||||
val repsButtonId = generateViewId()
|
||||
val timeButtonId = generateViewId()
|
||||
@ -73,15 +81,63 @@ class WorkoutEditorScreen(
|
||||
targetGroup.addView(timeButton)
|
||||
targetGroup.check(repsButtonId)
|
||||
|
||||
AppStyle.setTextMargin(targetGroup)
|
||||
content.addView(targetGroup)
|
||||
|
||||
val targetValueInput = EditText(context)
|
||||
targetValueInput.hint = "Wert, z.B. 12 oder 30"
|
||||
targetValueInput.inputType = android.text.InputType.TYPE_CLASS_NUMBER
|
||||
AppStyle.input(targetValueInput)
|
||||
content.addView(targetValueInput)
|
||||
|
||||
val infoInput = EditText(context)
|
||||
infoInput.hint = "Info / Anmerkung"
|
||||
AppStyle.input(infoInput)
|
||||
content.addView(infoInput)
|
||||
|
||||
val addExerciseButton = Button(context)
|
||||
addExerciseButton.text = "Übung hinzufügen"
|
||||
addExerciseButton.text = "Übung hinzufügen -->"
|
||||
AppStyle.primaryButton(addExerciseButton)
|
||||
content.addView(addExerciseButton)
|
||||
|
||||
val listTitle = TextView(context)
|
||||
listTitle.text = "Workout Plan"
|
||||
AppStyle.sectionTitle(listTitle)
|
||||
content.addView(listTitle)
|
||||
|
||||
exerciseListContainer.orientation = LinearLayout.VERTICAL
|
||||
content.addView(exerciseListContainer)
|
||||
|
||||
fun clearExerciseInputs() {
|
||||
exerciseNameInput.text.clear()
|
||||
targetValueInput.text.clear()
|
||||
infoInput.text.clear()
|
||||
targetGroup.check(repsButtonId)
|
||||
editingIndex = null
|
||||
addExerciseButton.text = "Übung hinzufügen -->"
|
||||
}
|
||||
|
||||
fun fillExerciseInputs(index: Int) {
|
||||
val exercise = exercises[index]
|
||||
|
||||
exerciseNameInput.setText(exercise.name)
|
||||
infoInput.setText(exercise.info)
|
||||
|
||||
when (val target = exercise.target) {
|
||||
is ExerciseTarget.Repetitions -> {
|
||||
targetGroup.check(repsButtonId)
|
||||
targetValueInput.setText(target.reps.toString())
|
||||
}
|
||||
|
||||
is ExerciseTarget.Duration -> {
|
||||
targetGroup.check(timeButtonId)
|
||||
targetValueInput.setText(target.seconds.toString())
|
||||
}
|
||||
}
|
||||
|
||||
editingIndex = index
|
||||
addExerciseButton.text = "Änderung übernehmen -->"
|
||||
}
|
||||
|
||||
addExerciseButton.setOnClickListener {
|
||||
val exerciseName = exerciseNameInput.text.toString()
|
||||
@ -98,26 +154,34 @@ class WorkoutEditorScreen(
|
||||
ExerciseTarget.Duration(targetValueText.toInt())
|
||||
}
|
||||
|
||||
val exercise = Exercise(
|
||||
val indexToEdit = editingIndex
|
||||
|
||||
if (indexToEdit == null) {
|
||||
exercises.add(
|
||||
Exercise(
|
||||
id = exercises.size + 1,
|
||||
name = exerciseName,
|
||||
target = target,
|
||||
info = info
|
||||
)
|
||||
)
|
||||
} else {
|
||||
exercises[indexToEdit] = Exercise(
|
||||
id = indexToEdit + 1,
|
||||
name = exerciseName,
|
||||
target = target,
|
||||
info = info
|
||||
)
|
||||
}
|
||||
|
||||
exercises.add(exercise)
|
||||
|
||||
exerciseNameInput.text.clear()
|
||||
targetValueInput.text.clear()
|
||||
infoInput.text.clear()
|
||||
targetGroup.check(repsButtonId)
|
||||
|
||||
updateExerciseList()
|
||||
updateExerciseIds()
|
||||
clearExerciseInputs()
|
||||
updateExerciseList(::fillExerciseInputs)
|
||||
}
|
||||
|
||||
val saveButton = Button(context)
|
||||
saveButton.text = "Workout speichern"
|
||||
|
||||
saveButton.text = "Workout speichern -->"
|
||||
AppStyle.primaryButton(saveButton)
|
||||
saveButton.setOnClickListener {
|
||||
val workoutName = workoutNameInput.text.toString()
|
||||
|
||||
@ -130,70 +194,99 @@ class WorkoutEditorScreen(
|
||||
|
||||
val cancelButton = Button(context)
|
||||
cancelButton.text = "Abbrechen"
|
||||
AppStyle.secondaryButton(cancelButton)
|
||||
cancelButton.setOnClickListener {
|
||||
onCancel()
|
||||
}
|
||||
|
||||
content.addView(title)
|
||||
content.addView(workoutNameInput)
|
||||
|
||||
val exerciseSectionTitle = TextView(context)
|
||||
exerciseSectionTitle.text = "Übung hinzufügen"
|
||||
exerciseSectionTitle.textSize = 22f
|
||||
|
||||
content.addView(exerciseSectionTitle)
|
||||
content.addView(exerciseNameInput)
|
||||
content.addView(targetGroup)
|
||||
content.addView(targetValueInput)
|
||||
content.addView(infoInput)
|
||||
content.addView(addExerciseButton)
|
||||
|
||||
val listTitle = TextView(context)
|
||||
listTitle.text = "Übungen im Workout"
|
||||
listTitle.textSize = 22f
|
||||
|
||||
content.addView(listTitle)
|
||||
exerciseListContainer.orientation = LinearLayout.VERTICAL
|
||||
content.addView(exerciseListContainer)
|
||||
|
||||
content.addView(saveButton)
|
||||
content.addView(cancelButton)
|
||||
|
||||
updateExerciseList()
|
||||
updateExerciseList(::fillExerciseInputs)
|
||||
}
|
||||
|
||||
private fun updateExerciseList() {
|
||||
private fun updateExerciseList(onEditExercise: (Int) -> Unit) {
|
||||
exerciseListContainer.removeAllViews()
|
||||
|
||||
if (exercises.isEmpty()) {
|
||||
val emptyText = TextView(context)
|
||||
emptyText.text = "Noch keine Übungen hinzugefügt."
|
||||
AppStyle.muted(emptyText)
|
||||
AppStyle.setTextMargin(emptyText)
|
||||
exerciseListContainer.addView(emptyText)
|
||||
return
|
||||
}
|
||||
|
||||
exercises.forEachIndexed { index, exercise ->
|
||||
val card = LinearLayout(context)
|
||||
AppStyle.card(card)
|
||||
|
||||
val row = LinearLayout(context)
|
||||
row.orientation = LinearLayout.HORIZONTAL
|
||||
row.gravity = Gravity.CENTER_VERTICAL
|
||||
val exerciseTitle = TextView(context)
|
||||
exerciseTitle.text = "${index + 1}. ${exercise.name}"
|
||||
AppStyle.title(exerciseTitle)
|
||||
|
||||
val exerciseText = TextView(context)
|
||||
exerciseText.text = "${index + 1}. ${exercise.name} - ${formatTarget(exercise.target)}"
|
||||
exerciseText.textSize = 16f
|
||||
val targetText = TextView(context)
|
||||
targetText.text = formatTarget(exercise.target)
|
||||
AppStyle.body(targetText)
|
||||
|
||||
val infoText = TextView(context)
|
||||
infoText.text = exercise.info
|
||||
AppStyle.muted(infoText)
|
||||
|
||||
val editButton = Button(context)
|
||||
editButton.text = "Bearbeiten"
|
||||
AppStyle.primaryButton(editButton)
|
||||
editButton.setOnClickListener {
|
||||
onEditExercise(index)
|
||||
}
|
||||
|
||||
val upButton = Button(context)
|
||||
upButton.text = "Nach oben"
|
||||
AppStyle.secondaryButton(upButton)
|
||||
upButton.isEnabled = index > 0
|
||||
upButton.setOnClickListener {
|
||||
val temp = exercises[index - 1]
|
||||
exercises[index - 1] = exercises[index]
|
||||
exercises[index] = temp
|
||||
updateExerciseIds()
|
||||
updateExerciseList(onEditExercise)
|
||||
}
|
||||
|
||||
val downButton = Button(context)
|
||||
downButton.text = "Nach unten"
|
||||
AppStyle.secondaryButton(downButton)
|
||||
downButton.isEnabled = index < exercises.lastIndex
|
||||
downButton.setOnClickListener {
|
||||
val temp = exercises[index + 1]
|
||||
exercises[index + 1] = exercises[index]
|
||||
exercises[index] = temp
|
||||
updateExerciseIds()
|
||||
updateExerciseList(onEditExercise)
|
||||
}
|
||||
|
||||
val deleteButton = Button(context)
|
||||
deleteButton.text = "Löschen"
|
||||
AppStyle.secondaryButton(deleteButton)
|
||||
deleteButton.setOnClickListener {
|
||||
exercises.removeAt(index)
|
||||
editingIndex = null
|
||||
updateExerciseIds()
|
||||
updateExerciseList()
|
||||
updateExerciseList(onEditExercise)
|
||||
}
|
||||
|
||||
row.addView(exerciseText)
|
||||
row.addView(deleteButton)
|
||||
card.addView(exerciseTitle)
|
||||
card.addView(targetText)
|
||||
|
||||
exerciseListContainer.addView(row)
|
||||
if (exercise.info.isNotBlank()) {
|
||||
card.addView(infoText)
|
||||
}
|
||||
|
||||
card.addView(editButton)
|
||||
card.addView(upButton)
|
||||
card.addView(downButton)
|
||||
card.addView(deleteButton)
|
||||
|
||||
exerciseListContainer.addView(card)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
266
app/src/main/java/com/example/workouttimer/ui/theme/AppStyle.kt
Normal file
266
app/src/main/java/com/example/workouttimer/ui/theme/AppStyle.kt
Normal file
@ -0,0 +1,266 @@
|
||||
package com.example.workouttimer.ui.theme
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.GradientDrawable
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.example.workouttimer.R
|
||||
|
||||
object AppStyle {
|
||||
|
||||
val yellow = Color.rgb(245, 218, 49)
|
||||
val green = Color.rgb(172, 232, 122)
|
||||
val cyan = Color.rgb(111, 219, 232)
|
||||
val black = Color.rgb(0, 0, 0)
|
||||
val white = Color.rgb(255, 255, 255)
|
||||
val softWhite = Color.rgb(250, 250, 250)
|
||||
val lightBlack = Color.rgb(24, 24, 24)
|
||||
val mutedText = Color.rgb(70, 70, 70)
|
||||
|
||||
const val screenPadding = 48
|
||||
const val smallSpacing = 16
|
||||
const val mediumSpacing = 24
|
||||
const val largeSpacing = 40
|
||||
const val cornerRadius = 4f
|
||||
|
||||
private val regularFontId = R.font.funnel_display_regular
|
||||
private val boldFontId = R.font.funnel_display_bold
|
||||
private val mediumFontId = R.font.funnel_display_medium
|
||||
private val extraBoldFontId = R.font.funnel_display_extra_bold
|
||||
|
||||
fun regular(view: TextView) {
|
||||
view.typeface = ResourcesCompat.getFont(view.context, regularFontId)
|
||||
}
|
||||
|
||||
fun medium(view: TextView) {
|
||||
view.typeface = ResourcesCompat.getFont(view.context, mediumFontId)
|
||||
}
|
||||
|
||||
fun bold(view: TextView) {
|
||||
view.typeface = ResourcesCompat.getFont(view.context, boldFontId)
|
||||
}
|
||||
|
||||
fun extraBold(view: TextView) {
|
||||
view.typeface = ResourcesCompat.getFont(view.context, extraBoldFontId)
|
||||
}
|
||||
|
||||
fun dp(view: View, value: Int): Int {
|
||||
return (value * view.context.resources.displayMetrics.density).toInt()
|
||||
}
|
||||
|
||||
fun applyGradientBackground(layout: LinearLayout) {
|
||||
layout.orientation = LinearLayout.VERTICAL
|
||||
layout.setPadding(
|
||||
dp(layout, 28),
|
||||
dp(layout, 56),
|
||||
dp(layout, 28),
|
||||
dp(layout, 28)
|
||||
)
|
||||
|
||||
val gradient = GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
intArrayOf(yellow, green, cyan)
|
||||
)
|
||||
|
||||
layout.background = gradientDrawable()
|
||||
}
|
||||
|
||||
fun headline(textView: TextView) {
|
||||
extraBold(textView)
|
||||
textView.textSize = 48f
|
||||
textView.setTextColor(black)
|
||||
}
|
||||
|
||||
fun title(textView: TextView) {
|
||||
bold(textView)
|
||||
textView.textSize = 30f
|
||||
textView.setTextColor(black)
|
||||
}
|
||||
|
||||
fun sectionTitle(textView: TextView) {
|
||||
bold(textView)
|
||||
textView.textSize = 22f
|
||||
textView.setTextColor(black)
|
||||
setTextMargin(textView)
|
||||
}
|
||||
|
||||
fun body(textView: TextView) {
|
||||
regular(textView)
|
||||
textView.textSize = 17f
|
||||
textView.setTextColor(black)
|
||||
}
|
||||
|
||||
fun muted(textView: TextView) {
|
||||
regular(textView)
|
||||
textView.textSize = 15f
|
||||
textView.setTextColor(mutedText)
|
||||
}
|
||||
|
||||
fun timer(textView: TextView) {
|
||||
extraBold(textView)
|
||||
textView.textSize = 76f
|
||||
textView.setTextColor(black)
|
||||
}
|
||||
|
||||
fun primaryButton(button: Button) {
|
||||
bold(button)
|
||||
button.textSize = 16f
|
||||
button.setTextColor(white)
|
||||
button.background = roundedBackground(black)
|
||||
button.isAllCaps = false
|
||||
setFullWidthMargin(button)
|
||||
}
|
||||
|
||||
fun secondaryButton(button: Button) {
|
||||
bold(button)
|
||||
button.textSize = 16f
|
||||
button.setTextColor(black)
|
||||
button.background = roundedBackground(white)
|
||||
button.isAllCaps = false
|
||||
setFullWidthMargin(button)
|
||||
}
|
||||
|
||||
fun dangerButton(button: Button) {
|
||||
bold(button)
|
||||
button.textSize = 16f
|
||||
button.setTextColor(white)
|
||||
button.background = roundedBackground(Color.rgb(210, 55, 55))
|
||||
button.isAllCaps = false
|
||||
setFullWidthMargin(button)
|
||||
}
|
||||
|
||||
fun compactButton(button: Button) {
|
||||
medium(button)
|
||||
button.textSize = 14f
|
||||
button.setTextColor(black)
|
||||
button.background = roundedBackground(white)
|
||||
button.isAllCaps = false
|
||||
}
|
||||
|
||||
fun input(editText: EditText) {
|
||||
regular(editText)
|
||||
editText.textSize = 16f
|
||||
editText.setTextColor(black)
|
||||
editText.setHintTextColor(mutedText)
|
||||
editText.background = roundedStrokeBackground(white)
|
||||
editText.setPadding(28, 12, 28, 12)
|
||||
setFullWidthMargin(editText)
|
||||
}
|
||||
|
||||
fun card(layout: LinearLayout) {
|
||||
layout.orientation = LinearLayout.VERTICAL
|
||||
layout.background = roundedBackground(softWhite)
|
||||
layout.setPadding(28, 24, 28, 24)
|
||||
|
||||
val params = LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.setMargins(0, mediumSpacing, 0, 0)
|
||||
layout.layoutParams = params
|
||||
}
|
||||
|
||||
fun row(layout: LinearLayout) {
|
||||
layout.orientation = LinearLayout.HORIZONTAL
|
||||
}
|
||||
|
||||
fun setFullWidthMargin(view: View) {
|
||||
val params = LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
dp(view, 58)
|
||||
)
|
||||
params.setMargins(0, dp(view, 14), 0, 0)
|
||||
view.layoutParams = params
|
||||
}
|
||||
|
||||
fun setTextMargin(view: View) {
|
||||
val params = LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
params.setMargins(0, mediumSpacing, 0, 0)
|
||||
view.layoutParams = params
|
||||
}
|
||||
|
||||
fun roundedBackground(color: Int): GradientDrawable {
|
||||
return GradientDrawable().apply {
|
||||
setColor(color)
|
||||
cornerRadius = AppStyle.cornerRadius
|
||||
}
|
||||
}
|
||||
|
||||
fun roundedStrokeBackground(color: Int): GradientDrawable {
|
||||
return GradientDrawable().apply {
|
||||
setColor(color)
|
||||
cornerRadius = AppStyle.cornerRadius
|
||||
setStroke(2, black)
|
||||
}
|
||||
}
|
||||
|
||||
fun squareBackground(color: Int): GradientDrawable {
|
||||
return GradientDrawable().apply {
|
||||
setColor(color)
|
||||
cornerRadius = 0f
|
||||
}
|
||||
}
|
||||
|
||||
fun actionCard(
|
||||
context: android.content.Context,
|
||||
text: String,
|
||||
dark: Boolean,
|
||||
onClick: () -> Unit
|
||||
): LinearLayout {
|
||||
val card = LinearLayout(context)
|
||||
card.orientation = LinearLayout.HORIZONTAL
|
||||
card.gravity = android.view.Gravity.CENTER_VERTICAL
|
||||
card.setPadding(dp(card, 20), 0, dp(card, 20), 0)
|
||||
card.background = squareBackground(if (dark) black else white)
|
||||
card.setOnClickListener { onClick() }
|
||||
|
||||
val label = TextView(context)
|
||||
label.text = text
|
||||
bold(label)
|
||||
label.textSize = 20f
|
||||
label.setTextColor(if (dark) white else black)
|
||||
|
||||
val arrow = TextView(context)
|
||||
arrow.text = " -->"
|
||||
bold(arrow)
|
||||
arrow.textSize = 30f
|
||||
arrow.setTextColor(if (dark) white else black)
|
||||
arrow.gravity = android.view.Gravity.END
|
||||
|
||||
val labelParams = LinearLayout.LayoutParams(
|
||||
0,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
1f
|
||||
)
|
||||
labelParams.setMargins(dp(card, 16), 0, dp(card, 16), 0)
|
||||
|
||||
label.layoutParams = labelParams
|
||||
|
||||
val cardParams = LinearLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
dp(card, 62)
|
||||
)
|
||||
cardParams.setMargins(0, dp(card, 14), 0, 0)
|
||||
card.layoutParams = cardParams
|
||||
|
||||
card.addView(label)
|
||||
card.addView(arrow)
|
||||
|
||||
return card
|
||||
}
|
||||
|
||||
fun gradientDrawable(): GradientDrawable {
|
||||
return GradientDrawable(
|
||||
GradientDrawable.Orientation.TOP_BOTTOM,
|
||||
intArrayOf(yellow, green, cyan)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -114,4 +114,15 @@ class WorkoutViewModel(context: Context) {
|
||||
val workout = currentWorkout ?: return null
|
||||
return workout.exercises[currentExerciseIndex]
|
||||
}
|
||||
|
||||
fun getNextExercise(): Exercise? {
|
||||
val workout = currentWorkout ?: return null
|
||||
val nextIndex = currentExerciseIndex + 1
|
||||
|
||||
return if (nextIndex <= workout.exercises.lastIndex) {
|
||||
workout.exercises[nextIndex]
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
app/src/main/res/font/funnel_display_bold.ttf
Normal file
BIN
app/src/main/res/font/funnel_display_bold.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/funnel_display_extra_bold.ttf
Normal file
BIN
app/src/main/res/font/funnel_display_extra_bold.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/funnel_display_light.ttf
Normal file
BIN
app/src/main/res/font/funnel_display_light.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/funnel_display_medium.ttf
Normal file
BIN
app/src/main/res/font/funnel_display_medium.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/funnel_display_regular.ttf
Normal file
BIN
app/src/main/res/font/funnel_display_regular.ttf
Normal file
Binary file not shown.
BIN
app/src/main/res/font/funnel_display_semi_bold.ttf
Normal file
BIN
app/src/main/res/font/funnel_display_semi_bold.ttf
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user