Skip to content

Commit

Permalink
Added Clock View (Gurupreet#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
randheer094 authored Sep 19, 2021
1 parent 5c3f67b commit 779d6e3
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.guru.composecookbook.ui.home.clock

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun ClockDemo(
viewModel: ClockViewModel = androidx.lifecycle.viewmodel.compose.viewModel()
) {
val clockState: Triple<Float, Float, Float> by viewModel.clockState.collectAsState()
Surface {
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
ClockView(
hourAngle = clockState.first,
minuteAngle = clockState.second,
secondAngle = clockState.third,
modifier = Modifier
.height(200.dp)
.width(200.dp)
.background(color = MaterialTheme.colors.surface, shape = CircleShape)
)
}
}
}
104 changes: 104 additions & 0 deletions app/src/main/java/com/guru/composecookbook/ui/home/clock/ClockView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.guru.composecookbook.ui.home.clock

import androidx.compose.foundation.Canvas
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.dp
import kotlin.math.cos
import kotlin.math.sin

@Composable
fun ClockView(
hourAngle: Float,
minuteAngle: Float,
secondAngle: Float,
modifier: Modifier = Modifier,
textColor: Color = MaterialTheme.colors.onSurface,
hourHandColor: Color = MaterialTheme.colors.onSurface,
minuteHandColor: Color = MaterialTheme.colors.onSurface,
secondHandColor: Color = MaterialTheme.colors.onSurface
) {
Canvas(modifier = modifier) {
// Outer Circle
drawCircle(color = textColor, style = Stroke(2.dp.toPx()))

// Hour Lines
val lineOuterR = (size.minDimension / 2.0f).minus(6.dp.toPx())
val lineInnerR = (size.minDimension / 2.0f).minus(18.dp.toPx())
val origin = size.minDimension / 2.0f
for (i in 0..11) {
val xRad = cos(30.0 * i * Math.PI / 180F)
val yRad = sin(30.0 * i * Math.PI / 180F)
drawLine(
color = textColor,
start = Offset(
(origin + (lineInnerR * xRad)).toFloat(),
(origin + (lineInnerR * yRad)).toFloat()
),
end = Offset(
(origin + (lineOuterR * xRad)).toFloat(),
(origin + (lineOuterR * yRad)).toFloat()
),
strokeWidth = 2.dp.toPx(),
cap = StrokeCap.Round,
)
}

// Inner Circle
val rInnerCircle = (size.minDimension / 2.0f).minus(22.dp.toPx())
drawCircle(color = textColor, radius = rInnerCircle, style = Stroke(1.dp.toPx()))

// Center
drawCircle(color = textColor, radius = 4.dp.toPx())

// Hour Hand
val xRadHour = cos(hourAngle * Math.PI / 180F)
val yRadHour = sin(hourAngle * Math.PI / 180F)
val rHour = rInnerCircle.times(3).div(4)
drawLine(
color = hourHandColor,
start = Offset(origin, origin),
end = Offset(
(origin + (rHour * xRadHour)).toFloat(),
(origin + (rHour * yRadHour)).toFloat()
),
strokeWidth = 3.dp.toPx(),
cap = StrokeCap.Round
)

// Minute Hand
val xRadMinute = cos(minuteAngle * Math.PI / 180F)
val yRadMinute = sin(minuteAngle * Math.PI / 180F)
val rMinute = rInnerCircle.minus(2.dp.toPx())
drawLine(
color = minuteHandColor,
start = Offset(origin, origin),
end = Offset(
(origin + (rMinute * xRadMinute)).toFloat(),
(origin + (rMinute * yRadMinute)).toFloat()
),
strokeWidth = 2.dp.toPx(),
cap = StrokeCap.Round
)

// Second Hand
val xRadSecond = cos(secondAngle * Math.PI / 180F)
val yRadSecond = sin(secondAngle * Math.PI / 180F)
val rSecond = lineOuterR.minus(2.dp.toPx())
drawLine(
color = secondHandColor,
start = Offset(origin, origin),
end = Offset(
(origin + (rSecond * xRadSecond)).toFloat(),
(origin + (rSecond * yRadSecond)).toFloat()
),
strokeWidth = 1.dp.toPx(),
cap = StrokeCap.Round
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.guru.composecookbook.ui.home.clock

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import java.util.*

class ClockViewModel : ViewModel() {

private val _clockState = MutableStateFlow(Triple(0f, 0f, 0f))
val clockState: StateFlow<Triple<Float, Float, Float>> = _clockState

init {
initTimer()
}

private fun initTimer() {
viewModelScope.launch {
while (true) {
val cal = Calendar.getInstance()
val hour = cal.get(Calendar.HOUR)
val minute = cal.get(Calendar.MINUTE)
val second = cal.get(Calendar.SECOND)
val secondAngle = (second * 6f).minus(90).plus(360).rem(360)
val minuteAngle = (minute * 6f).plus(second / 10f)
.minus(90).plus(360).rem(360)
val hourAngle = (hour * 30f).plus(minute / 2f)
.minus(90).plus(360).rem(360)
_clockState.emit(Triple(hourAngle, minuteAngle, secondAngle))
delay(1000L)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ val templates = listOf(
"Loaders",
"Canvas Drawing",
"Animations",
"Timer"
"Timer",
"Clock View"
)
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.guru.composecookbook.onboarding.OnBoardingScreen
import com.guru.composecookbook.paymentcard.AddPaymentScreen
import com.guru.composecookbook.profile.ProfileScreen
import com.guru.composecookbook.theme.ComposeCookBookTheme
import com.guru.composecookbook.ui.home.clock.ClockDemo
import com.guru.composecookbook.ui.home.timer.TimerDemo
import com.guru.pinlock.PinLockView

Expand Down Expand Up @@ -67,6 +68,7 @@ fun TemplateApp(templateType: String) {
"Adding Payment Card" -> AddPaymentScreen()
"Pin Lock/BioMetric" -> PinLockView()
"Timer" -> TimerDemo()
"Clock View" -> ClockDemo()
else -> ComingSoon()
}
}
Expand Down

0 comments on commit 779d6e3

Please sign in to comment.