├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml └── inspectionProfiles │ └── Project_Default.xml ├── Readme.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── adriano │ │ └── composecomponents │ │ ├── CircularMotion.kt │ │ ├── CircularSlider.kt │ │ ├── ColorCheckChip.kt │ │ ├── MainActivity.kt │ │ ├── SimpleSlider.kt │ │ ├── SinusWave.kt │ │ ├── gameoflife │ │ ├── Cell.kt │ │ ├── CellGrid.kt │ │ └── GameOfLife.kt │ │ ├── theme │ │ ├── Color.kt │ │ ├── Shape.kt │ │ ├── Theme.kt │ │ └── Type.kt │ │ └── util │ │ ├── AnimationUtil.kt │ │ ├── DrawScopeExtensions.kt │ │ ├── MathUtils.kt │ │ └── RectExtensions.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── values-night │ └── themes.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── themes.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/androidstudio 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=androidstudio 4 | 5 | ### AndroidStudio ### 6 | # Covers files to be ignored for android development using Android Studio. 7 | 8 | # Built application files 9 | *.apk 10 | *.ap_ 11 | *.aab 12 | 13 | # Files for the ART/Dalvik VM 14 | *.dex 15 | 16 | # Java class files 17 | *.class 18 | 19 | # Generated files 20 | bin/ 21 | gen/ 22 | out/ 23 | 24 | # Gradle files 25 | .gradle 26 | .gradle/ 27 | build/ 28 | 29 | # Signing files 30 | .signing/ 31 | 32 | # Local configuration file (sdk path, etc) 33 | local.properties 34 | 35 | # Proguard folder generated by Eclipse 36 | proguard/ 37 | 38 | # Log Files 39 | *.log 40 | 41 | # Android Studio 42 | /*/build/ 43 | /*/local.properties 44 | /*/out 45 | /*/*/build 46 | /*/*/production 47 | captures/ 48 | .navigation/ 49 | *.ipr 50 | *~ 51 | *.swp 52 | 53 | # Keystore files 54 | *.jks 55 | *.keystore 56 | 57 | # Google Services (e.g. APIs or Firebase) 58 | # google-services.json 59 | 60 | # Android Patch 61 | gen-external-apklibs 62 | 63 | # External native build folder generated in Android Studio 2.2 and later 64 | .externalNativeBuild 65 | 66 | # NDK 67 | obj/ 68 | 69 | # IntelliJ IDEA 70 | *.iml 71 | *.iws 72 | /out/ 73 | 74 | # User-specific configurations 75 | .idea/caches/ 76 | .idea/libraries/ 77 | .idea/shelf/ 78 | .idea/workspace.xml 79 | .idea/tasks.xml 80 | .idea/.name 81 | .idea/compiler.xml 82 | .idea/copyright/profiles_settings.xml 83 | .idea/encodings.xml 84 | .idea/misc.xml 85 | .idea/modules.xml 86 | .idea/scopes/scope_settings.xml 87 | .idea/dictionaries 88 | .idea/vcs.xml 89 | .idea/jsLibraryMappings.xml 90 | .idea/datasources.xml 91 | .idea/dataSources.ids 92 | .idea/sqlDataSources.xml 93 | .idea/dynamic.xml 94 | .idea/uiDesigner.xml 95 | .idea/assetWizardSettings.xml 96 | .idea/gradle.xml 97 | .idea/jarRepositories.xml 98 | .idea/navEditor.xml 99 | 100 | # OS-specific files 101 | .DS_Store 102 | .DS_Store? 103 | ._* 104 | .Spotlight-V100 105 | .Trashes 106 | ehthumbs.db 107 | Thumbs.db 108 | 109 | # Legacy Eclipse project files 110 | .classpath 111 | .project 112 | .cproject 113 | .settings/ 114 | 115 | # Mobile Tools for Java (J2ME) 116 | .mtj.tmp/ 117 | 118 | # Package Files # 119 | *.war 120 | *.ear 121 | 122 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) 123 | hs_err_pid* 124 | 125 | ## Plugin-specific files: 126 | 127 | # mpeltonen/sbt-idea plugin 128 | .idea_modules/ 129 | 130 | # JIRA plugin 131 | atlassian-ide-plugin.xml 132 | 133 | # Mongo Explorer plugin 134 | .idea/mongoSettings.xml 135 | 136 | # Crashlytics plugin (for Android Studio and IntelliJ) 137 | com_crashlytics_export_strings.xml 138 | crashlytics.properties 139 | crashlytics-build.properties 140 | fabric.properties 141 | 142 | ### AndroidStudio Patch ### 143 | 144 | !/gradle/wrapper/gradle-wrapper.jar 145 | 146 | # End of https://www.toptal.com/developers/gitignore/api/androidstudio -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 20 | 22 | 23 | 135 | 136 | 138 | 139 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # ComposeComponents 2 | 3 | A collection of Views done with Jetpack Compose 4 | 5 | --- 6 | 7 | ## CircularMotion 8 | 9 | ![https://media.giphy.com/media/s3crJQPziQPi5c8zKu/giphy.gif](https://media.giphy.com/media/s3crJQPziQPi5c8zKu/giphy.gif) 10 | 11 | --- 12 | 13 | ## CircularSlider 14 | 15 | ![https://media.giphy.com/media/ZxGB34QU9Uq36H514c/giphy.gif](https://media.giphy.com/media/ZxGB34QU9Uq36H514c/giphy.gif) 16 | 17 | --- 18 | 19 | ## SimpleSlider 20 | 21 | ![https://media.giphy.com/media/TnGz6XDRXrOG2vuMGx/giphy.gif](https://media.giphy.com/media/TnGz6XDRXrOG2vuMGx/giphy.gif) 22 | 23 | --- 24 | 25 | ## ColorCheckChip 26 | 27 | ![https://media.giphy.com/media/8pV4KFf4dXlcVEZXqk/giphy.gif](https://media.giphy.com/media/8pV4KFf4dXlcVEZXqk/giphy.gif) 28 | 29 | --- 30 | 31 | ## SinusWave 32 | 33 | ![https://media.giphy.com/media/i6k29qCdRVLyREj4db/giphy.gif](https://media.giphy.com/media/i6k29qCdRVLyREj4db/giphy.gif) 34 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdkVersion 30 8 | 9 | defaultConfig { 10 | applicationId "com.adriano.composecomponents" 11 | minSdkVersion 23 12 | targetSdkVersion 30 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | compileOptions { 26 | sourceCompatibility JavaVersion.VERSION_1_8 27 | targetCompatibility JavaVersion.VERSION_1_8 28 | } 29 | kotlinOptions { 30 | jvmTarget = '1.8' 31 | useIR = true 32 | } 33 | buildFeatures { 34 | compose true 35 | } 36 | composeOptions { 37 | kotlinCompilerExtensionVersion compose_version 38 | kotlinCompilerVersion '1.4.21-2' 39 | } 40 | } 41 | 42 | dependencies { 43 | 44 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 45 | implementation 'androidx.core:core-ktx:1.3.2' 46 | implementation 'androidx.appcompat:appcompat:1.2.0' 47 | implementation 'com.google.android.material:material:1.2.1' 48 | implementation "androidx.compose.ui:ui:" 49 | implementation "androidx.compose.material:material:$compose_version" 50 | implementation "androidx.ui:ui-tooling:1.0.0-alpha07" 51 | implementation "androidx.compose.material:material-icons-extended:$compose_version" 52 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha07' 53 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/CircularMotion.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.compose.creative 2 | 3 | import androidx.annotation.FloatRange 4 | import androidx.compose.foundation.Canvas 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.getValue 8 | import androidx.compose.runtime.remember 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.geometry.Offset 11 | import androidx.compose.ui.graphics.* 12 | import androidx.compose.ui.graphics.drawscope.DrawScope 13 | import androidx.compose.ui.graphics.drawscope.Stroke 14 | import androidx.compose.ui.graphics.drawscope.translate 15 | import androidx.compose.ui.unit.Dp 16 | import androidx.compose.ui.unit.dp 17 | import androidx.ui.tooling.preview.Preview 18 | import com.adriano.compose.composables.ColorCheckChip 19 | import com.adriano.compose.util.TWO_PI 20 | import com.adriano.compose.util.animationTimeMillis 21 | import com.adriano.compose.util.mapRange 22 | import com.adriano.compose.util.pointForRadiusAndAngle 23 | import com.adriano.composecomponents.util.horizontalCenter 24 | import com.adriano.composecomponents.util.verticalCenter 25 | import kotlin.random.Random 26 | import kotlin.random.nextInt 27 | 28 | @Composable 29 | fun CircularMotion() { 30 | 31 | val millis by animationTimeMillis() 32 | val circleDataList = remember { createCircleData() } 33 | val path = remember { Path() } 34 | 35 | Canvas(modifier = Modifier.fillMaxSize()) { 36 | translate(horizontalCenter, verticalCenter) { 37 | circleDataList.forEach { circleData -> 38 | drawArc( 39 | millis = millis, 40 | path = path, 41 | circleData = circleData, 42 | ) 43 | } 44 | } 45 | } 46 | } 47 | 48 | private fun DrawScope.drawArc( 49 | millis: Long, 50 | path: Path, 51 | circleData: CircleData, 52 | ) { 53 | path.reset() 54 | val angles = getAngles(circleData.fraction) 55 | val circleOffsets = getCircleOffsets(angles, circleData, millis) 56 | 57 | circleOffsets.forEachIndexed { index, offset -> 58 | if (index == 0) path.moveTo(offset.x, offset.y) 59 | else path.lineTo(offset.x, offset.y) 60 | } 61 | 62 | drawPath( 63 | path = path, 64 | brush = LinearGradient( 65 | colors = listOf(circleData.color, circleData.color.copy(alpha = 0f)), 66 | startX = circleOffsets.first().x, 67 | startY = circleOffsets.first().y, 68 | endX = circleOffsets.last().x, 69 | endY = circleOffsets.last().y, 70 | ), 71 | style = Stroke( 72 | width = 4.dp.toPx(), 73 | join = StrokeJoin.Round, 74 | ) 75 | ) 76 | } 77 | 78 | private fun DrawScope.getCircleOffsets( 79 | angles: List, 80 | circleData: CircleData, 81 | millis: Long, 82 | ): List { 83 | return angles.map { angle -> 84 | val circleProgress = millis / 1000f * TWO_PI * circleData.speed 85 | return@map pointForRadiusAndAngle( 86 | radius = circleData.radius.toPx(), 87 | angle = angle - circleProgress 88 | ) 89 | } 90 | } 91 | 92 | private fun getAngles( 93 | @FloatRange(from = 0.0, to = 1.0) circleFraction: Float = 1.0f 94 | ): List { 95 | return (0..100).map { 96 | mapRange( 97 | it.toFloat(), 98 | 0f, 99 | 100f, 100 | 0f, 101 | TWO_PI * circleFraction 102 | ) 103 | } 104 | } 105 | 106 | private fun createCircleData(): List { 107 | return List(50) { 108 | CircleData( 109 | radius = Random.nextInt(10..120).dp, 110 | fraction = Random.nextInt(3..6) / 10f, 111 | speed = Random.nextInt(20..80) / 100f, 112 | color = lerp(Color.Cyan, Color.Blue, Random.nextFloat()) 113 | ) 114 | } 115 | } 116 | 117 | data class CircleData( 118 | val radius: Dp, 119 | val fraction: Float, 120 | val speed: Float, 121 | val color: Color 122 | ) 123 | 124 | @Preview 125 | @Composable 126 | fun CircularMotionPreview() { 127 | CircularMotion() 128 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/CircularSlider.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents 2 | 3 | import androidx.compose.foundation.Canvas 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.runtime.* 6 | import androidx.compose.ui.Modifier 7 | import androidx.compose.ui.geometry.Offset 8 | import androidx.compose.ui.gesture.DragObserver 9 | import androidx.compose.ui.gesture.dragGestureFilter 10 | import androidx.compose.ui.graphics.Color 11 | import androidx.compose.ui.graphics.drawscope.DrawScope 12 | import androidx.compose.ui.graphics.drawscope.Fill 13 | import androidx.compose.ui.graphics.drawscope.Stroke 14 | import androidx.compose.ui.graphics.drawscope.translate 15 | import androidx.compose.ui.unit.dp 16 | import androidx.ui.tooling.preview.Preview 17 | import com.adriano.compose.util.angleForXAndRadius 18 | import com.adriano.compose.util.pointForRadiusAndAngle 19 | import com.adriano.compose.util.radiusForPoint 20 | import com.adriano.composecomponents.util.horizontalCenter 21 | import com.adriano.composecomponents.util.verticalCenter 22 | 23 | @Composable 24 | fun CircularSlider(modifier: Modifier = Modifier) { 25 | 26 | var dragPosition by remember { mutableStateOf(Offset.Zero) } 27 | 28 | Canvas( 29 | modifier = modifier.dragGestureFilter( 30 | dragObserver = object : DragObserver { 31 | 32 | override fun onStart(downPosition: Offset) { 33 | dragPosition = downPosition 34 | } 35 | 36 | override fun onDrag(dragDistance: Offset): Offset { 37 | dragPosition += dragDistance 38 | return super.onDrag(dragDistance) 39 | } 40 | } 41 | ) 42 | ) { 43 | val (indicatorX, indicatorY) = calculateIndicatorPosition(dragPosition) 44 | 45 | translate(indicatorX, indicatorY) { 46 | drawCircle( 47 | color = Color.Magenta, 48 | radius = indicatorCircleRadius(), 49 | style = Fill 50 | ) 51 | } 52 | 53 | drawCircle( 54 | color = Color.Magenta.copy(alpha = 0.4f), 55 | radius = outerCircleRadius(), 56 | style = Stroke(width = 6.dp.toPx()) 57 | ) 58 | } 59 | } 60 | 61 | private fun DrawScope.calculateIndicatorPosition(dragPosition: Offset): Offset { 62 | val dragXOnCanvas = dragPosition.x - horizontalCenter 63 | val dragYOnCanvas = dragPosition.y - verticalCenter 64 | val radius = radiusForPoint(dragXOnCanvas, dragYOnCanvas) 65 | val angle = angleForXAndRadius(radius, dragXOnCanvas) 66 | val adjustedAngle = if (dragYOnCanvas < 0) angle * -1 else angle 67 | return pointForRadiusAndAngle(outerCircleRadius(), adjustedAngle) 68 | } 69 | 70 | private fun DrawScope.indicatorCircleRadius(): Float { 71 | return outerCircleRadius() / 12 72 | } 73 | 74 | private fun DrawScope.outerCircleRadius(): Float { 75 | return size.minDimension / 2 76 | } 77 | 78 | @Preview 79 | @Composable 80 | fun CircularSliderPreview() { 81 | CircularSlider(Modifier.fillMaxSize()) 82 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/ColorCheckChip.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.compose.composables 2 | 3 | import androidx.compose.animation.animate 4 | import androidx.compose.animation.core.TweenSpec 5 | import androidx.compose.foundation.* 6 | import androidx.compose.foundation.layout.fillMaxSize 7 | import androidx.compose.foundation.layout.preferredSize 8 | import androidx.compose.foundation.shape.RoundedCornerShape 9 | import androidx.compose.material.Card 10 | import androidx.compose.material.Text 11 | import androidx.compose.material.icons.Icons 12 | import androidx.compose.material.icons.filled.Close 13 | import androidx.compose.runtime.Composable 14 | import androidx.compose.runtime.mutableStateOf 15 | import androidx.compose.runtime.remember 16 | import androidx.compose.ui.Modifier 17 | import androidx.compose.ui.draw.clip 18 | import androidx.compose.ui.graphics.Color 19 | import androidx.compose.ui.graphics.ColorFilter 20 | import androidx.compose.ui.graphics.drawscope.translate 21 | import androidx.compose.ui.layout.ContentScale 22 | import androidx.compose.ui.layout.Layout 23 | import androidx.compose.ui.text.TextStyle 24 | import androidx.compose.ui.unit.Constraints 25 | import androidx.compose.ui.unit.Dp 26 | import androidx.compose.ui.unit.dp 27 | import androidx.ui.tooling.preview.Preview 28 | 29 | @Composable 30 | fun ColorCheckChip( 31 | modifier: Modifier = Modifier, 32 | color: Color, 33 | text: String 34 | ) { 35 | val (checked, setChecked) = remember { mutableStateOf(false) } 36 | Card( 37 | modifier = modifier 38 | .clip(RoundedCornerShape(8.dp)) 39 | .clickable { 40 | setChecked(!checked) 41 | }, 42 | border = BorderStroke(color = Color.Black, width = Dp.Hairline), 43 | shape = RoundedCornerShape(8.dp) 44 | ) { 45 | ChipLayout(checked) { 46 | ChipContent(isChecked = checked, color, text) 47 | } 48 | } 49 | } 50 | 51 | @Composable 52 | private fun ChipLayout(checked: Boolean, slot: @Composable () -> Unit) { 53 | val textMargin = if (checked) 8.dp else 32.dp 54 | val textMarginAnimated = animate(textMargin, TweenSpec(delay = 50)) 55 | Layout( 56 | content = slot, 57 | measureBlock = { measurables, constraints -> 58 | val textPlaceable = measurables[1].measure(constraints) 59 | val width = textPlaceable.width + 40.dp.toIntPx() 60 | val height = textPlaceable.height + 8.dp.toIntPx() 61 | val canvasConstraints = Constraints( 62 | maxHeight = height, 63 | minHeight = height, 64 | maxWidth = width, 65 | minWidth = width 66 | ) 67 | val canvasPlaceable = measurables[0].measure(canvasConstraints) 68 | val iconPlaceable = measurables[2].measure(constraints) 69 | layout(width, height) { 70 | canvasPlaceable.place(x = 0, y = 0) 71 | textPlaceable.place( 72 | x = textMarginAnimated.toIntPx(), 73 | y = 4.dp.toIntPx() 74 | ) 75 | iconPlaceable.place( 76 | x = width - 8.dp.toIntPx() - iconPlaceable.width, 77 | y = height / 2 - iconPlaceable.height / 2 78 | ) 79 | } 80 | } 81 | ) 82 | } 83 | 84 | @Composable 85 | fun ChipContent(isChecked: Boolean, color: Color, text: String) { 86 | 87 | val radiusExpandedFactor = if (isChecked) 1f else 0f 88 | val radiusExpandedFactorAnimated = animate(radiusExpandedFactor) 89 | 90 | val textColor = if (isChecked) Color.White else Color.Black 91 | val textColorAnimated = animate(textColor) 92 | 93 | val iconSize = if (isChecked) 16.dp else 0.dp 94 | val iconSizeAnimated = animate(iconSize, TweenSpec(delay = 100)) 95 | 96 | Canvas( 97 | modifier = Modifier.fillMaxSize(), 98 | onDraw = { 99 | val baseRadius = size.height / 6 100 | val radius = baseRadius + (radiusExpandedFactorAnimated * (size.width - baseRadius)) 101 | val left = -size.width / 2 + 16.dp.toPx() 102 | translate(left, 0f) { 103 | drawCircle(color = color, radius = radius) 104 | } 105 | } 106 | ) 107 | Text( 108 | modifier = Modifier, 109 | style = TextStyle( 110 | color = textColorAnimated 111 | ), 112 | text = text 113 | ) 114 | Image( 115 | imageVector = Icons.Filled.Close, 116 | modifier = Modifier.preferredSize(iconSizeAnimated), 117 | colorFilter = ColorFilter.tint(Color.White), 118 | contentScale = ContentScale.Fit, 119 | contentDescription = "Close" 120 | ) 121 | } 122 | 123 | @Preview 124 | @Composable 125 | fun ColorCheckChipPreview() { 126 | ColorCheckChip(color = Color.Cyan, text = "Very long test to test long text") 127 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents 2 | 3 | import android.os.Bundle 4 | import androidx.appcompat.app.AppCompatActivity 5 | import androidx.compose.foundation.layout.fillMaxSize 6 | import androidx.compose.ui.Modifier 7 | import androidx.compose.ui.platform.setContent 8 | import com.adriano.compose.composables.SimpleSlider 9 | import com.adriano.composecomponents.gameoflife.GameOfLife 10 | 11 | class MainActivity : AppCompatActivity() { 12 | override fun onCreate(savedInstanceState: Bundle?) { 13 | super.onCreate(savedInstanceState) 14 | setContent { 15 | GameOfLife() 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/SimpleSlider.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.compose.composables 2 | 3 | import androidx.compose.foundation.Canvas 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.material.MaterialTheme 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.runtime.MutableState 8 | import androidx.compose.runtime.Stable 9 | import androidx.compose.runtime.mutableStateOf 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.geometry.Offset 12 | import androidx.compose.ui.geometry.Rect 13 | import androidx.compose.ui.gesture.DragObserver 14 | import androidx.compose.ui.gesture.dragGestureFilter 15 | import androidx.compose.ui.graphics.Color 16 | import androidx.compose.ui.graphics.drawscope.DrawScope 17 | import androidx.compose.ui.graphics.drawscope.translate 18 | import androidx.compose.ui.platform.DensityAmbient 19 | import androidx.compose.ui.unit.Dp 20 | import androidx.compose.ui.unit.dp 21 | import androidx.ui.tooling.preview.Preview 22 | import com.adriano.compose.creative.CircularMotion 23 | import com.adriano.composecomponents.util.translateX 24 | import com.adriano.composecomponents.util.verticalCenter 25 | 26 | @Composable 27 | fun SimpleSlider( 28 | modifier: Modifier = Modifier, 29 | color: Color = MaterialTheme.colors.primary 30 | ) { 31 | val dragArea = mutableStateOf(Rect.Zero) 32 | Canvas( 33 | modifier = modifier.dragGestureFilter( 34 | startDragImmediately = true, 35 | dragObserver = dragObserver(dragArea) 36 | ) 37 | ) { 38 | if (initIndicatorArea(dragArea)) return@Canvas 39 | drawProgress(dragArea.value.center.x, color) 40 | drawIndicator(dragArea.value.center.x, color) 41 | } 42 | } 43 | 44 | @Composable 45 | fun dragObserver(indicatorArea: MutableState): DragObserver { 46 | 47 | val indicatorAreaRadius = indicatorRadiusPixel() 48 | var isDragging = false 49 | 50 | return object : DragObserver { 51 | 52 | override fun onStart(downPosition: Offset) { 53 | if (indicatorArea.value.contains(downPosition)) { 54 | isDragging = true 55 | indicatorArea.value = Rect( 56 | center = downPosition, 57 | radius = indicatorAreaRadius 58 | ) 59 | } 60 | } 61 | 62 | override fun onDrag(dragDistance: Offset): Offset { 63 | if (isDragging) { 64 | indicatorArea.value = indicatorArea.value.translateX(dragDistance.x) 65 | } 66 | return super.onDrag(dragDistance) 67 | } 68 | 69 | override fun onStop(velocity: Offset) { 70 | isDragging = false 71 | } 72 | } 73 | } 74 | 75 | private fun DrawScope.initIndicatorArea(dragArea: MutableState): Boolean { 76 | val notInitialized = dragArea.value == Rect.Zero 77 | if (notInitialized) { 78 | val circleRadiusPixel = indicatorRadiusPixel() 79 | dragArea.value = Rect( 80 | 0f, 81 | verticalCenter - circleRadiusPixel, 82 | circleRadiusPixel * 2, 83 | verticalCenter + circleRadiusPixel 84 | ) 85 | } 86 | return notInitialized 87 | } 88 | 89 | private fun DrawScope.drawProgress( 90 | dragPosition: Float, 91 | color: Color 92 | ) { 93 | val strokeWidth = 12 94 | 95 | drawLine( 96 | color = color, 97 | strokeWidth = strokeWidth.dp.toPx(), 98 | start = Offset(0f, verticalCenter), 99 | end = Offset(dragPosition, verticalCenter) 100 | ) 101 | 102 | drawLine( 103 | color = color.copy(alpha = 0.3f), 104 | strokeWidth = strokeWidth.dp.toPx(), 105 | start = Offset(dragPosition, verticalCenter), 106 | end = Offset(size.width, verticalCenter) 107 | ) 108 | } 109 | 110 | private fun DrawScope.drawIndicator( 111 | dragPosition: Float, 112 | color: Color 113 | ) { 114 | val circleRadiusPixel = indicatorRadiusPixel() 115 | val canvasDragPosition = dragPosition - size.width / 2 116 | val minPosition = -size.width / 2 + circleRadiusPixel 117 | val maxPosition = size.width / 2 - circleRadiusPixel 118 | val indicatorPosition = canvasDragPosition.coerceIn(minPosition, maxPosition) 119 | translate(left = indicatorPosition) { 120 | drawCircle(color = color, radius = circleRadiusPixel) 121 | } 122 | } 123 | 124 | @Composable 125 | private fun indicatorRadiusPixel(): Float = with(DensityAmbient.current) { 16.dp.toPx() } 126 | 127 | private fun DrawScope.indicatorRadiusPixel(): Float = 16.dp.toPx() 128 | 129 | @Preview 130 | @Composable 131 | fun SimpleSliderPreview() { 132 | SimpleSlider(Modifier.fillMaxSize()) 133 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/SinusWave.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.compose.creative 2 | 3 | import androidx.compose.foundation.Canvas 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.runtime.Composable 6 | import androidx.compose.runtime.getValue 7 | import androidx.compose.runtime.remember 8 | import androidx.compose.ui.Modifier 9 | import androidx.compose.ui.graphics.Color 10 | import androidx.compose.ui.graphics.Path 11 | import androidx.compose.ui.graphics.StrokeJoin 12 | import androidx.compose.ui.graphics.drawscope.DrawScope 13 | import androidx.compose.ui.graphics.drawscope.Stroke 14 | import androidx.compose.ui.graphics.drawscope.translate 15 | import androidx.compose.ui.unit.dp 16 | import androidx.ui.tooling.preview.Preview 17 | import com.adriano.compose.util.animationTimeMillis 18 | import com.adriano.composecomponents.util.verticalCenter 19 | import kotlin.math.sin 20 | 21 | @Composable 22 | fun SinusWave() { 23 | 24 | val millis by animationTimeMillis() 25 | val path = remember { Path() } 26 | Canvas(modifier = Modifier.fillMaxSize()) { 27 | path.reset() 28 | (1..WAVE_COUNT).forEach { waveIndex -> 29 | val waveDistance = waveIndex.dp.toPx() * 4 30 | translate(waveDistance, verticalCenter) { 31 | drawWave( 32 | path, 33 | color = Color.Green.copy(alpha = 1f / waveIndex), 34 | millis 35 | ) 36 | } 37 | } 38 | } 39 | } 40 | 41 | fun DrawScope.drawWave(path: Path, color: Color, millis: Long) { 42 | path.moveTo(0f, 0f) 43 | (0..size.width.toInt()).forEach { x -> 44 | val frequency = millis / 1000f 45 | val altitude = 100 * (sin(millis / 1000f)) 46 | val waveLength = 0.015f 47 | val y = sin(x * waveLength + (frequency)) * altitude 48 | path.lineTo(x.toFloat(), y) 49 | } 50 | drawPath( 51 | path = path, 52 | color = color, 53 | style = Stroke( 54 | width = 2.dp.toPx(), 55 | join = StrokeJoin.Round, 56 | ) 57 | ) 58 | } 59 | 60 | private const val WAVE_COUNT = 10 61 | 62 | @Preview 63 | @Composable 64 | fun SinusWavePreview() { 65 | SinusWave() 66 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/gameoflife/Cell.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.gameoflife 2 | 3 | import androidx.compose.ui.geometry.Offset 4 | import androidx.compose.ui.geometry.Size 5 | import androidx.compose.ui.graphics.Color 6 | import androidx.compose.ui.graphics.drawscope.DrawScope 7 | import androidx.compose.ui.graphics.drawscope.Fill 8 | 9 | data class Cell( 10 | val x: Int, 11 | val y: Int, 12 | var isAlive: Boolean, 13 | ) { 14 | 15 | fun draw(drawScope: DrawScope, cellWidth: Float, cellHeight: Float) { 16 | val color = if (isAlive) Color.Black else Color.White 17 | drawScope.drawRect( 18 | color = color, 19 | topLeft = Offset(x = x * cellWidth, y = y * cellHeight), 20 | size = Size(cellWidth, cellHeight), 21 | style = Fill 22 | ) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/gameoflife/CellGrid.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.gameoflife 2 | 3 | import androidx.compose.ui.graphics.drawscope.DrawScope 4 | import kotlin.random.Random 5 | 6 | data class CellGrid constructor( 7 | private val cells: MutableList> 8 | ) { 9 | 10 | fun calculateNextGrid(): CellGrid { 11 | val newGrid = create() 12 | (0 until cellRowSize).forEach { x -> 13 | (0 until cellColumnSize).forEach { y -> 14 | val above = if (y == 0) cellColumnSize - 1 else y - 1 15 | val below = if (y == cellColumnSize - 1) 0 else y + 1 16 | val left = if (x == 0) cellRowSize - 1 else x - 1 17 | val right = if (x == cellRowSize - 1) 0 else x + 1 18 | 19 | val currentCell = cells[x][y] 20 | 21 | val neighbours = mutableListOf() 22 | neighbours.add(cells[left][above]) 23 | neighbours.add((cells[left][y])) 24 | neighbours.add((cells[left][below])) 25 | neighbours.add(cells[x][below]) 26 | neighbours.add(cells[right][below]) 27 | neighbours.add(cells[right][y]) 28 | neighbours.add(cells[right][above]) 29 | neighbours.add(cells[x][above]) 30 | val aliveNeighbours = neighbours.count { it.isAlive } 31 | 32 | val nextStep = classicalRules(currentCell, aliveNeighbours) 33 | newGrid.cells[x][y] = Cell(isAlive = nextStep, x = x, y = y) 34 | } 35 | } 36 | return newGrid 37 | } 38 | 39 | fun draw(drawScope: DrawScope) { 40 | val cellWidth = drawScope.size.width / cellRowSize 41 | val cellHeight = drawScope.size.height / cellColumnSize 42 | (0 until cellRowSize).forEach { x -> 43 | (0 until cellColumnSize).forEach { y -> 44 | cells[x][y].draw(drawScope, cellWidth, cellHeight) 45 | } 46 | } 47 | } 48 | 49 | private fun classicalRules( 50 | currentCell: Cell, 51 | aliveNeighbours: Int 52 | ) = when { 53 | currentCell.isAlive && aliveNeighbours in 2..3 -> true 54 | currentCell.isAlive.not() && aliveNeighbours == 3 -> true 55 | else -> false 56 | } 57 | 58 | private fun vichniacVoteRules( 59 | currentCell: Cell, 60 | aliveNeighbours: Int 61 | ): Boolean { 62 | val aliveCount = aliveNeighbours + if (currentCell.isAlive) 1 else 0 63 | return when { 64 | aliveCount <= 4 -> false 65 | else -> true 66 | } 67 | } 68 | 69 | companion object { 70 | 71 | const val cellRowSize = 100 72 | const val cellColumnSize = 200 73 | 74 | fun create(): CellGrid { 75 | return CellGrid(MutableList(cellRowSize) { x -> 76 | MutableList(cellColumnSize) { y -> 77 | Cell( 78 | x = x, 79 | y = y, 80 | isAlive = Random.nextFloat() > 0.5f 81 | ) 82 | } 83 | }) 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/gameoflife/GameOfLife.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.gameoflife 2 | 3 | import androidx.compose.foundation.Canvas 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.runtime.Composable 6 | import androidx.compose.runtime.LaunchedEffect 7 | import androidx.compose.runtime.mutableStateOf 8 | import androidx.compose.runtime.remember 9 | import androidx.compose.ui.Modifier 10 | import kotlinx.coroutines.delay 11 | import kotlinx.coroutines.isActive 12 | 13 | @Composable 14 | fun GameOfLife() { 15 | 16 | val cellGrid = remember { mutableStateOf(CellGrid.create()) } 17 | 18 | LaunchedEffect(Unit) { 19 | while (isActive) { 20 | cellGrid.value = cellGrid.value.calculateNextGrid() 21 | delay(100) 22 | } 23 | } 24 | 25 | Canvas( 26 | modifier = Modifier 27 | .fillMaxSize() 28 | ) { 29 | cellGrid.value.draw(this) 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.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/adriano/composecomponents/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.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/adriano/composecomponents/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.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 ComposeComponentsTheme(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/adriano/composecomponents/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.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/adriano/composecomponents/util/AnimationUtil.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.compose.util 2 | 3 | import androidx.compose.runtime.Composable 4 | import androidx.compose.runtime.LaunchedEffect 5 | import androidx.compose.runtime.State 6 | import androidx.compose.runtime.dispatch.withFrameMillis 7 | import androidx.compose.runtime.mutableStateOf 8 | import androidx.compose.ui.graphics.Color 9 | import androidx.compose.ui.platform.AmbientLifecycleOwner 10 | import androidx.lifecycle.whenStarted 11 | import kotlin.math.PI 12 | import kotlin.math.pow 13 | import kotlin.math.sin 14 | 15 | @Composable 16 | fun animationTimeMillis(): State { 17 | val millisState = mutableStateOf(0L) 18 | val lifecycleOwner = AmbientLifecycleOwner.current 19 | LaunchedEffect(Unit) { 20 | val startTime = withFrameMillis { it } 21 | lifecycleOwner.whenStarted { 22 | while (true) { 23 | withFrameMillis { frameTime -> 24 | millisState.value = frameTime - startTime 25 | } 26 | } 27 | } 28 | } 29 | return millisState 30 | } 31 | 32 | fun sinebow(t: Float): Color { 33 | return Color( 34 | red = sin(PI * (t + 0f / 3f)).pow(2).toFloat(), 35 | green = sin(PI * (t + 1f / 3f)).pow(2).toFloat(), 36 | blue = sin(PI * (t + 2f / 3f)).pow(2).toFloat(), 37 | ) 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/util/DrawScopeExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.util 2 | 3 | import androidx.compose.ui.graphics.drawscope.DrawScope 4 | 5 | val DrawScope.horizontalCenter get() = size.width / 2 6 | val DrawScope.verticalCenter get() = size.height / 2 -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/util/MathUtils.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.compose.util 2 | 3 | import androidx.compose.ui.geometry.Offset 4 | import kotlin.math.* 5 | 6 | const val PI = Math.PI.toFloat() 7 | const val TWO_PI = 2 * PI 8 | const val HALF_PI = PI / 2 9 | 10 | /** 11 | * gives the radius for a point on the circle 12 | */ 13 | fun radiusForPoint(x: Double, y: Double): Double { 14 | return sqrt(x.pow(2) + y.pow(2)) 15 | } 16 | 17 | /** 18 | * gives the radius for a point on the circle 19 | */ 20 | fun radiusForPoint(x: Float, y: Float): Float { 21 | return sqrt(x.pow(2) + y.pow(2)) 22 | } 23 | 24 | /** 25 | * gives a point on a circle for the radius and an angle 26 | */ 27 | fun pointForRadiusAndAngle(radius: Float, angle: Float): Offset { 28 | return Offset( 29 | x = radius * cos(angle), 30 | y = radius * sin(angle) 31 | ) 32 | } 33 | 34 | 35 | /** 36 | * gives an angle for a x-coordinate and a radius 37 | */ 38 | fun angleForXAndRadius(radius: Float, x: Float): Float { 39 | return acos(x / radius) 40 | } 41 | /** 42 | * Re-maps a number from one range to another. 43 | */ 44 | fun mapRange(value: Float, start1: Float, stop1: Float, start2: Float, stop2: Float): Float { 45 | return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1)) 46 | } -------------------------------------------------------------------------------- /app/src/main/java/com/adriano/composecomponents/util/RectExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.adriano.composecomponents.util 2 | 3 | import androidx.compose.runtime.Stable 4 | import androidx.compose.ui.geometry.Rect 5 | 6 | @Stable 7 | fun Rect.translateX(translateX: Float): Rect { 8 | return Rect( 9 | left + translateX, 10 | top, 11 | right + translateX, 12 | bottom 13 | ) 14 | } -------------------------------------------------------------------------------- /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_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/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.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AdrianoCelentano/ComposeComponents/5e2cf900a947345d6f65947688daf23c086736d2/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /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 | ComposeComponents 3 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 21 | 22 |