├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── daanidev │ │ └── compose │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── daanidev │ │ │ └── compose │ │ │ ├── AndroidIconWithStateAnimation.kt │ │ │ ├── AndroidIconWithoutStateAnimation.kt │ │ │ ├── bottomnav │ │ │ ├── BottomNavActivity.kt │ │ │ ├── BottomNavContentScreens.kt │ │ │ └── BottomNavItem.kt │ │ │ └── ui │ │ │ ├── exoplayer │ │ │ └── ExoPlayerActivity.kt │ │ │ ├── listview │ │ │ ├── ListViewSwipeToDeleteScreen.kt │ │ │ └── NotesItem.kt │ │ │ ├── theme │ │ │ ├── Color.kt │ │ │ ├── Shape.kt │ │ │ ├── Theme.kt │ │ │ └── Type.kt │ │ │ └── webview │ │ │ └── WebviewScreen.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_home.xml │ │ ├── ic_job.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_my_network.xml │ │ ├── ic_notification.xml │ │ └── ic_post.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-night │ │ └── themes.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ └── test │ └── java │ └── com │ └── daanidev │ └── compose │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ └── gradle-wrapper.properties ├── images └── bottom_navigation │ ├── Screenshot_1637497996.png │ ├── exoplayer_output.png │ └── swipetodimiss.png └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # jetpack compose custom views with animation 2 | 3 | This repository contains source code for designing custom view in jetpack compose with animations. 4 | You just need to clone this repository and run the application to see things in working. 5 | I will also add more custom views and animations in this repository. 6 | If you like it don't forget to give a star. 7 | 8 | 9 | # Webview Jetpack Compose 10 | [Webview_jetpack_Compose](https://github.com/DaaniDev/jetpack_compose_animations/tree/master/app/src/main/java/com/daanidev/compose/ui/webview) 11 | 12 | # SwipeToDelete Jetpack Compose LazyColumn 13 | [SwipeToDelete_jetpack_Compose_LazyColumn](https://github.com/DaaniDev/jetpack_compose_animations/tree/master/app/src/main/java/com/daanidev/compose/ui/listview) 14 | 15 | 16 | ![alt text](https://github.com/DaaniDev/jetpack_compose_animations/blob/master/images/bottom_navigation/swipetodimiss.png?raw=true) 17 | 18 | # Bottom Navigation in jetpack compose 19 | [Bottom Navigation Jetpack Compose](https://github.com/DaaniDev/jetpack_compose_animations/tree/master/app/src/main/java/com/daanidev/compose/bottomnav) 20 | 21 | ![alt text](https://github.com/DaaniDev/jetpack_compose_animations/blob/master/images/bottom_navigation/Screenshot_1637497996.png?raw=true) 22 | 23 | # Exoplayer Jetpack Compose 24 | [Exoplayer Jetpack Compose](https://github.com/DaaniDev/jetpack_compose_animations/tree/master/app/src/main/java/com/daanidev/compose/ui/exoplayer) 25 | 26 | ![alt text](https://github.com/DaaniDev/jetpack_compose_animations/blob/master/images/bottom_navigation/exoplayer_output.png?raw=true) 27 | 28 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdk 31 8 | 9 | defaultConfig { 10 | applicationId "com.daanidev.compose" 11 | minSdk 21 12 | targetSdk 31 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | vectorDrawables { 18 | useSupportLibrary true 19 | } 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | kotlinOptions { 33 | jvmTarget = '1.8' 34 | useIR = true 35 | } 36 | buildFeatures { 37 | compose true 38 | } 39 | composeOptions { 40 | kotlinCompilerExtensionVersion compose_version 41 | kotlinCompilerVersion '1.5.31' 42 | } 43 | packagingOptions { 44 | resources { 45 | excludes += '/META-INF/{AL2.0,LGPL2.1}' 46 | } 47 | } 48 | } 49 | 50 | dependencies { 51 | 52 | implementation 'androidx.core:core-ktx:1.6.0' 53 | implementation 'androidx.appcompat:appcompat:1.3.1' 54 | implementation 'com.google.android.material:material:1.4.0' 55 | implementation "androidx.compose.ui:ui:$compose_version" 56 | implementation "androidx.compose.material:material:$compose_version" 57 | implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" 58 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' 59 | implementation 'androidx.activity:activity-compose:1.4.0' 60 | implementation "androidx.navigation:navigation-compose:2.4.0-beta02" 61 | testImplementation 'junit:junit:4.+' 62 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 63 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 64 | androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" 65 | debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" 66 | 67 | //Exoplayer 68 | implementation "com.google.android.exoplayer:exoplayer:2.17.1" 69 | 70 | //Accompanist 71 | implementation 'com.google.accompanist:accompanist-insets:0.22.0-rc' 72 | implementation 'com.google.accompanist:accompanist-pager:0.22.0-rc' 73 | implementation "androidx.glance:glance-appwidget:1.0.0-SNAPSHOT" 74 | } -------------------------------------------------------------------------------- /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/androidTest/java/com/daanidev/compose/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.daanidev.compose", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/AndroidIconWithStateAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose 2 | 3 | import android.os.Bundle 4 | import androidx.activity.compose.setContent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.compose.animation.AnimatedVisibility 7 | import androidx.compose.animation.ExperimentalAnimationApi 8 | import androidx.compose.animation.core.* 9 | import androidx.compose.foundation.Canvas 10 | import androidx.compose.foundation.layout.fillMaxSize 11 | import androidx.compose.material.Button 12 | import androidx.compose.material.Text 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.runtime.LaunchedEffect 15 | import androidx.compose.runtime.mutableStateOf 16 | import androidx.compose.runtime.remember 17 | import androidx.compose.ui.Modifier 18 | import androidx.compose.ui.geometry.CornerRadius 19 | import androidx.compose.ui.geometry.Offset 20 | import androidx.compose.ui.geometry.Size 21 | import androidx.compose.ui.graphics.Color 22 | import androidx.compose.ui.graphics.StrokeCap 23 | import androidx.compose.ui.tooling.preview.Preview 24 | import com.daanidev.compose.ui.theme.ComposeTheme 25 | 26 | class AnimatedCanvas : AppCompatActivity() { 27 | 28 | @ExperimentalAnimationApi 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | super.onCreate(savedInstanceState) 31 | 32 | setContent { 33 | ComposeTheme { 34 | 35 | drawAnimatedCanvas() 36 | } 37 | } 38 | } 39 | 40 | } 41 | 42 | @ExperimentalAnimationApi 43 | @Composable 44 | fun drawAnimatedCanvas() { 45 | 46 | // state check variables 47 | val headState = remember { 48 | mutableStateOf(false) 49 | } 50 | val leftEarState = remember { 51 | mutableStateOf(false) 52 | } 53 | val rightEarState = remember { 54 | mutableStateOf(false) 55 | } 56 | 57 | val rightEyeState = remember { 58 | mutableStateOf(false) 59 | } 60 | 61 | val leftEyeState = remember { 62 | mutableStateOf(false) 63 | } 64 | 65 | val centerRectState = remember { 66 | mutableStateOf(false) 67 | } 68 | 69 | val leftLegState = remember { 70 | mutableStateOf(false) 71 | } 72 | 73 | val rightLegState = remember { 74 | mutableStateOf(false) 75 | } 76 | 77 | val leftArmState = remember { 78 | mutableStateOf(false) 79 | } 80 | 81 | val rightArmState = remember { 82 | mutableStateOf(false) 83 | } 84 | // animations 85 | val headAnim = animateFloatAsState( 86 | targetValue = if (headState.value) .50f else 0f, 87 | finishedListener = { 88 | 89 | leftEarState.value = true 90 | }, 91 | animationSpec = tween(1000, easing = LinearEasing) 92 | ) 93 | 94 | val leftEarAnim = animateFloatAsState( 95 | targetValue = if (leftEarState.value) 0.28f else 0.33f, 96 | finishedListener = { 97 | rightEarState.value = true 98 | }, 99 | animationSpec = tween(1000, easing = LinearEasing) 100 | ) 101 | 102 | val rightEarAnim = animateFloatAsState( 103 | targetValue = if (rightEarState.value) 0.28f else 0.32f, 104 | finishedListener = { 105 | leftEyeState.value = true 106 | }, 107 | animationSpec = tween(1000, easing = LinearEasing) 108 | ) 109 | 110 | val leftEyeAnim = animateFloatAsState( 111 | targetValue = if (leftEyeState.value) 20f else 0f, 112 | finishedListener = { 113 | rightEyeState.value = true 114 | }, 115 | animationSpec = tween(1000, easing = LinearEasing) 116 | ) 117 | 118 | val rightEyeAnim = animateFloatAsState( 119 | targetValue = if (rightEyeState.value) 20f else 0f, 120 | finishedListener = { 121 | centerRectState.value = true 122 | }, 123 | animationSpec = tween(1000, easing = LinearEasing) 124 | ) 125 | 126 | val centerRectAnim = animateFloatAsState( 127 | targetValue = if (centerRectState.value) 0.16f else 0f, 128 | finishedListener = { 129 | 130 | leftLegState.value = true 131 | }, 132 | animationSpec = tween(1000, easing = LinearEasing) 133 | ) 134 | 135 | val leftLegAnim = animateFloatAsState( 136 | targetValue = if (leftLegState.value) 0.65f else 0.5f, 137 | finishedListener = { 138 | 139 | rightLegState.value = true 140 | }, 141 | animationSpec = tween(1000, easing = LinearEasing) 142 | ) 143 | 144 | val rightLegAnim = animateFloatAsState( 145 | targetValue = if (rightLegState.value) 0.65f else 0.5f, 146 | finishedListener = { 147 | 148 | leftArmState.value = true 149 | }, 150 | animationSpec = tween(1000, easing = LinearEasing) 151 | ) 152 | 153 | val leftArmAnim = animateFloatAsState( 154 | targetValue = if (leftArmState.value) 0.55f else 0.45f, 155 | finishedListener = { 156 | 157 | rightArmState.value = true 158 | }, 159 | animationSpec = tween(1000, easing = LinearEasing) 160 | ) 161 | 162 | val rightArmAnim = animateFloatAsState( 163 | targetValue = if (rightArmState.value) 0.55f else 0.45f, 164 | finishedListener = { 165 | 166 | }, 167 | animationSpec = tween(1000, easing = LinearEasing) 168 | ) 169 | 170 | // canvas 171 | Canvas(modifier = Modifier.fillMaxSize()) { 172 | 173 | val canvasWidth = size.width 174 | val canvasHeight = size.height 175 | val sizeArc = size / 2.25F 176 | 177 | drawArc( 178 | color = Color(0xFF58bd46), 179 | startAngle = 0f, 180 | sweepAngle = -180f, 181 | useCenter = false, 182 | size = Size(size.width * headAnim.value, size.height * 0.25f), 183 | topLeft = Offset( 184 | (size.width - sizeArc.width) / 2f, 185 | (size.height - sizeArc.height) / 2f 186 | ), 187 | ) 188 | 189 | 190 | if (leftEarState.value) { 191 | drawLine( 192 | color = Color(0xFF58bd46), 193 | start = Offset(canvasWidth.times(.38f), canvasHeight.times(0.33f)), 194 | strokeWidth = 20f, 195 | cap = StrokeCap.Round, 196 | end = Offset(canvasWidth.times(.31f), canvasHeight.times(leftEarAnim.value)) 197 | ) 198 | } 199 | 200 | if (rightEarState.value) { 201 | drawLine( 202 | color = Color(0xFF58bd46), 203 | start = Offset(canvasWidth.times(.68f), canvasHeight.times(0.32f)), 204 | strokeWidth = 15f, 205 | cap = StrokeCap.Round, 206 | end = Offset(canvasWidth.times(.75f), canvasHeight.times(rightEarAnim.value)) 207 | ) 208 | } 209 | 210 | if (leftEarState.value) { 211 | drawCircle( 212 | color = Color.White, 213 | center = Offset(x = (canvasWidth / 2) * 0.88f, y = (size.height) / 3f), 214 | radius = leftEyeAnim.value 215 | ) 216 | } 217 | 218 | if (rightEyeState.value) { 219 | drawCircle( 220 | color = Color.White, 221 | center = Offset(x = (canvasWidth / 2) * 1.22f, y = (size.height) / 3f), 222 | radius = rightEyeAnim.value 223 | ) 224 | } 225 | 226 | if (centerRectState.value) { 227 | drawRoundRect( 228 | color = Color(0xFF58bd46), 229 | topLeft = Offset(x = canvasWidth / 3.3F, y = canvasHeight / 2.3F), 230 | size = Size(canvasWidth / 2.25f, canvasHeight.times(centerRectAnim.value)), 231 | cornerRadius = CornerRadius(x = 10f, y = 10f) 232 | ) 233 | } 234 | 235 | if (leftLegState.value) { 236 | drawLine( 237 | color = Color(0xFF58bd46), 238 | start = Offset(canvasWidth.times(0.4f), canvasHeight.times(.5f)), 239 | strokeWidth = 70f, 240 | cap = StrokeCap.Round, 241 | end = Offset(canvasWidth.times(0.4f), canvasHeight.times(leftLegAnim.value)) 242 | ) 243 | } 244 | 245 | if (rightLegState.value) { 246 | drawLine( 247 | color = Color(0xFF58bd46), 248 | start = Offset(canvasWidth.times(0.65f), canvasHeight.times(0.5f)), 249 | strokeWidth = 70f, 250 | cap = StrokeCap.Round, 251 | end = Offset(canvasWidth.times(0.65f), canvasHeight.times(rightLegAnim.value)) 252 | ) 253 | } 254 | 255 | if (leftArmState.value) { 256 | drawLine( 257 | color = Color(0xFF58bd46), 258 | start = Offset( 259 | (size.width - sizeArc.width) / 2.25f, 260 | canvasHeight.times(leftArmAnim.value) 261 | ), 262 | strokeWidth = 70f, 263 | cap = StrokeCap.Round, 264 | end = Offset((size.width - sizeArc.width) / 2.25f, canvasHeight.times(0.45f)) 265 | ) 266 | } 267 | 268 | if (rightArmState.value) { 269 | drawLine( 270 | color = Color(0xFF58bd46), 271 | start = Offset(size.width.times(0.8f), canvasHeight.times(rightArmAnim.value)), 272 | strokeWidth = 70f, 273 | cap = StrokeCap.Round, 274 | end = Offset(size.width.times(0.8f), canvasHeight.times(.45f)) 275 | ) 276 | } 277 | 278 | 279 | } 280 | Button(onClick = { headState.value = true }) { 281 | 282 | Text(text = "Play Animation") 283 | 284 | } 285 | 286 | 287 | } 288 | 289 | @ExperimentalAnimationApi 290 | @Preview(showBackground = true) 291 | @Composable 292 | fun animatedPreview() { 293 | ComposeTheme { 294 | drawAnimatedCanvas() 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/AndroidIconWithoutStateAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.widget.Toast 6 | import androidx.activity.compose.setContent 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.compose.animation.AnimatedVisibility 9 | import androidx.compose.animation.ExperimentalAnimationApi 10 | import androidx.compose.animation.core.* 11 | import androidx.compose.animation.fadeIn 12 | import androidx.compose.foundation.Canvas 13 | import androidx.compose.foundation.background 14 | import androidx.compose.foundation.layout.Box 15 | import androidx.compose.foundation.layout.fillMaxSize 16 | import androidx.compose.foundation.layout.size 17 | import androidx.compose.foundation.shape.RoundedCornerShape 18 | import androidx.compose.material.Surface 19 | import androidx.compose.runtime.* 20 | import androidx.compose.ui.Modifier 21 | import androidx.compose.ui.draw.clip 22 | import androidx.compose.ui.geometry.CornerRadius 23 | import androidx.compose.ui.geometry.Offset 24 | import androidx.compose.ui.geometry.Size 25 | import androidx.compose.ui.graphics.* 26 | import androidx.compose.ui.graphics.drawscope.DrawStyle 27 | import androidx.compose.ui.graphics.drawscope.Stroke 28 | import androidx.compose.ui.graphics.drawscope.clipRect 29 | import androidx.compose.ui.graphics.drawscope.rotate 30 | import androidx.compose.ui.platform.ClipboardManager 31 | import androidx.compose.ui.tooling.preview.Preview 32 | import androidx.compose.ui.unit.dp 33 | import com.daanidev.compose.ui.theme.ComposeTheme 34 | 35 | class CanvasActivity : AppCompatActivity() { 36 | 37 | override fun onCreate(savedInstanceState: Bundle?) { 38 | super.onCreate(savedInstanceState) 39 | 40 | setContent { 41 | ComposeTheme { 42 | 43 | drawCanvas() 44 | } 45 | } 46 | } 47 | 48 | } 49 | 50 | 51 | @Composable 52 | fun drawCanvas() { 53 | 54 | 55 | val rightLegAnim = remember { Animatable(0.5f) } 56 | 57 | LaunchedEffect(rightLegAnim) { 58 | rightLegAnim.animateTo( 59 | targetValue = 0.65f, 60 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 61 | ) 62 | } 63 | 64 | val leftLegAnim = remember { Animatable(0.5f) } 65 | 66 | LaunchedEffect(leftLegAnim) { 67 | leftLegAnim.animateTo( 68 | targetValue = 0.65f, 69 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 70 | ) 71 | 72 | } 73 | 74 | 75 | val leftArmAnim = remember { Animatable(0.45f) } 76 | 77 | LaunchedEffect(leftArmAnim) { 78 | leftArmAnim.animateTo( 79 | targetValue = 0.55f, 80 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 81 | ) 82 | 83 | } 84 | 85 | val rightArmAnim = remember { Animatable(0.45f) } 86 | 87 | LaunchedEffect(rightArmAnim) { 88 | rightArmAnim.animateTo( 89 | targetValue = 0.55f, 90 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 91 | ) 92 | 93 | } 94 | 95 | val rectangleAnim = remember { Animatable(0f) } 96 | 97 | LaunchedEffect(rectangleAnim) { 98 | rectangleAnim.animateTo( 99 | targetValue = 0.16f, 100 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 101 | ) 102 | 103 | } 104 | 105 | val headAnim = remember { Animatable(0f) } 106 | 107 | LaunchedEffect(headAnim) { 108 | headAnim.animateTo( 109 | targetValue = .25f, 110 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 111 | ) 112 | 113 | } 114 | 115 | val headLeftLineAnim = remember { Animatable(0.28f) } 116 | 117 | LaunchedEffect(headLeftLineAnim) { 118 | headLeftLineAnim.animateTo( 119 | targetValue = .33f, 120 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 121 | ) 122 | 123 | } 124 | 125 | val headRightLineAnim = remember { Animatable(0.28f) } 126 | 127 | LaunchedEffect(headRightLineAnim) { 128 | headRightLineAnim.animateTo( 129 | targetValue = .32f, 130 | animationSpec = tween(durationMillis = 1000, easing = LinearEasing) 131 | ) 132 | 133 | } 134 | 135 | val leftEyeAnim = remember { Animatable(0f) } 136 | 137 | LaunchedEffect(leftEyeAnim) { 138 | leftEyeAnim.animateTo( 139 | targetValue = 20f, 140 | animationSpec = tween(durationMillis = 2000, easing = LinearEasing) 141 | ) 142 | // fadeIn(initialAlpha = 0.3f) 143 | 144 | } 145 | /* AnimatedVisibility( 146 | visible = true, 147 | enter = fadeIn( 148 | // Overwrites the initial value of alpha to 0.4f for fade in, 0 by default 149 | initialAlpha = 0.4f 150 | ) 151 | ) { 152 | // Content that needs to appear/disappear goes here: 153 | }*/ 154 | 155 | 156 | Canvas(modifier = Modifier.fillMaxSize()){ 157 | 158 | val canvasWidth = size.width 159 | val canvasHeight = size.height 160 | val sizeArc = size/2.25F 161 | 162 | 163 | drawArc( 164 | color = Color(0xFF58bd46), 165 | startAngle = 0f, 166 | sweepAngle = -180f, 167 | useCenter = false, 168 | size = Size(size.width * .50f, size.height * headAnim.value), 169 | topLeft = Offset((size.width - sizeArc.width)/2f,(size.height - sizeArc.height)/2f), 170 | 171 | ) 172 | 173 | drawCircle( 174 | color = Color.White, 175 | center = Offset(x = (canvasWidth / 2) * 0.88f , y = (size.height)/3f), 176 | radius = leftEyeAnim.value 177 | ) 178 | drawCircle( 179 | color = Color.White, 180 | center = Offset(x = (canvasWidth / 2) * 1.22f, y = (size.height)/3f), 181 | radius = leftEyeAnim.value 182 | ) 183 | 184 | drawLine( 185 | color = Color(0xFF58bd46), 186 | start = Offset(canvasWidth.times(.38f), canvasHeight.times(headLeftLineAnim.value)), 187 | strokeWidth = 15f, 188 | cap = StrokeCap.Round, 189 | end = Offset(canvasWidth.times(.31f), canvasHeight.times(0.28f)) 190 | ) 191 | drawLine( 192 | color = Color(0xFF58bd46), 193 | start = Offset(canvasWidth.times(.68f), canvasHeight.times(headRightLineAnim.value)), 194 | strokeWidth = 15f, 195 | cap = StrokeCap.Round, 196 | end = Offset(canvasWidth.times(.75f), canvasHeight.times(.28f)) 197 | ) 198 | 199 | drawLine( 200 | color = Color(0xFF58bd46), 201 | start = Offset((size.width - sizeArc.width)/2.25f, canvasHeight.times(leftArmAnim.value)), 202 | strokeWidth = 70f, 203 | cap = StrokeCap.Round, 204 | end = Offset((size.width - sizeArc.width)/2.25f, canvasHeight.times(0.45f)) 205 | ) 206 | 207 | drawLine( 208 | color = Color(0xFF58bd46), 209 | start = Offset(size.width.times(0.8f), canvasHeight.times(rightArmAnim.value)), 210 | strokeWidth = 70f, 211 | cap = StrokeCap.Round, 212 | end = Offset(size.width.times(0.8f), canvasHeight.times(.45f)) 213 | ) 214 | /* drawLine( 215 | color = Color(0xFF58bd46), 216 | start = Offset(canvasHeight.times(0.37f), canvasHeight.times(.55f)), 217 | strokeWidth = 70f, 218 | cap = StrokeCap.Round, 219 | end = Offset(canvasHeight.times(0.37f), canvasHeight.times(.45f)) 220 | )*/ 221 | 222 | drawRoundRect( 223 | color = Color(0xFF58bd46), 224 | topLeft = Offset(x = canvasWidth / 3.3F, y = canvasHeight / 2.3F), 225 | size = Size(canvasWidth/2.25f,canvasHeight.times(rectangleAnim.value)), 226 | cornerRadius = CornerRadius(x=10f,y=10f) 227 | ) 228 | 229 | drawLine( 230 | color = Color(0xFF58bd46), 231 | start = Offset(canvasWidth.times(0.4f), canvasHeight.times(.5f)), 232 | strokeWidth = 70f, 233 | cap = StrokeCap.Round, 234 | end = Offset(canvasWidth.times(0.4f), canvasHeight.times(leftLegAnim.value)) 235 | ) 236 | 237 | drawLine( 238 | color = Color(0xFF58bd46), 239 | start = Offset(canvasWidth.times(0.65f), canvasHeight.times(0.5f)), 240 | strokeWidth = 70f, 241 | cap = StrokeCap.Round, 242 | end = Offset(canvasWidth.times(0.65f), canvasHeight.times(rightLegAnim.value)) 243 | ) 244 | 245 | 246 | } 247 | 248 | 249 | 250 | 251 | } 252 | @Preview(showBackground = true) 253 | @Composable 254 | fun preview() { 255 | ComposeTheme { 256 | drawCanvas() 257 | } 258 | } 259 | 260 | -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/bottomnav/BottomNavActivity.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.bottomnav 2 | 3 | import android.os.Bundle 4 | import androidx.activity.compose.setContent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.compose.material.* 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.runtime.getValue 9 | import androidx.compose.ui.graphics.Color 10 | import androidx.compose.ui.res.colorResource 11 | import androidx.compose.ui.res.painterResource 12 | import androidx.compose.ui.tooling.preview.Preview 13 | import androidx.compose.ui.unit.sp 14 | import androidx.navigation.NavController 15 | import androidx.navigation.NavHostController 16 | import androidx.navigation.compose.NavHost 17 | import androidx.navigation.compose.composable 18 | import androidx.navigation.compose.currentBackStackEntryAsState 19 | import androidx.navigation.compose.rememberNavController 20 | import com.daanidev.compose.R 21 | 22 | class BottomNavActivity : AppCompatActivity() { 23 | 24 | override fun onCreate(savedInstanceState: Bundle?) { 25 | super.onCreate(savedInstanceState) 26 | setContent { 27 | MainScreenView() 28 | } 29 | } 30 | } 31 | 32 | 33 | @Composable 34 | fun MainScreenView(){ 35 | val navController = rememberNavController() 36 | Scaffold( 37 | bottomBar = { BottomNavigation(navController = navController) } 38 | ) { 39 | 40 | NavigationGraph(navController = navController) 41 | } 42 | } 43 | @Composable 44 | fun BottomNavigation(navController: NavController) { 45 | val items = listOf( 46 | BottomNavItem.Home, 47 | BottomNavItem.MyNetwork, 48 | BottomNavItem.AddPost, 49 | BottomNavItem.Notification, 50 | BottomNavItem.Jobs 51 | ) 52 | BottomNavigation( 53 | backgroundColor = colorResource(id = R.color.teal_200), 54 | contentColor = Color.Black 55 | ) { 56 | val navBackStackEntry by navController.currentBackStackEntryAsState() 57 | val currentRoute = navBackStackEntry?.destination?.route 58 | items.forEach { item -> 59 | BottomNavigationItem( 60 | icon = { Icon(painterResource(id = item.icon), contentDescription = item.title) }, 61 | label = { Text(text = item.title, 62 | fontSize = 9.sp) }, 63 | selectedContentColor = Color.Black, 64 | unselectedContentColor = Color.Black.copy(0.4f), 65 | alwaysShowLabel = true, 66 | selected = currentRoute == item.screen_route, 67 | onClick = { 68 | navController.navigate(item.screen_route) { 69 | 70 | navController.graph.startDestinationRoute?.let { screen_route -> 71 | popUpTo(screen_route) { 72 | saveState = true 73 | } 74 | } 75 | launchSingleTop = true 76 | restoreState = true 77 | } 78 | } 79 | ) 80 | } 81 | } 82 | } 83 | 84 | @Composable 85 | fun NavigationGraph(navController: NavHostController) { 86 | NavHost(navController, startDestination = BottomNavItem.Home.screen_route) { 87 | composable(BottomNavItem.Home.screen_route) { 88 | HomeScreen() 89 | } 90 | composable(BottomNavItem.MyNetwork.screen_route) { 91 | NetworkScreen() 92 | } 93 | composable(BottomNavItem.AddPost.screen_route) { 94 | AddPostScreen() 95 | } 96 | composable(BottomNavItem.Notification.screen_route) { 97 | NotificationScreen() 98 | } 99 | composable(BottomNavItem.Jobs.screen_route) { 100 | JobScreen() 101 | } 102 | } 103 | } 104 | 105 | @Preview(showBackground = true) 106 | @Composable 107 | fun BottomNavigationPreview() { 108 | MainScreenView() 109 | } -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/bottomnav/BottomNavContentScreens.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.bottomnav 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.foundation.layout.wrapContentSize 7 | import androidx.compose.material.Text 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Alignment 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.graphics.Color 12 | import androidx.compose.ui.res.colorResource 13 | import androidx.compose.ui.text.font.FontWeight 14 | import androidx.compose.ui.text.style.TextAlign 15 | import androidx.compose.ui.tooling.preview.Preview 16 | import androidx.compose.ui.unit.sp 17 | import com.daanidev.compose.R 18 | 19 | @Composable 20 | fun HomeScreen() { 21 | Column( 22 | modifier = Modifier 23 | .fillMaxSize() 24 | .background(colorResource(id = R.color.teal_700)) 25 | .wrapContentSize(Alignment.Center) 26 | ) { 27 | Text( 28 | text = "Home Screen", 29 | fontWeight = FontWeight.Bold, 30 | color = Color.White, 31 | modifier = Modifier.align(Alignment.CenterHorizontally), 32 | textAlign = TextAlign.Center, 33 | fontSize = 20.sp 34 | ) 35 | } 36 | } 37 | 38 | @Composable 39 | fun NetworkScreen() { 40 | Column( 41 | modifier = Modifier 42 | .fillMaxSize() 43 | .background(colorResource(id = R.color.teal_700)) 44 | .wrapContentSize(Alignment.Center) 45 | ) { 46 | Text( 47 | text = "My Network Screen", 48 | fontWeight = FontWeight.Bold, 49 | color = Color.White, 50 | modifier = Modifier.align(Alignment.CenterHorizontally), 51 | textAlign = TextAlign.Center, 52 | fontSize = 20.sp 53 | ) 54 | } 55 | } 56 | 57 | @Composable 58 | fun AddPostScreen() { 59 | Column( 60 | modifier = Modifier 61 | .fillMaxSize() 62 | .background(colorResource(id = R.color.teal_700)) 63 | .wrapContentSize(Alignment.Center) 64 | ) { 65 | Text( 66 | text = "Add Post Screen", 67 | fontWeight = FontWeight.Bold, 68 | color = Color.White, 69 | modifier = Modifier.align(Alignment.CenterHorizontally), 70 | textAlign = TextAlign.Center, 71 | fontSize = 20.sp 72 | ) 73 | } 74 | } 75 | 76 | 77 | @Composable 78 | fun NotificationScreen() { 79 | Column( 80 | modifier = Modifier 81 | .fillMaxSize() 82 | .background(colorResource(id = R.color.teal_700)) 83 | .wrapContentSize(Alignment.Center) 84 | ) { 85 | Text( 86 | text = "Notification Screen", 87 | fontWeight = FontWeight.Bold, 88 | color = Color.White, 89 | modifier = Modifier.align(Alignment.CenterHorizontally), 90 | textAlign = TextAlign.Center, 91 | fontSize = 20.sp 92 | ) 93 | } 94 | } 95 | 96 | 97 | @Composable 98 | fun JobScreen() { 99 | Column( 100 | modifier = Modifier 101 | .fillMaxSize() 102 | .background(colorResource(id = R.color.teal_700)) 103 | .wrapContentSize(Alignment.Center) 104 | ) { 105 | Text( 106 | text = "Jobs Screen", 107 | fontWeight = FontWeight.Bold, 108 | color = Color.White, 109 | modifier = Modifier.align(Alignment.CenterHorizontally), 110 | textAlign = TextAlign.Center, 111 | fontSize = 20.sp 112 | ) 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/bottomnav/BottomNavItem.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.bottomnav 2 | 3 | import com.daanidev.compose.R 4 | 5 | sealed class BottomNavItem(var title:String, var icon:Int, var screen_route:String){ 6 | 7 | object Home : BottomNavItem("Home", R.drawable.ic_home,"home") 8 | object MyNetwork: BottomNavItem("My Network",R.drawable.ic_my_network,"my_network") 9 | object AddPost: BottomNavItem("Post",R.drawable.ic_post,"add_post") 10 | object Notification: BottomNavItem("Notification",R.drawable.ic_notification,"notification") 11 | object Jobs: BottomNavItem("Jobs",R.drawable.ic_job,"jobs") 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/exoplayer/ExoPlayerActivity.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.exoplayer 2 | 3 | import android.net.Uri 4 | import android.os.Bundle 5 | import androidx.activity.compose.setContent 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.compose.foundation.layout.Arrangement 8 | import androidx.compose.foundation.layout.Column 9 | import androidx.compose.foundation.layout.fillMaxSize 10 | import androidx.compose.material.Scaffold 11 | import androidx.compose.material.Text 12 | import androidx.compose.material.TopAppBar 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.runtime.remember 15 | import androidx.compose.ui.Alignment 16 | import androidx.compose.ui.Modifier 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.platform.LocalContext 19 | import androidx.compose.ui.viewinterop.AndroidView 20 | import com.daanidev.compose.R 21 | import com.google.android.exoplayer2.ExoPlayer 22 | import com.google.android.exoplayer2.MediaItem 23 | import com.google.android.exoplayer2.Player 24 | import com.google.android.exoplayer2.source.DefaultMediaSourceFactory 25 | import com.google.android.exoplayer2.source.MediaSource 26 | import com.google.android.exoplayer2.source.ProgressiveMediaSource 27 | import com.google.android.exoplayer2.ui.PlayerView 28 | import com.google.android.exoplayer2.ui.StyledPlayerView 29 | import com.google.android.exoplayer2.util.MimeTypes 30 | import com.google.android.exoplayer2.util.Util 31 | 32 | 33 | class ExoPlayerActivity : AppCompatActivity() { 34 | 35 | val videoURL = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" 36 | 37 | override fun onCreate(savedInstanceState: Bundle?) { 38 | super.onCreate(savedInstanceState) 39 | 40 | setContent { uiContainer() } 41 | 42 | } 43 | 44 | 45 | @Composable 46 | private fun uiContainer() { 47 | Scaffold( 48 | topBar = { 49 | TopAppBar( 50 | title = { Text("ExoPlayer View", color = Color.White) }, 51 | backgroundColor = Color(0xff0f9d58) 52 | ) 53 | }, 54 | content = { exoPlayerUI() } 55 | ) 56 | } 57 | 58 | @Composable 59 | private fun exoPlayerUI() { 60 | 61 | Column( 62 | Modifier.fillMaxSize(), 63 | horizontalAlignment = Alignment.CenterHorizontally, 64 | verticalArrangement = Arrangement.Center 65 | ) { 66 | 67 | val mContext = LocalContext.current 68 | 69 | // Initializing ExoPLayer 70 | val mExoPlayer = remember(mContext) { 71 | ExoPlayer.Builder(mContext).build().apply { 72 | 73 | val mediaItem = MediaItem.Builder() 74 | .setUri(Uri.parse(videoURL)) 75 | .build() 76 | setMediaItem(mediaItem) 77 | 78 | playWhenReady = true 79 | prepare() 80 | } 81 | } 82 | 83 | 84 | // Implementing ExoPlayer 85 | AndroidView(factory = { context -> 86 | StyledPlayerView(context).apply { 87 | player = mExoPlayer 88 | 89 | } 90 | }) 91 | } 92 | } 93 | 94 | 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/listview/ListViewSwipeToDeleteScreen.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.listview 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.widget.RatingBar 6 | import android.widget.Toast 7 | import androidx.activity.compose.setContent 8 | import androidx.appcompat.app.AppCompatActivity 9 | import androidx.compose.animation.animateColorAsState 10 | import androidx.compose.animation.core.animateDpAsState 11 | import androidx.compose.animation.core.animateFloatAsState 12 | import androidx.compose.foundation.background 13 | import androidx.compose.foundation.gestures.Orientation 14 | import androidx.compose.foundation.gestures.draggable 15 | import androidx.compose.foundation.layout.* 16 | import androidx.compose.foundation.lazy.LazyColumn 17 | import androidx.compose.foundation.lazy.items 18 | import androidx.compose.foundation.lazy.itemsIndexed 19 | import androidx.compose.foundation.text.ClickableText 20 | import androidx.compose.foundation.text.KeyboardOptions 21 | import androidx.compose.material.* 22 | import androidx.compose.material.icons.Icons 23 | import androidx.compose.material.icons.filled.Delete 24 | import androidx.compose.material.icons.filled.Done 25 | import androidx.compose.runtime.* 26 | import androidx.compose.ui.Alignment 27 | import androidx.compose.ui.Modifier 28 | import androidx.compose.ui.draw.scale 29 | import androidx.compose.ui.graphics.Color 30 | import androidx.compose.ui.platform.LocalDensity 31 | import androidx.compose.ui.text.SpanStyle 32 | import androidx.compose.ui.text.TextStyle 33 | import androidx.compose.ui.text.buildAnnotatedString 34 | import androidx.compose.ui.text.font.FontFamily 35 | import androidx.compose.ui.text.font.FontWeight 36 | import androidx.compose.ui.text.input.ImeAction 37 | import androidx.compose.ui.text.input.KeyboardCapitalization 38 | import androidx.compose.ui.text.input.KeyboardType 39 | import androidx.compose.ui.text.input.TextFieldValue 40 | import androidx.compose.ui.text.withStyle 41 | import androidx.compose.ui.unit.* 42 | import kotlin.math.roundToInt 43 | 44 | class ListViewSwipeToDeleteScreen : AppCompatActivity() { 45 | 46 | var id=0 47 | @ExperimentalUnitApi 48 | @ExperimentalMaterialApi 49 | override fun onCreate(savedInstanceState: Bundle?) { 50 | super.onCreate(savedInstanceState) 51 | 52 | setContent { 53 | setupList() 54 | } 55 | } 56 | 57 | 58 | @ExperimentalUnitApi 59 | @ExperimentalMaterialApi 60 | @Composable 61 | fun setupList() { 62 | 63 | val notesList = remember { 64 | mutableStateListOf() 65 | } 66 | 67 | 68 | 69 | val inputvalue = remember { mutableStateOf(TextFieldValue()) } 70 | 71 | 72 | Column { 73 | 74 | Row( 75 | Modifier 76 | .fillMaxWidth() 77 | .height(Dp(60f)) 78 | ) { 79 | 80 | TextField( 81 | value = inputvalue.value, 82 | onValueChange = { 83 | inputvalue.value = it 84 | }, 85 | modifier = Modifier.weight(0.8f), 86 | placeholder = { Text(text = "Enter your note") }, 87 | keyboardOptions = KeyboardOptions( 88 | capitalization = KeyboardCapitalization.None, 89 | autoCorrect = true, 90 | keyboardType = KeyboardType.Text, 91 | imeAction = ImeAction.Done 92 | ), 93 | textStyle = TextStyle( 94 | color = Color.Black, fontSize = TextUnit.Unspecified, 95 | fontFamily = FontFamily.SansSerif 96 | ), 97 | maxLines = 1, 98 | singleLine = true 99 | ) 100 | 101 | 102 | Button( 103 | onClick = { 104 | notesList.add(NotesItem(id++,inputvalue.value.text)) 105 | 106 | }, 107 | modifier = Modifier 108 | .weight(0.2f) 109 | .fillMaxHeight() 110 | ) { 111 | Text(text = "ADD") 112 | } 113 | } 114 | Spacer(modifier = Modifier.height(Dp(1f))) 115 | 116 | 117 | LazyColumn { 118 | 119 | items(notesList,{notesList:NotesItem->notesList.id}){item-> 120 | val dismissState = rememberDismissState() 121 | 122 | if (dismissState.isDismissed(DismissDirection.EndToStart)) { 123 | 124 | notesList.remove(item) 125 | } 126 | SwipeToDismiss( 127 | state = dismissState, 128 | modifier = Modifier 129 | .padding(vertical = Dp(1f)), 130 | directions = setOf( 131 | DismissDirection.EndToStart 132 | ), 133 | dismissThresholds = { direction -> 134 | FractionalThreshold(if (direction == DismissDirection.EndToStart) 0.1f else 0.05f) 135 | }, 136 | background = { 137 | val color by animateColorAsState( 138 | when (dismissState.targetValue) { 139 | DismissValue.Default -> Color.White 140 | else -> Color.Red 141 | } 142 | ) 143 | val alignment = Alignment.CenterEnd 144 | val icon = Icons.Default.Delete 145 | 146 | val scale by animateFloatAsState( 147 | if (dismissState.targetValue == DismissValue.Default) 0.75f else 1f 148 | ) 149 | 150 | Box( 151 | Modifier 152 | .fillMaxSize() 153 | .background(color) 154 | .padding(horizontal = Dp(20f)), 155 | contentAlignment = alignment 156 | ) { 157 | Icon( 158 | icon, 159 | contentDescription = "Delete Icon", 160 | modifier = Modifier.scale(scale) 161 | ) 162 | } 163 | }, 164 | dismissContent = { 165 | 166 | Card( 167 | elevation = animateDpAsState( 168 | if (dismissState.dismissDirection != null) 4.dp else 0.dp 169 | ).value, 170 | modifier = Modifier 171 | .fillMaxWidth() 172 | .height(Dp(50f)) 173 | .align(alignment = Alignment.CenterVertically) 174 | ) { 175 | setUpRow(item = item) 176 | } 177 | } 178 | ) 179 | 180 | Divider(Modifier.fillMaxWidth(), Color.DarkGray) 181 | } 182 | } 183 | } 184 | } 185 | 186 | @ExperimentalUnitApi 187 | @Composable 188 | fun setUpRow( 189 | item:NotesItem 190 | ){ 191 | Row( 192 | modifier= Modifier 193 | .fillMaxWidth() 194 | .fillMaxHeight(), 195 | verticalAlignment = Alignment.CenterVertically, 196 | horizontalArrangement = Arrangement.Center 197 | ) { 198 | 199 | Text( 200 | text = item.title,modifier = Modifier.wrapContentSize(),fontSize = TextUnit(value = 16f,type = TextUnitType.Sp)) 201 | 202 | } 203 | } 204 | 205 | @Composable 206 | fun ratingBar(){ 207 | 208 | Row(modifier = Modifier.wrapContentSize()) { 209 | 210 | } 211 | } 212 | } -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/listview/NotesItem.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.listview 2 | 3 | data class NotesItem(var id:Int,var title:String) -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val Purple200 = Color(0xFFBB86FC) 6 | val Purple500 = Color(0xFF6200EE) 7 | val Purple700 = Color(0xFF3700B3) 8 | val Teal200 = Color(0xFF03DAC5) -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.theme 2 | 3 | import androidx.compose.foundation.shape.RoundedCornerShape 4 | import androidx.compose.material.Shapes 5 | import androidx.compose.ui.unit.dp 6 | 7 | val Shapes = Shapes( 8 | small = RoundedCornerShape(4.dp), 9 | medium = RoundedCornerShape(4.dp), 10 | large = RoundedCornerShape(0.dp) 11 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.theme 2 | 3 | import androidx.compose.foundation.isSystemInDarkTheme 4 | import androidx.compose.material.MaterialTheme 5 | import androidx.compose.material.darkColors 6 | import androidx.compose.material.lightColors 7 | import androidx.compose.runtime.Composable 8 | 9 | private val DarkColorPalette = darkColors( 10 | primary = Purple200, 11 | primaryVariant = Purple700, 12 | secondary = Teal200 13 | ) 14 | 15 | private val LightColorPalette = lightColors( 16 | primary = Purple500, 17 | primaryVariant = Purple700, 18 | secondary = Teal200 19 | 20 | /* Other default colors to override 21 | background = Color.White, 22 | surface = Color.White, 23 | onPrimary = Color.White, 24 | onSecondary = Color.Black, 25 | onBackground = Color.Black, 26 | onSurface = Color.Black, 27 | */ 28 | ) 29 | 30 | @Composable 31 | fun ComposeTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) { 32 | val colors = if (darkTheme) { 33 | DarkColorPalette 34 | } else { 35 | LightColorPalette 36 | } 37 | 38 | MaterialTheme( 39 | colors = colors, 40 | typography = Typography, 41 | shapes = Shapes, 42 | content = content 43 | ) 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.theme 2 | 3 | import androidx.compose.material.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | body1 = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp 15 | ) 16 | /* Other default text styles to override 17 | button = TextStyle( 18 | fontFamily = FontFamily.Default, 19 | fontWeight = FontWeight.W500, 20 | fontSize = 14.sp 21 | ), 22 | caption = TextStyle( 23 | fontFamily = FontFamily.Default, 24 | fontWeight = FontWeight.Normal, 25 | fontSize = 12.sp 26 | ) 27 | */ 28 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/daanidev/compose/ui/webview/WebviewScreen.kt: -------------------------------------------------------------------------------- 1 | package com.daanidev.compose.ui.webview 2 | 3 | import android.content.Intent 4 | import android.net.Uri 5 | import android.os.Bundle 6 | import android.webkit.WebView 7 | import android.webkit.WebViewClient 8 | import androidx.activity.compose.setContent 9 | import androidx.appcompat.app.AppCompatActivity 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.runtime.rememberCompositionContext 12 | import androidx.compose.ui.viewinterop.AndroidView 13 | 14 | const val webUrl="https://www.github.com/Daanidev" 15 | class WebviewScreen : AppCompatActivity() { 16 | 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | 21 | setContent{ 22 | urlIntent(url = webUrl) 23 | } 24 | } 25 | 26 | 27 | @Composable 28 | fun loadWebUrl(url: String) { 29 | 30 | AndroidView(factory = { 31 | WebView(this).apply { 32 | webViewClient = WebViewClient() 33 | 34 | loadUrl(url) 35 | } 36 | }) 37 | } 38 | 39 | @Composable 40 | fun urlIntent(url:String){ 41 | 42 | val webIntent: Intent = Uri.parse(url).let { webpage -> 43 | Intent(Intent.ACTION_VIEW, webpage) 44 | } 45 | startActivity(webIntent) 46 | } 47 | } -------------------------------------------------------------------------------- /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_home.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_job.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /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_my_network.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_notification.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_post.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /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/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /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/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | compose 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 21 | 22 |