├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── io │ │ └── github │ │ └── hanihashemi │ │ └── alarmclock │ │ ├── MainActivity.kt │ │ └── ui │ │ ├── AnalongClockComponent.kt │ │ ├── ModifierShadow.kt │ │ └── theme │ │ ├── Color.kt │ │ ├── Theme.kt │ │ └── Type.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ ├── ic_baseline_hourglass_bottom_24.xml │ ├── ic_launcher_background.xml │ ├── ic_outline_access_time_24.xml │ ├── ic_outline_alarm_24.xml │ ├── ic_outline_hotel_24.xml │ └── ic_outline_timer_24.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-mdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxxhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── values │ ├── colors.xml │ ├── font_certs.xml │ ├── strings.xml │ └── themes.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .DS_Store 5 | /build 6 | /captures 7 | .externalNativeBuild 8 | .cxx 9 | local.properties 10 | /.idea/ 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alarm Clock App with Jetpack Compose 2 | 3 | Join me in this tutorial as I guide you on how to create an alarm clock app using Jetpack Compose. Due to my cold, my voice may not sound the best but I will still provide clear and concise instructions on how to build the app step by step. Don't let my cold stop you from learning and creating your own alarm clock app with Jetpack Compose. 4 | 5 | My youtube channel: https://www.youtube.com/@HaniTech 6 | 7 | 8 | Blog post: https://medium.com/@hanihashemi/how-to-implement-a-clock-with-jetpack-compose-0e65be4a0a27 9 | ![Thumbnail](https://user-images.githubusercontent.com/2553497/212576539-355770d2-bed4-4fd8-ad55-739252af5b22.png) 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'org.jetbrains.kotlin.android' 4 | } 5 | 6 | android { 7 | namespace 'io.github.hanihashemi.alarmclock' 8 | compileSdk 33 9 | 10 | defaultConfig { 11 | applicationId "io.github.hanihashemi.alarmclock" 12 | minSdk 26 13 | targetSdk 33 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | vectorDrawables { 19 | useSupportLibrary true 20 | } 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_8 31 | targetCompatibility JavaVersion.VERSION_1_8 32 | } 33 | kotlinOptions { 34 | jvmTarget = '1.8' 35 | } 36 | buildFeatures { 37 | compose true 38 | } 39 | composeOptions { 40 | kotlinCompilerExtensionVersion '1.3.2' 41 | } 42 | packagingOptions { 43 | resources { 44 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 45 | } 46 | } 47 | } 48 | 49 | dependencies { 50 | implementation "androidx.compose.ui:ui-text-google-fonts:$compose_version" 51 | 52 | implementation 'androidx.core:core-ktx:1.9.0' 53 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' 54 | implementation 'androidx.activity:activity-compose:1.6.1' 55 | implementation "androidx.compose.ui:ui:$compose_version" 56 | implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" 57 | implementation 'androidx.compose.material3:material3:1.1.0-alpha03' 58 | testImplementation 'junit:junit:4.13.2' 59 | androidTestImplementation 'androidx.test.ext:junit:1.1.4' 60 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' 61 | androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" 62 | debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" 63 | debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version" 64 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/hanihashemi/alarmclock/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package io.github.hanihashemi.alarmclock 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.foundation.layout.* 7 | import androidx.compose.foundation.shape.RoundedCornerShape 8 | import androidx.compose.material3.* 9 | import androidx.compose.runtime.* 10 | import androidx.compose.ui.Alignment 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.draw.clip 13 | import androidx.compose.ui.res.painterResource 14 | import androidx.compose.ui.text.TextStyle 15 | import androidx.compose.ui.unit.dp 16 | import io.github.hanihashemi.alarmclock.ui.AnalogClockComponent 17 | import io.github.hanihashemi.alarmclock.ui.shadow 18 | import io.github.hanihashemi.alarmclock.ui.theme.AlarmClockTheme 19 | import io.github.hanihashemi.alarmclock.ui.theme.NavigationBarColor 20 | import io.github.hanihashemi.alarmclock.ui.theme.NavigationBarShadowColor 21 | import kotlinx.coroutines.delay 22 | import java.util.* 23 | 24 | class MainActivity : ComponentActivity() { 25 | @OptIn(ExperimentalMaterial3Api::class) 26 | override fun onCreate(savedInstanceState: Bundle?) { 27 | super.onCreate(savedInstanceState) 28 | setContent { 29 | var hour by remember { mutableStateOf("0") } 30 | var minute by remember { mutableStateOf("0") } 31 | var second by remember { mutableStateOf("0") } 32 | var amOrPm by remember { mutableStateOf("0") } 33 | 34 | LaunchedEffect(Unit) { 35 | while (true) { 36 | val cal = Calendar.getInstance() 37 | hour = cal.get(Calendar.HOUR).run { 38 | if (this.toString().length == 1) "0$this" else "$this" 39 | } 40 | minute = cal.get(Calendar.MINUTE).run { 41 | if (this.toString().length == 1) "0$this" else "$this" 42 | } 43 | second = cal.get(Calendar.SECOND).run { 44 | if (this.toString().length == 1) "0$this" else "$this" 45 | } 46 | amOrPm = cal.get(Calendar.AM_PM).run { 47 | if (this == Calendar.AM) "AM" else "PM" 48 | } 49 | 50 | delay(1000) 51 | } 52 | } 53 | 54 | AlarmClockTheme { 55 | Scaffold(bottomBar = { NavigationBarComponent() }) { 56 | Box( 57 | modifier = Modifier 58 | .padding(it) 59 | .fillMaxSize(), 60 | contentAlignment = Alignment.Center 61 | ) { 62 | Column(horizontalAlignment = Alignment.CenterHorizontally) { 63 | HeaderComponent() 64 | 65 | Box( 66 | modifier = Modifier 67 | .fillMaxSize() 68 | .fillMaxHeight(fraction = 0.8f), 69 | contentAlignment = Alignment.Center 70 | ) { 71 | Column(horizontalAlignment = Alignment.CenterHorizontally) { 72 | AnalogClockComponent( 73 | hour = hour.toInt(), 74 | minute = minute.toInt(), 75 | second = second.toInt() 76 | ) 77 | Spacer(modifier = Modifier.height(24.dp)) 78 | DigitalClockComponent( 79 | hour = hour, 80 | minute = minute, 81 | amOrPm = amOrPm, 82 | ) 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } 92 | 93 | @Composable 94 | fun HeaderComponent() { 95 | Box(modifier = Modifier.padding(vertical = 16.dp)) { 96 | Text(text = "Clock", style = MaterialTheme.typography.titleMedium) 97 | } 98 | } 99 | 100 | @Composable 101 | fun NavigationBarComponent() { 102 | NavigationBar( 103 | modifier = Modifier 104 | .shadow( 105 | color = NavigationBarShadowColor, 106 | offsetX = 0.dp, 107 | offsetY = (-5).dp, 108 | blurRadius = 50.dp 109 | ) 110 | .clip(RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp)), 111 | containerColor = NavigationBarColor 112 | ) { 113 | NavigationBarItem(icon = { 114 | Icon( 115 | painter = painterResource(id = R.drawable.ic_outline_alarm_24), 116 | contentDescription = null 117 | ) 118 | }, selected = false, onClick = { }) 119 | NavigationBarItem(icon = { 120 | Icon( 121 | painter = painterResource(id = R.drawable.ic_baseline_hourglass_bottom_24), 122 | contentDescription = null 123 | ) 124 | }, selected = false, onClick = { }) 125 | NavigationBarItem(icon = { 126 | Icon( 127 | painter = painterResource(id = R.drawable.ic_outline_access_time_24), 128 | contentDescription = null 129 | ) 130 | }, selected = true, onClick = { }) 131 | NavigationBarItem(icon = { 132 | Icon( 133 | painter = painterResource(id = R.drawable.ic_outline_timer_24), 134 | contentDescription = null 135 | ) 136 | }, selected = false, onClick = { }) 137 | NavigationBarItem(icon = { 138 | Icon( 139 | painter = painterResource(id = R.drawable.ic_outline_hotel_24), 140 | contentDescription = null 141 | ) 142 | }, selected = false, onClick = { }) 143 | } 144 | } 145 | 146 | @Composable 147 | fun DigitalClockComponent( 148 | hour: String, 149 | minute: String, 150 | amOrPm: String, 151 | ) { 152 | Text( 153 | text = "$hour:$minute $amOrPm", style = MaterialTheme.typography.titleLarge 154 | ) 155 | Text( 156 | text = "Berlin, Germany", style = MaterialTheme.typography.bodyMedium.merge( 157 | TextStyle( 158 | color = MaterialTheme.colorScheme.onBackground.copy( 159 | alpha = 0.6f 160 | ) 161 | ) 162 | ) 163 | ) 164 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/hanihashemi/alarmclock/ui/AnalongClockComponent.kt: -------------------------------------------------------------------------------- 1 | package io.github.hanihashemi.alarmclock.ui 2 | 3 | import androidx.compose.foundation.Canvas 4 | import androidx.compose.foundation.background 5 | import androidx.compose.foundation.layout.Box 6 | import androidx.compose.foundation.layout.aspectRatio 7 | import androidx.compose.foundation.layout.fillMaxSize 8 | import androidx.compose.foundation.shape.CircleShape 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Alignment 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.draw.clip 13 | import androidx.compose.ui.geometry.Offset 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.graphics.StrokeCap 16 | import androidx.compose.ui.graphics.drawscope.rotate 17 | import androidx.compose.ui.unit.dp 18 | import io.github.hanihashemi.alarmclock.ui.theme.* 19 | import kotlin.math.min 20 | 21 | @Composable 22 | fun AnalogClockComponent( 23 | hour: Int, 24 | minute: Int, 25 | second: Int, 26 | ) { 27 | Box( 28 | contentAlignment = Alignment.Center, 29 | modifier = Modifier 30 | .fillMaxSize(fraction = 0.6f) 31 | .aspectRatio(1f) 32 | .shadowCircular( 33 | offsetX = (-38).dp, 34 | offsetY = 0.dp, 35 | blurRadius = 54.dp, 36 | color = AnalogClockOuterBoxShadow1 37 | ) 38 | .shadowCircular( 39 | offsetX = (30).dp, 40 | offsetY = 0.dp, 41 | blurRadius = 54.dp, 42 | color = AnalogClockOuterBoxShadow2 43 | ) 44 | .shadowCircular( 45 | offsetX = (-11).dp, 46 | offsetY = 0.dp, 47 | blurRadius = 44.dp, 48 | color = AnalogClockOuterBoxShadow3 49 | ) 50 | .shadowCircular( 51 | offsetX = (10).dp, 52 | offsetY = 0.dp, 53 | blurRadius = 44.dp, 54 | color = AnalogClockOuterBoxShadow4 55 | ) 56 | .clip(CircleShape) 57 | .background(AnalogClockOuterBoxColor) 58 | ) { 59 | Box( 60 | modifier = Modifier 61 | .fillMaxSize(fraction = 0.78f) 62 | .aspectRatio(1f) 63 | .shadowCircular( 64 | offsetX = 4.dp, 65 | offsetY = 0.dp, 66 | blurRadius = 10.dp, 67 | color = AnalogClockInnerBoxShadow 68 | ) 69 | .clip(CircleShape) 70 | .background(AnalogClockInnerBoxColor) 71 | ) { 72 | Canvas(modifier = Modifier.fillMaxSize()) { 73 | val diameter = min(size.width, size.height) * 0.9f 74 | val radius = diameter / 2 75 | 76 | repeat(4) { 77 | val start = center - Offset(0f, radius) 78 | val end = start + Offset(0f, radius / 40f) 79 | rotate(it / 4f * 360) { 80 | drawLine( 81 | color = Color.White, 82 | start = start, 83 | end = end, 84 | strokeWidth = 5.dp.toPx(), 85 | cap = StrokeCap.Round 86 | ) 87 | } 88 | } 89 | 90 | val secondRatio = second / 60f 91 | val minuteRatio = minute / 60f 92 | val hourRatio = hour / 12f 93 | 94 | rotate(hourRatio * 360, center) { 95 | drawLine( 96 | color = AnalogClockHourHandColor, 97 | start = center - Offset(0f, radius * 0.4f), 98 | end = center + Offset(0f, radius * 0.1f), 99 | strokeWidth = 3.8.dp.toPx(), 100 | cap = StrokeCap.Round 101 | ) 102 | } 103 | 104 | rotate(minuteRatio * 360, center) { 105 | drawLine( 106 | color = AnalogClockMinuteHandColor, 107 | start = center - Offset(0f, radius * 0.6f), 108 | end = center + Offset(0f, radius * 0.1f), 109 | strokeWidth = 3.dp.toPx(), 110 | cap = StrokeCap.Round 111 | ) 112 | } 113 | 114 | rotate(secondRatio * 360, center) { 115 | drawLine( 116 | color = AnalogClockSecondHandColor, 117 | start = center - Offset(0f, radius * 0.7f), 118 | end = center + Offset(0f, radius * 0.1f), 119 | strokeWidth = 3.dp.toPx(), 120 | cap = StrokeCap.Round 121 | ) 122 | } 123 | 124 | drawCircle( 125 | color = AnalogClockSecondHandColor, 126 | radius = 5.dp.toPx(), 127 | center = center 128 | ) 129 | } 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /app/src/main/java/io/github/hanihashemi/alarmclock/ui/ModifierShadow.kt: -------------------------------------------------------------------------------- 1 | package io.github.hanihashemi.alarmclock.ui 2 | 3 | import android.graphics.BlurMaskFilter 4 | import android.graphics.BlurMaskFilter.Blur.NORMAL 5 | import androidx.compose.ui.Modifier 6 | import androidx.compose.ui.draw.drawBehind 7 | import androidx.compose.ui.geometry.Offset 8 | import androidx.compose.ui.graphics.Color 9 | import androidx.compose.ui.graphics.Paint 10 | import androidx.compose.ui.graphics.drawscope.drawIntoCanvas 11 | import androidx.compose.ui.graphics.toArgb 12 | import androidx.compose.ui.unit.Dp 13 | import androidx.compose.ui.unit.dp 14 | 15 | fun Modifier.shadow( 16 | color: Color = Color.Black, 17 | offsetX: Dp = 0.dp, 18 | offsetY: Dp = 0.dp, 19 | blurRadius: Dp = 0.dp, 20 | ) = then( 21 | drawBehind { 22 | drawIntoCanvas { canvas -> 23 | val paint = Paint() 24 | val frameworkPaint = paint.asFrameworkPaint() 25 | if (blurRadius != 0.dp) { 26 | frameworkPaint.maskFilter = (BlurMaskFilter(blurRadius.toPx(), NORMAL)) 27 | } 28 | frameworkPaint.color = color.toArgb() 29 | 30 | val leftPixel = offsetX.toPx() 31 | val topPixel = offsetY.toPx() 32 | val rightPixel = size.width + topPixel 33 | val bottomPixel = size.height + leftPixel 34 | 35 | canvas.drawRect( 36 | left = leftPixel, 37 | top = topPixel, 38 | right = rightPixel, 39 | bottom = bottomPixel, 40 | paint = paint, 41 | ) 42 | } 43 | } 44 | ) 45 | 46 | fun Modifier.shadowCircular( 47 | color: Color = Color.Black, 48 | offsetX: Dp = 0.dp, 49 | offsetY: Dp = 0.dp, 50 | blurRadius: Dp = 0.dp 51 | ) = then( 52 | drawBehind { 53 | drawIntoCanvas {canvas -> 54 | val paint = Paint() 55 | val frameworkPaint = paint.asFrameworkPaint() 56 | if (blurRadius != 0.dp) { 57 | frameworkPaint.maskFilter = (BlurMaskFilter(blurRadius.toPx(), NORMAL)) 58 | } 59 | frameworkPaint.color = color.toArgb() 60 | 61 | canvas.drawCircle( 62 | center = Offset(x = center.x + offsetX.toPx(), y = center.y + offsetY.toPx()), 63 | radius = size.width / 2, 64 | paint = paint 65 | ) 66 | } 67 | } 68 | ) -------------------------------------------------------------------------------- /app/src/main/java/io/github/hanihashemi/alarmclock/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package io.github.hanihashemi.alarmclock.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val PrimaryColor = Color(0xFF435688) 6 | val SurfaceColor = Color(0xFFF7F9FC) 7 | val OnBackgroundColor = Color(0xFF364767) 8 | val SecondaryContainerColor = Color(0xFFD81F72) 9 | val OnSurfaceVariantColor = Color(0xFF364767) 10 | 11 | val AnalogClockOuterBoxShadow1 = Color.White.copy(alpha = 0.41f) 12 | val AnalogClockOuterBoxShadow2 = Color(0x48C7D6EA) 13 | val AnalogClockOuterBoxShadow3 = Color.White 14 | val AnalogClockOuterBoxShadow4 = Color(0xffC4D4E7) 15 | val AnalogClockOuterBoxColor = Color(0xffE7EEFB) 16 | 17 | val AnalogClockInnerBoxShadow = Color(0x59C4D4E7) 18 | val AnalogClockInnerBoxColor = Color(0xffEDF1FB) 19 | 20 | val AnalogClockHourHandColor = Color(0xFF0C0F1F) 21 | val AnalogClockMinuteHandColor = Color(0xff9FA7BC) 22 | val AnalogClockSecondHandColor = Color(0xFFD81F72) 23 | 24 | val NavigationBarShadowColor = Color(0xBFC4D4E7) 25 | val NavigationBarColor = Color(0xFFECF1FF) 26 | val AndroidNavigationBarColor = Color(0xFF17213A) 27 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/hanihashemi/alarmclock/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package io.github.hanihashemi.alarmclock.ui.theme 2 | 3 | import android.app.Activity 4 | import androidx.compose.material3.MaterialTheme 5 | import androidx.compose.material3.lightColorScheme 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.SideEffect 8 | import androidx.compose.ui.graphics.toArgb 9 | import androidx.compose.ui.platform.LocalView 10 | import androidx.core.view.ViewCompat 11 | 12 | private val LightColorScheme = lightColorScheme( 13 | primary = PrimaryColor, 14 | surface = SurfaceColor, 15 | onBackground = OnBackgroundColor, 16 | secondaryContainer = SecondaryContainerColor, 17 | onSurfaceVariant = OnSurfaceVariantColor, 18 | ) 19 | 20 | @Composable 21 | fun AlarmClockTheme( 22 | content: @Composable () -> Unit 23 | ) { 24 | val view = LocalView.current 25 | if (!view.isInEditMode) { 26 | SideEffect { 27 | (view.context as Activity).window.statusBarColor = LightColorScheme.primary.toArgb() 28 | (view.context as Activity).window.navigationBarColor = 29 | AndroidNavigationBarColor.toArgb() 30 | ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = false 31 | } 32 | } 33 | 34 | MaterialTheme( 35 | colorScheme = LightColorScheme, 36 | typography = Typography, 37 | content = content 38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/io/github/hanihashemi/alarmclock/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package io.github.hanihashemi.alarmclock.ui.theme 2 | 3 | import androidx.compose.material3.Typography 4 | import androidx.compose.ui.text.ExperimentalTextApi 5 | import androidx.compose.ui.text.TextStyle 6 | import androidx.compose.ui.text.font.FontFamily 7 | import androidx.compose.ui.text.font.FontWeight 8 | import androidx.compose.ui.text.googlefonts.Font 9 | import androidx.compose.ui.text.googlefonts.GoogleFont 10 | import androidx.compose.ui.unit.sp 11 | import io.github.hanihashemi.alarmclock.R 12 | 13 | @OptIn(ExperimentalTextApi::class) 14 | val provider = GoogleFont.Provider( 15 | providerAuthority = "com.google.android.gms.fonts", 16 | providerPackage = "com.google.android.gms", 17 | certificates = R.array.com_google_android_gms_fonts_certs 18 | ) 19 | 20 | @OptIn(ExperimentalTextApi::class) 21 | val fontName = GoogleFont("Inter") 22 | 23 | 24 | @OptIn(ExperimentalTextApi::class) 25 | val fontFamily = FontFamily( 26 | Font(googleFont = GoogleFont("Poppins"), fontProvider = provider), 27 | Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold) 28 | ) 29 | 30 | val Typography = Typography( 31 | titleLarge = TextStyle( 32 | fontFamily = fontFamily, 33 | fontWeight = FontWeight.Bold, 34 | fontSize = 35.sp, 35 | lineHeight = 28.sp, 36 | letterSpacing = 0.15.sp 37 | ), 38 | titleMedium = TextStyle( 39 | fontFamily = fontFamily, 40 | fontWeight = FontWeight.Bold, 41 | fontSize = 26.sp, 42 | lineHeight = 24.sp, 43 | letterSpacing = 0.15.sp 44 | ), 45 | bodyMedium = TextStyle( 46 | fontFamily = fontFamily, 47 | fontWeight = FontWeight.Normal, 48 | fontSize = 16.sp, 49 | lineHeight = 24.sp, 50 | letterSpacing = 0.5.sp 51 | ), 52 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_baseline_hourglass_bottom_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_access_time_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_alarm_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_hotel_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_outline_timer_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanihashemi/Alarm-Clock-App-Tutorial/20f3c1b561f63438cf389eb0814add081e2e93bb/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/font_certs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @array/com_google_android_gms_fonts_certs_dev 5 | @array/com_google_android_gms_fonts_certs_prod 6 | 7 | 8 | 9 | MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs= 10 | 11 | 12 | 13 | 14 | MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AlarmClock 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |