├── 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 | 
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 | 
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 | 
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 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/test/java/com/daanidev/compose/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.daanidev.compose
2 |
3 | import org.junit.Test
4 |
5 | import org.junit.Assert.*
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * See [testing documentation](http://d.android.com/tools/testing).
11 | */
12 | class ExampleUnitTest {
13 | @Test
14 | fun addition_isCorrect() {
15 | assertEquals(4, 2 + 2)
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | ext {
4 | compose_version = '1.0.5'
5 | }
6 | repositories {
7 | google()
8 | mavenCentral()
9 | }
10 | dependencies {
11 | classpath "com.android.tools.build:gradle:7.0.4"
12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | task clean(type: Delete) {
20 | delete rootProject.buildDir
21 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | # Kotlin code style for this project: "official" or "obsolete":
21 | kotlin.code.style=official
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Oct 07 23:15:13 PKT 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/images/bottom_navigation/Screenshot_1637497996.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/images/bottom_navigation/Screenshot_1637497996.png
--------------------------------------------------------------------------------
/images/bottom_navigation/exoplayer_output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/images/bottom_navigation/exoplayer_output.png
--------------------------------------------------------------------------------
/images/bottom_navigation/swipetodimiss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DaaniDev/jetpack_compose_animations/8930f540aa5836f972740287bd59cd353833351c/images/bottom_navigation/swipetodimiss.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | dependencyResolutionManagement {
2 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | repositories {
4 | google()
5 | mavenCentral()
6 | maven { url 'https://androidx.dev/snapshots/latest/artifacts/repository' }
7 | jcenter() // Warning: this repository is going to shut down soon
8 | }
9 | }
10 | rootProject.name = "compose"
11 | include ':app'
12 |
--------------------------------------------------------------------------------