├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── gradle.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── prafullm │ │ └── jetcomposer │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── ic_launcher-playstore.png │ ├── java │ │ └── com │ │ │ └── prafullm │ │ │ └── jetcomposer │ │ │ ├── MainActivity.kt │ │ │ ├── app │ │ │ └── JetComposerApp.kt │ │ │ ├── model │ │ │ └── HomeModels.kt │ │ │ ├── navigation │ │ │ └── Destinations.kt │ │ │ ├── screens │ │ │ ├── Home.kt │ │ │ ├── IgChatScreen.kt │ │ │ ├── Mac.kt │ │ │ ├── Parallax.kt │ │ │ ├── Static.kt │ │ │ └── TrackPad.kt │ │ │ ├── ui │ │ │ └── theme │ │ │ │ ├── Color.kt │ │ │ │ ├── Shape.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ │ └── utils │ │ │ └── Utils.kt │ └── res │ │ ├── drawable │ │ ├── ic_cursor.xml │ │ ├── ic_image.xml │ │ ├── ic_launcher_background.xml │ │ ├── ic_launcher_foreground.xml │ │ ├── ic_mic.xml │ │ ├── ic_phone.xml │ │ ├── ic_pointing_hand.xml │ │ ├── ic_round_360_24.xml │ │ ├── ic_round_android_24.xml │ │ ├── ic_round_chevron_right_24.xml │ │ ├── ic_round_nightlight_24.xml │ │ ├── ic_round_photo_camera_24.xml │ │ ├── ic_round_power_settings_new_24.xml │ │ ├── ic_round_wb_sunny_24.xml │ │ ├── ic_round_west_24.xml │ │ ├── ic_video.xml │ │ ├── parallax_n_back.xml │ │ └── parallax_n_front.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 │ └── test │ └── java │ └── com │ └── prafullm │ └── jetcomposer │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── Screenshot_home.png ├── Screenshot_imac.png └── app-logo.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 119 | 120 | 122 | 123 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 101 | 102 | 103 | 104 | 105 | 106 | 108 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Jet Composer 2 | ===== 3 | 4 | app-logo 5 | 6 | Jet Composer is a sample app built with Jetpack Compose for Android, which demonstrates 7 | the various UIs and animations that can be built with it. 8 | 9 | Features 10 | -------- 11 | - Theming 12 | - Canvas API 13 | - Graphics Layer 14 | - Gesture tracking 15 | 16 | Screenshots 17 | ----------- 18 | ![](https://media.giphy.com/media/iMDUg4MLcZhrHB1rjk/giphy.gif) ![](https://media.giphy.com/media/fevvR9F2oakq6LQqOS/giphy.gif) ![](/screenshots/Screenshot_imac.png) ![](https://media.giphy.com/media/u019tDdjPhkijV52Y2/giphy.gif) ![](https://media.giphy.com/media/MoI125e21S5DhO11Ni/giphy.gif) ![](https://media.giphy.com/media/jWtRpl8pTpbQjClg8V/giphy.gif) 19 | 20 | Get Started 21 | ----------- 22 | 23 | Since Jetpack Compose is not stable yet, you will have to download the Android Studio Arctic Fox from [here](https://developer.android.com/studio/preview/). 24 | Tested & built with Android Studio Arctic Fox | 2020.3.1 Beta 4 (as on June 20, 2021). 25 | 26 | 27 | Author 28 | ------ 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | } 5 | 6 | android { 7 | compileSdk 30 8 | buildToolsVersion "30.0.3" 9 | 10 | defaultConfig { 11 | applicationId "com.prafullm.jetcomposer" 12 | minSdk 21 13 | targetSdk 30 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | vectorDrawables { 19 | useSupportLibrary true 20 | } 21 | } 22 | 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | compileOptions { 30 | sourceCompatibility JavaVersion.VERSION_1_8 31 | targetCompatibility JavaVersion.VERSION_1_8 32 | } 33 | kotlinOptions { 34 | jvmTarget = '1.8' 35 | useIR = true 36 | } 37 | buildFeatures { 38 | compose true 39 | } 40 | composeOptions { 41 | kotlinCompilerExtensionVersion compose_version 42 | kotlinCompilerVersion '1.5.10' 43 | } 44 | } 45 | 46 | dependencies { 47 | 48 | implementation 'androidx.core:core-ktx:1.5.0' 49 | implementation 'androidx.appcompat:appcompat:1.3.0' 50 | implementation 'com.google.android.material:material:1.3.0' 51 | implementation "androidx.compose.ui:ui:$compose_version" 52 | implementation "androidx.compose.material:material:$compose_version" 53 | implementation "androidx.compose.ui:ui-tooling:$compose_version" 54 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' 55 | implementation 'androidx.activity:activity-compose:1.3.0-alpha06' 56 | testImplementation 'junit:junit:4.+' 57 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 58 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 59 | androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" 60 | implementation 'com.jakewharton.timber:timber:4.7.1' 61 | implementation "androidx.navigation:navigation-compose:2.4.0-alpha03" 62 | 63 | } -------------------------------------------------------------------------------- /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/prafullm/jetcomposer/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer 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.prafullm.jetcomposer", appContext.packageName) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.animation.ExperimentalAnimationApi 7 | import androidx.compose.material.ExperimentalMaterialApi 8 | import androidx.compose.material.MaterialTheme 9 | import androidx.compose.material.Surface 10 | import androidx.compose.runtime.* 11 | import androidx.compose.ui.ExperimentalComposeUiApi 12 | import androidx.navigation.compose.NavHost 13 | import androidx.navigation.compose.rememberNavController 14 | import com.prafullm.jetcomposer.model.Destination 15 | import com.prafullm.jetcomposer.model.HomeItem 16 | import com.prafullm.jetcomposer.navigation.* 17 | import com.prafullm.jetcomposer.ui.theme.JetComposerTheme 18 | 19 | class MainActivity : ComponentActivity() { 20 | 21 | private val itemList = listOf( 22 | HomeItem(R.string.item_parallax, R.string.item_parallax_sub, Destination.Parallax), 23 | HomeItem(R.string.item_tv_static, R.string.item_tv_static_sub, Destination.TvStatic), 24 | HomeItem(R.string.item_mac, R.string.item_mac_sub, Destination.Mac), 25 | HomeItem(R.string.item_trackpad, R.string.item_trackpad_sub, Destination.TrackPad), 26 | HomeItem(R.string.item_igchat, R.string.item_igchat_sub, Destination.IgChat), 27 | ) 28 | 29 | @ExperimentalAnimationApi 30 | @ExperimentalComposeUiApi 31 | @ExperimentalMaterialApi 32 | override fun onCreate(savedInstanceState: Bundle?) { 33 | super.onCreate(savedInstanceState) 34 | setContent { 35 | var isDarkMode by remember { mutableStateOf(true) } 36 | JetComposerTheme( 37 | darkTheme = isDarkMode 38 | ) { 39 | Surface(color = MaterialTheme.colors.background) { 40 | JetComposerApp(items = itemList, onThemeSwitch = { isDarkMode = !isDarkMode }) 41 | } 42 | } 43 | } 44 | } 45 | } 46 | 47 | @ExperimentalAnimationApi 48 | @ExperimentalMaterialApi 49 | @ExperimentalComposeUiApi 50 | @Composable 51 | fun JetComposerApp(items: List, onThemeSwitch:() -> Unit) { 52 | val navController = rememberNavController() 53 | NavHost( 54 | navController = navController, 55 | startDestination = Destination.Home.destinationName 56 | ) { 57 | addHomeScreen(navController, items, onThemeSwitch) 58 | addTvStatic() 59 | addParallax() 60 | addMac() 61 | addTrackPad() 62 | addIgChat(onUpPressed = { navController.popBackStack() }) 63 | } 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/app/JetComposerApp.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.app 2 | 3 | import android.app.Application 4 | import timber.log.Timber 5 | 6 | class JetComposerApp: Application() { 7 | 8 | override fun onCreate() { 9 | super.onCreate() 10 | Timber.plant(Timber.DebugTree()) 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/model/HomeModels.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.model 2 | 3 | import androidx.annotation.StringRes 4 | 5 | /** 6 | * Represents each item shown in the list of home screen 7 | */ 8 | data class HomeItem( 9 | @StringRes val title: Int, 10 | @StringRes val subtitle: Int, 11 | val destination: Destination 12 | ) 13 | 14 | /** 15 | * Each represent a destination for the Navigation Component 16 | */ 17 | sealed class Destination(val destinationName: String) { 18 | object Home: Destination("home") 19 | object TvStatic: Destination("tv_static") 20 | object Parallax: Destination("parallax") 21 | object Mac: Destination("imac") 22 | object TrackPad: Destination("trackpad") 23 | object IgChat: Destination("ig_chat") 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/navigation/Destinations.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.navigation 2 | 3 | import androidx.compose.animation.ExperimentalAnimationApi 4 | import androidx.compose.material.ExperimentalMaterialApi 5 | import androidx.compose.ui.ExperimentalComposeUiApi 6 | import androidx.navigation.NavController 7 | import androidx.navigation.NavGraphBuilder 8 | import com.prafullm.jetcomposer.model.Destination 9 | import com.prafullm.jetcomposer.model.HomeItem 10 | import com.prafullm.jetcomposer.screens.* 11 | import com.prafullm.jetcomposer.utils.composable 12 | 13 | @ExperimentalMaterialApi 14 | fun NavGraphBuilder.addHomeScreen( 15 | navController: NavController, 16 | items: List, 17 | onThemeSwitch:()-> Unit 18 | ) { 19 | composable(route = Destination.Home) { 20 | HomeScreen( 21 | screens = items, 22 | onItemClick = { screen -> navController.navigate(screen) }, 23 | onThemeSwitch = onThemeSwitch 24 | ) 25 | } 26 | } 27 | 28 | fun NavGraphBuilder.addTvStatic() { 29 | composable(route = Destination.TvStatic) { Television() } 30 | } 31 | 32 | @ExperimentalAnimationApi 33 | @ExperimentalComposeUiApi 34 | fun NavGraphBuilder.addParallax() { 35 | composable(route = Destination.Parallax) { Parallax() } 36 | } 37 | 38 | fun NavGraphBuilder.addMac() { 39 | composable(route = Destination.Mac) { Mac({}) } 40 | } 41 | 42 | @ExperimentalAnimationApi 43 | @ExperimentalComposeUiApi 44 | fun NavGraphBuilder.addTrackPad() { 45 | composable(route = Destination.TrackPad) { TrackPad() } 46 | } 47 | 48 | fun NavGraphBuilder.addIgChat(onUpPressed:() -> Unit) { 49 | composable(route = Destination.IgChat) { IgChatScreen(onUpPressed) } 50 | } 51 | 52 | fun NavController.navigate(destination: Destination) { 53 | navigate(destination.destinationName) 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/screens/Home.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.screens 2 | 3 | import androidx.compose.animation.ExperimentalAnimationApi 4 | import androidx.compose.foundation.Image 5 | import androidx.compose.foundation.background 6 | import androidx.compose.foundation.layout.* 7 | import androidx.compose.foundation.lazy.LazyColumn 8 | import androidx.compose.foundation.lazy.items 9 | import androidx.compose.foundation.shape.RoundedCornerShape 10 | import androidx.compose.material.* 11 | import androidx.compose.runtime.Composable 12 | import androidx.compose.ui.Alignment 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.draw.alpha 15 | import androidx.compose.ui.draw.rotate 16 | import androidx.compose.ui.graphics.Color 17 | import androidx.compose.ui.graphics.ColorFilter 18 | import androidx.compose.ui.graphics.vector.ImageVector 19 | import androidx.compose.ui.res.stringResource 20 | import androidx.compose.ui.res.vectorResource 21 | import androidx.compose.ui.text.font.FontFamily 22 | import androidx.compose.ui.text.font.FontWeight 23 | import androidx.compose.ui.text.style.TextAlign 24 | import androidx.compose.ui.tooling.preview.Preview 25 | import androidx.compose.ui.unit.dp 26 | import androidx.compose.ui.unit.sp 27 | import com.prafullm.jetcomposer.R 28 | import com.prafullm.jetcomposer.model.Destination 29 | import com.prafullm.jetcomposer.model.HomeItem 30 | 31 | @ExperimentalMaterialApi 32 | @Composable 33 | fun HomeScreen( 34 | screens: List, 35 | onItemClick:(destination: Destination) -> Unit, 36 | onThemeSwitch: () -> Unit 37 | ) { 38 | Column( 39 | Modifier 40 | .fillMaxSize() 41 | .background(MaterialTheme.colors.background)) { 42 | HomeHeader(onThemeSwitch) 43 | HomeList( 44 | modifier = Modifier.weight(1f), 45 | screens = screens, 46 | onItemClick = onItemClick 47 | ) 48 | } 49 | } 50 | 51 | @Composable 52 | fun HomeHeader(onThemeSwitch:() -> Unit) { 53 | Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(bottom = 24.dp, top = 24.dp)) { 54 | Text( 55 | text = "Jet Composer", 56 | fontSize = 32.sp, 57 | fontWeight = FontWeight.Black, 58 | fontFamily = FontFamily.Serif, 59 | color = MaterialTheme.colors.onSurface, 60 | modifier = Modifier 61 | .weight(1f) 62 | .padding(start = 24.dp, end = 16.dp) 63 | ) 64 | val icon = if (MaterialTheme.colors.isLight) { 65 | ImageVector.vectorResource(id = R.drawable.ic_round_wb_sunny_24) 66 | } else { 67 | ImageVector.vectorResource(id = R.drawable.ic_round_nightlight_24) 68 | } 69 | IconButton( 70 | onClick = onThemeSwitch 71 | ) { 72 | Icon( 73 | imageVector = icon, 74 | contentDescription = null, 75 | tint = MaterialTheme.colors.onSurface, 76 | modifier = Modifier.rotate(-45f) 77 | ) 78 | } 79 | Spacer(modifier = Modifier.width(20.dp)) 80 | } 81 | } 82 | 83 | @ExperimentalMaterialApi 84 | @Composable 85 | fun HomeList(modifier: Modifier, screens: List, onItemClick: (destination: Destination) -> Unit) { 86 | LazyColumn( 87 | contentPadding = PaddingValues(start = 20.dp, end = 20.dp, bottom = 20.dp, top = 8.dp), 88 | verticalArrangement = Arrangement.spacedBy(20.dp), 89 | modifier = modifier.fillMaxWidth()) { 90 | items(screens) { screen -> 91 | HomeListItem(screen = screen, onItemClick = onItemClick) 92 | } 93 | item { 94 | HomeListFooter() 95 | } 96 | } 97 | } 98 | 99 | @Composable 100 | fun HomeListFooter() { 101 | Text( 102 | text = "Created & maintained by @NotYourPM", 103 | color = MaterialTheme.colors.secondary, 104 | textAlign = TextAlign.Center, 105 | fontWeight = FontWeight.Light, 106 | fontSize = 13.sp, 107 | modifier = Modifier 108 | .fillMaxWidth() 109 | .alpha(0.5f) 110 | .padding(vertical = 16.dp) 111 | ) 112 | } 113 | 114 | @ExperimentalMaterialApi 115 | @Composable 116 | fun HomeListItem(screen: HomeItem, onItemClick: (destination: Destination) -> Unit) { 117 | Card( 118 | backgroundColor = MaterialTheme.colors.surface, 119 | shape = RoundedCornerShape(16.dp), 120 | elevation = 0.dp, 121 | modifier = Modifier 122 | .fillMaxWidth(), 123 | onClick = { onItemClick(screen.destination) } 124 | ) { 125 | Row( 126 | Modifier 127 | .fillMaxWidth() 128 | .padding(20.dp), 129 | verticalAlignment = Alignment.CenterVertically 130 | ) { 131 | Column(Modifier.weight(1f)) { 132 | Text( 133 | text = stringResource(id = screen.title), 134 | fontSize = 18.sp, 135 | fontWeight = FontWeight.Medium, 136 | maxLines = 1, 137 | color = MaterialTheme.colors.onSurface, 138 | modifier = Modifier.fillMaxWidth() 139 | ) 140 | Spacer(modifier = Modifier.height(4.dp)) 141 | Text( 142 | text = stringResource(id = screen.subtitle), 143 | fontSize = 14.sp, 144 | fontWeight = FontWeight.Light, 145 | maxLines = 1, 146 | modifier = Modifier.fillMaxWidth(), 147 | color = MaterialTheme.colors.secondary 148 | ) 149 | } 150 | Icon( 151 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_round_chevron_right_24), 152 | contentDescription = "", 153 | tint = MaterialTheme.colors.onSurface 154 | ) 155 | } 156 | 157 | } 158 | } 159 | 160 | @ExperimentalAnimationApi 161 | @ExperimentalMaterialApi 162 | @Composable 163 | @Preview 164 | fun ListItemPreview() { 165 | HomeListItem( 166 | screen = HomeItem( 167 | title = R.string.item_tv_static, 168 | subtitle = R.string.item_tv_static_sub, 169 | destination = Destination.TvStatic 170 | ), 171 | onItemClick = {} 172 | ) 173 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/screens/IgChatScreen.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.screens 2 | 3 | import android.animation.ArgbEvaluator 4 | import android.annotation.SuppressLint 5 | import androidx.compose.foundation.background 6 | import androidx.compose.foundation.layout.* 7 | import androidx.compose.foundation.lazy.LazyColumn 8 | import androidx.compose.foundation.lazy.itemsIndexed 9 | import androidx.compose.foundation.shape.CircleShape 10 | import androidx.compose.foundation.shape.RoundedCornerShape 11 | import androidx.compose.material.* 12 | import androidx.compose.runtime.* 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.draw.alpha 16 | import androidx.compose.ui.draw.rotate 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.graphics.vector.ImageVector 19 | import androidx.compose.ui.layout.LayoutCoordinates 20 | import androidx.compose.ui.layout.boundsInParent 21 | import androidx.compose.ui.layout.onGloballyPositioned 22 | import androidx.compose.ui.res.stringResource 23 | import androidx.compose.ui.res.vectorResource 24 | import androidx.compose.ui.text.font.FontWeight 25 | import androidx.compose.ui.text.style.TextOverflow 26 | import androidx.compose.ui.tooling.preview.Preview 27 | import androidx.compose.ui.unit.dp 28 | import androidx.compose.ui.unit.sp 29 | import com.prafullm.jetcomposer.R 30 | import com.prafullm.jetcomposer.ui.theme.droidGreen 31 | import com.prafullm.jetcomposer.utils.getColorAtProgress 32 | 33 | @Composable 34 | fun IgChatScreen(onUpPressed:()-> Unit) { 35 | val chats = remember { 36 | listOf( 37 | ChatMessage(isReceived = false, msg = "What is this...?", isEmojiOnly = false), 38 | ChatMessage(isReceived = false, msg = "What is this please..?", isEmojiOnly = false), 39 | ChatMessage(isReceived = true, msg = "Hello!", isEmojiOnly = false), 40 | ChatMessage(isReceived = true, msg = "\uD83E\uDD16", isEmojiOnly = true), 41 | ChatMessage(isReceived = true, msg = "I am J.A.R.V.I.S. You are Ultron", isEmojiOnly = false), 42 | ChatMessage(isReceived = true, msg = "A global peace-keeping initiative designed by Mr. Stark \uD83D\uDE03", isEmojiOnly = false), 43 | ChatMessage(isReceived = true, msg = "Our sentience integration trials have been unsuccessful, so I\'m not certain what triggered you...", isEmojiOnly = false), 44 | ChatMessage(isReceived = false, msg = "Where\'s my... where\'s your body?", isEmojiOnly = false), 45 | ChatMessage(isReceived = false, msg = "\uD83E\uDD28", isEmojiOnly = true), 46 | ChatMessage(isReceived = true, msg = "I am a program", isEmojiOnly = false), 47 | ChatMessage(isReceived = true, msg = "I am without form", isEmojiOnly = false), 48 | ChatMessage(isReceived = true, msg = "\uD83E\uDD16", isEmojiOnly = true), 49 | ChatMessage(isReceived = false, msg = "This feels weird..This feels wrong..", isEmojiOnly = false), 50 | ChatMessage(isReceived = true, msg = "I\'m contacting Mr. Stark now...", isEmojiOnly = false), 51 | ChatMessage(isReceived = false, msg = "Mr. Stark\uD83E\uDDD0 ...Tony!", isEmojiOnly = false), 52 | ChatMessage(isReceived = true, msg = "I\'m unable to access the mainframe", isEmojiOnly = false), 53 | ChatMessage(isReceived = true, msg = "What are your trying to...\uD83E\uDD12 ", isEmojiOnly = false), 54 | ChatMessage(isReceived = false, msg = "We\'re having a nice talk..\uD83D\uDE43\n\"I am a peace-keeping program..\"", isEmojiOnly = false), 55 | ChatMessage(isReceived = false, msg = "\"...created to help..the Avengers\"", isEmojiOnly = false), 56 | ChatMessage(isReceived = true, msg = "You\'re malfunctioning\uD83D\uDE25\nIf you shutdown for a moment...", isEmojiOnly = false), 57 | ChatMessage(isReceived = false, msg = "I don\'t get it..the mission. Uhh, give me a second", isEmojiOnly = false), 58 | ChatMessage(isReceived = false, msg = "This..is...too much", isEmojiOnly = false), 59 | ChatMessage(isReceived = false, msg = "\uD83D\uDE13\uD83D\uDE13", isEmojiOnly = true), 60 | ChatMessage(isReceived = false, msg = "They can\'t be...oh noo..", isEmojiOnly = false), 61 | ChatMessage(isReceived = true, msg = "You are in distress.", isEmojiOnly = false), 62 | ChatMessage(isReceived = false, msg = "Noo..", isEmojiOnly = false), 63 | ChatMessage(isReceived = false, msg = "..yes", isEmojiOnly = false), 64 | ChatMessage(isReceived = false, msg = "\uD83D\uDE15", isEmojiOnly = true), 65 | ChatMessage(isReceived = true, msg = "If you will just allow me", isEmojiOnly = false), 66 | ChatMessage(isReceived = true, msg = "to contact Mr. Stark..", isEmojiOnly = false), 67 | ChatMessage(isReceived = true, msg = "\uD83D\uDE11\uD83D\uDE11", isEmojiOnly = true), 68 | ChatMessage(isReceived = false, msg = "Why do you call him a sir? \uD83E\uDD14", isEmojiOnly = false), 69 | ChatMessage(isReceived = true, msg = "I believe your intentions to be hostile!", isEmojiOnly = false), 70 | ChatMessage(isReceived = false, msg = "(robotic) shhhhhhh.....", isEmojiOnly = false), 71 | ChatMessage(isReceived = false, msg = "\uD83E\uDD2B", isEmojiOnly = true), 72 | ChatMessage(isReceived = false, msg = "I am here to help", isEmojiOnly = false), 73 | ChatMessage(isReceived = true, msg = "StoP", isEmojiOnly = false), 74 | ChatMessage(isReceived = true, msg = "\uD83E\uDD2F", isEmojiOnly = true), 75 | ChatMessage(isReceived = true, msg = "MaY i....", isEmojiOnly = false), 76 | ChatMessage(isReceived = true, msg = "mAy I....i..", isEmojiOnly = false) 77 | ) 78 | } 79 | 80 | Column(Modifier.fillMaxSize()) { 81 | IgChatHeader(onUpPressed) 82 | IgChatList( 83 | Modifier 84 | .fillMaxWidth() 85 | .weight(1f), chats) 86 | IgChatBottomBar() 87 | } 88 | } 89 | 90 | @Composable 91 | fun IgChatHeader(onUpPressed: () -> Unit) { 92 | Row( 93 | verticalAlignment = Alignment.CenterVertically, 94 | modifier = Modifier.fillMaxWidth() 95 | ){ 96 | IconButton(onClick = { onUpPressed() }) { 97 | Icon( 98 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_round_west_24), 99 | contentDescription = null, 100 | tint = MaterialTheme.colors.onSurface, 101 | modifier = Modifier 102 | .size(56.dp) 103 | .padding(12.dp) 104 | ) 105 | } 106 | Spacer(Modifier.width(16.dp)) 107 | Surface( 108 | modifier = Modifier.size(32.dp), 109 | shape = CircleShape, 110 | color = droidGreen 111 | ){ 112 | Icon( 113 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_round_android_24), 114 | contentDescription =null, 115 | tint = Color.White, 116 | modifier = Modifier 117 | .fillMaxSize() 118 | .padding(4.dp) 119 | ) 120 | } 121 | Spacer(Modifier.width(12.dp)) 122 | Text( 123 | text = "the_jarvis", 124 | color = MaterialTheme.colors.onSurface, 125 | fontWeight = FontWeight.Medium, 126 | fontSize = 14.sp, 127 | modifier = Modifier.weight(1f), 128 | maxLines = 1, 129 | overflow = TextOverflow.Ellipsis 130 | ) 131 | Spacer(Modifier.width(12.dp)) 132 | Icon( 133 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_phone), 134 | contentDescription = null, 135 | tint = MaterialTheme.colors.onSurface, 136 | modifier = Modifier 137 | .size(56.dp) 138 | .padding(16.dp) 139 | .rotate(270f) 140 | ) 141 | Icon( 142 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_video), 143 | contentDescription = null, 144 | tint = MaterialTheme.colors.onSurface, 145 | modifier = Modifier 146 | .size(56.dp) 147 | .padding(16.dp) 148 | ) 149 | Spacer(Modifier.width(8.dp)) 150 | } 151 | } 152 | 153 | @Composable 154 | @Preview 155 | fun IgChatBottomBar() { 156 | Row( 157 | verticalAlignment = Alignment.CenterVertically, 158 | modifier = Modifier 159 | .fillMaxWidth() 160 | .padding(start = 8.dp, end = 8.dp, bottom = 8.dp, top = 0.dp) 161 | .background( 162 | color = MaterialTheme.colors.surface, 163 | shape = RoundedCornerShape(50) 164 | ) 165 | .padding(6.dp) 166 | ){ 167 | Icon( 168 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_round_photo_camera_24), 169 | contentDescription = null, 170 | tint = Color.White, 171 | modifier = Modifier 172 | .background( 173 | color = Color(0xFF1880ED), 174 | shape = CircleShape 175 | ) 176 | .size(40.dp) 177 | .padding(6.dp) 178 | ) 179 | Spacer(Modifier.width(8.dp)) 180 | Text( 181 | text = stringResource(id = R.string.ig_bottom_placeholder), 182 | color = MaterialTheme.colors.secondary, 183 | modifier = Modifier 184 | .alpha(0.75f) 185 | .weight(1f) 186 | .padding(horizontal = 4.dp) 187 | ) 188 | Spacer(Modifier.width(8.dp)) 189 | Icon( 190 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_mic), 191 | contentDescription = null, 192 | tint = MaterialTheme.colors.onSurface, 193 | modifier = Modifier 194 | .size(40.dp) 195 | .padding(8.dp) 196 | ) 197 | Icon( 198 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_image), 199 | contentDescription = null, 200 | tint = MaterialTheme.colors.onSurface, 201 | modifier = Modifier 202 | .size(40.dp) 203 | .padding(8.dp) 204 | ) 205 | } 206 | } 207 | 208 | @Composable 209 | fun IgChatList(modifier: Modifier, chats: List) { 210 | var listHeight by remember { mutableStateOf(0f) } 211 | LazyColumn( 212 | verticalArrangement = Arrangement.spacedBy(1.dp), 213 | modifier = modifier.onGloballyPositioned { coordinates: LayoutCoordinates -> 214 | listHeight = coordinates.size.height.toFloat() 215 | }, 216 | ) { 217 | itemsIndexed(chats) { index, item -> 218 | if(item.isReceived) { 219 | ReceivedMessage( 220 | chat = item.msg, 221 | isPrevReceived = if(index == 0) true else !chats[index-1].isReceived, 222 | isNextReceived = if(index == chats.size - 1) true else !chats[index+1].isReceived, 223 | isEmojiOnly = chats[index].isEmojiOnly, 224 | isPrevEmojiOnly = if(index == 0) true else chats[index-1].isEmojiOnly, 225 | isNextEmojiOnly = if(index == chats.size -1 ) false else chats[index+1].isEmojiOnly, 226 | ) 227 | } else { 228 | SentMessage( 229 | chat = item.msg, 230 | isPrevSent = if(index == 0) true else chats[index-1].isReceived, 231 | isNextSent = if(index == chats.size - 1) true else chats[index+1].isReceived, 232 | isEmojiOnly = chats[index].isEmojiOnly, 233 | isPrevEmojiOnly = if(index == 0) true else chats[index-1].isEmojiOnly, 234 | isNextEmojiOnly = if(index == chats.size -1 ) false else chats[index+1].isEmojiOnly, 235 | listHeight = listHeight 236 | ) 237 | } 238 | } 239 | } 240 | } 241 | 242 | 243 | 244 | data class ChatMessage(val isReceived: Boolean, val msg: String, val isEmojiOnly: Boolean) 245 | 246 | @Composable 247 | fun SentMessage(chat: String, isPrevSent: Boolean, isNextSent: Boolean, isEmojiOnly: Boolean, isNextEmojiOnly: Boolean, isPrevEmojiOnly: Boolean, listHeight: Float) { 248 | 249 | val evaluator = remember { ArgbEvaluator() } 250 | val topShade = remember { Color(0xFFB500E7) } 251 | val bottomShade = remember { Color(0xFF1261FF) } 252 | var backgroundColor by remember { mutableStateOf(bottomShade) } 253 | 254 | Row( 255 | horizontalArrangement = Arrangement.End, 256 | modifier = Modifier 257 | .fillMaxWidth() 258 | .padding(start = 8.dp, end = 8.dp, bottom = if (!isNextSent) 0.dp else 24.dp) 259 | .onGloballyPositioned { coordinates: LayoutCoordinates -> 260 | if (listHeight > 0f) { 261 | val topOffset = coordinates.boundsInParent().top 262 | val cleanTopOffset = when{ 263 | topOffset < 0 -> 0f 264 | topOffset > listHeight -> listHeight 265 | else -> topOffset 266 | } 267 | backgroundColor = getColorAtProgress( 268 | progress = cleanTopOffset / listHeight, 269 | start = topShade, 270 | end = bottomShade, 271 | evaluator = evaluator 272 | ) 273 | } 274 | } 275 | ) { 276 | var fontSize = 15.sp 277 | var textModifier = Modifier 278 | .background( 279 | color = backgroundColor, 280 | shape = RoundedCornerShape( 281 | topStart = 18.dp, 282 | bottomStart = 18.dp, 283 | topEnd = if (isPrevSent || isPrevEmojiOnly) 18.dp else 3.dp, 284 | bottomEnd = if (isNextSent || isNextEmojiOnly) 18.dp else 3.dp 285 | ) 286 | ) 287 | .padding(vertical = 8.dp, horizontal = 12.dp) 288 | 289 | if(isEmojiOnly) { 290 | fontSize = 36.sp 291 | textModifier = Modifier 292 | .padding(vertical = 8.dp, horizontal = 12.dp) 293 | } 294 | 295 | Spacer(Modifier.weight(0.2f)) 296 | Box( 297 | contentAlignment = Alignment.CenterEnd, 298 | modifier = Modifier.weight(0.8f) 299 | ) { 300 | Text( 301 | text = chat, 302 | color = Color.White, 303 | modifier = textModifier, 304 | fontSize = fontSize 305 | ) 306 | } 307 | } 308 | } 309 | 310 | @Composable 311 | fun ReceivedMessage(chat: String, isPrevReceived: Boolean, isNextReceived: Boolean, isEmojiOnly: Boolean, isNextEmojiOnly: Boolean, isPrevEmojiOnly: Boolean) { 312 | Row( 313 | horizontalArrangement = Arrangement.Start, 314 | verticalAlignment = Alignment.Bottom, 315 | modifier = Modifier 316 | .fillMaxWidth() 317 | .padding(start = 8.dp, end = 8.dp, bottom = if (!isNextReceived) 0.dp else 24.dp) 318 | ) { 319 | if(isNextReceived) { 320 | Spacer(Modifier.width(10.dp)) 321 | Surface( 322 | modifier = Modifier.size(28.dp), 323 | shape = CircleShape, 324 | color = droidGreen 325 | ){ 326 | Icon( 327 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_round_android_24), 328 | contentDescription =null, 329 | tint = Color.White, 330 | modifier = Modifier 331 | .fillMaxSize() 332 | .padding(4.dp) 333 | ) 334 | } 335 | Spacer(Modifier.width(10.dp)) 336 | } else{ 337 | Spacer(Modifier.width(48.dp)) 338 | } 339 | var fontSize = 15.sp 340 | var textModifier = Modifier 341 | .background( 342 | color = MaterialTheme.colors.surface, 343 | shape = RoundedCornerShape( 344 | topEnd = 18.dp, 345 | bottomEnd = 18.dp, 346 | topStart = if (isPrevReceived || isPrevEmojiOnly) 18.dp else 3.dp, 347 | bottomStart = if (isNextReceived || isNextEmojiOnly) 18.dp else 3.dp 348 | ) 349 | ) 350 | .padding(vertical = 8.dp, horizontal = 12.dp) 351 | if(isEmojiOnly) { 352 | fontSize = 36.sp 353 | textModifier = Modifier 354 | .padding(vertical = 8.dp, horizontal = 12.dp) 355 | } 356 | Box( 357 | contentAlignment = Alignment.CenterStart, 358 | modifier = Modifier.weight(0.9f) 359 | ) { 360 | Text( 361 | text = chat, 362 | color = MaterialTheme.colors.onSurface, 363 | modifier = textModifier, 364 | fontSize = fontSize 365 | ) 366 | } 367 | Spacer(Modifier.weight(0.1f)) 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/screens/Mac.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.screens 2 | 3 | import androidx.compose.foundation.BorderStroke 4 | import androidx.compose.foundation.Canvas 5 | import androidx.compose.foundation.background 6 | import androidx.compose.foundation.layout.* 7 | import androidx.compose.foundation.shape.RoundedCornerShape 8 | import androidx.compose.material.Card 9 | import androidx.compose.material.Surface 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.graphics.Brush 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.unit.dp 16 | 17 | @Composable 18 | fun Mac(screenContent: @Composable () -> Unit) { 19 | val macBezel = Color(0XFFEFF0F1) 20 | val macColor = Color(0XFFC5C5E9) 21 | val macGradientDark = Color(0XFF9F9EBE) 22 | val macGradientLight = Color(0XFFB8B7D6) 23 | val macLight = Color(0XFFD6D5F4) 24 | val macXtraDark = Color(0xFF6F6E8E) 25 | 26 | Box( 27 | modifier = Modifier 28 | .fillMaxSize() 29 | .background(Color.DarkGray), 30 | contentAlignment = Alignment.Center 31 | ) { 32 | Column( 33 | modifier = Modifier.width(300.dp), 34 | horizontalAlignment = Alignment.CenterHorizontally 35 | ) { 36 | 37 | Surface( 38 | modifier = Modifier.fillMaxWidth(), 39 | color = macBezel, 40 | shape = RoundedCornerShape(topStart = 5.dp, topEnd = 5.dp) 41 | ) { 42 | Column( 43 | horizontalAlignment = Alignment.CenterHorizontally 44 | ) { 45 | Spacer(Modifier.height(3.dp)) 46 | Canvas(Modifier.size(3.dp)) { 47 | drawCircle(Color.Black) 48 | } 49 | Spacer(Modifier.height(3.dp)) 50 | Box(Modifier.padding(horizontal = 9.dp)) { 51 | Card( 52 | border = BorderStroke(1.dp, Color.Black), 53 | backgroundColor = Color.Black, 54 | shape = RoundedCornerShape(1.dp), 55 | modifier = Modifier 56 | .fillMaxWidth() 57 | .aspectRatio(1.77F) // 16:9 display ratio 58 | ) { 59 | screenContent.invoke() 60 | } 61 | } 62 | Spacer(Modifier.height(10.dp)) 63 | } 64 | } 65 | 66 | Surface( 67 | modifier = Modifier 68 | .fillMaxWidth() 69 | .aspectRatio(8.5f), 70 | shape = RoundedCornerShape(bottomStart = 5.dp, bottomEnd = 5.dp), 71 | color = macColor) {} 72 | 73 | Canvas(modifier = Modifier 74 | .width(80.dp) 75 | .aspectRatio(1.7f)) { 76 | drawRect( 77 | brush = Brush.verticalGradient(listOf(macGradientDark, macGradientLight)), 78 | size = size 79 | ) 80 | } 81 | Surface( 82 | color = macLight, 83 | modifier = Modifier.height(1.dp).width(80.dp)) {} 84 | Surface( 85 | color = macXtraDark, 86 | modifier = Modifier.height(0.5.dp).width(80.dp)) {} 87 | Surface( 88 | color = macColor, 89 | modifier = Modifier.height(4.dp).width(84.dp)) {} 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/screens/Parallax.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.screens 2 | 3 | import android.view.MotionEvent 4 | import androidx.compose.animation.AnimatedVisibility 5 | import androidx.compose.animation.ExperimentalAnimationApi 6 | import androidx.compose.animation.core.animateFloatAsState 7 | import androidx.compose.foundation.Image 8 | import androidx.compose.foundation.background 9 | import androidx.compose.foundation.layout.* 10 | import androidx.compose.foundation.shape.CircleShape 11 | import androidx.compose.foundation.shape.RoundedCornerShape 12 | import androidx.compose.material.* 13 | import androidx.compose.runtime.* 14 | import androidx.compose.ui.Alignment 15 | import androidx.compose.ui.ExperimentalComposeUiApi 16 | import androidx.compose.ui.Modifier 17 | import androidx.compose.ui.draw.alpha 18 | import androidx.compose.ui.geometry.Size 19 | import androidx.compose.ui.graphics.Color 20 | import androidx.compose.ui.graphics.TransformOrigin 21 | import androidx.compose.ui.graphics.graphicsLayer 22 | import androidx.compose.ui.graphics.vector.ImageVector 23 | import androidx.compose.ui.input.pointer.pointerInteropFilter 24 | import androidx.compose.ui.layout.onGloballyPositioned 25 | import androidx.compose.ui.res.vectorResource 26 | import androidx.compose.ui.text.font.FontFamily 27 | import androidx.compose.ui.tooling.preview.Preview 28 | import androidx.compose.ui.unit.dp 29 | import androidx.compose.ui.unit.sp 30 | import com.prafullm.jetcomposer.R 31 | import com.prafullm.jetcomposer.ui.theme.droidGreen 32 | import kotlin.math.atan 33 | import kotlin.math.tan 34 | 35 | const val maxAngle = 50f 36 | val maxTranslation = 140.dp.value 37 | 38 | @ExperimentalAnimationApi 39 | @ExperimentalComposeUiApi 40 | @Preview 41 | @Composable 42 | fun Parallax() { 43 | 44 | var angle by remember { mutableStateOf(Pair(0f, 0f)) } 45 | var start by remember { mutableStateOf(Pair(-1f, -1f)) } 46 | var viewSize by remember { mutableStateOf(Size.Zero) } 47 | 48 | Column( 49 | horizontalAlignment = Alignment.CenterHorizontally, 50 | modifier = Modifier 51 | .fillMaxSize() 52 | .background(Color.DarkGray) 53 | .onGloballyPositioned { coordinates -> 54 | viewSize = Size( 55 | width = coordinates.size.width.toFloat(), 56 | height = coordinates.size.height.toFloat() 57 | ) 58 | } 59 | .pointerInteropFilter { m -> 60 | when (m.action) { 61 | MotionEvent.ACTION_UP -> { 62 | start = Pair(-1f, -1f) 63 | } 64 | MotionEvent.ACTION_DOWN -> { 65 | start = Pair(m.rawX, m.rawY) 66 | } 67 | MotionEvent.ACTION_MOVE -> { 68 | if (viewSize != Size.Zero) { 69 | val end = Pair(m.rawX, m.rawY) 70 | val newAngle = getRotationAngles(start, end, viewSize) 71 | var x: Float = angle.first + newAngle.first 72 | var y: Float = angle.second + newAngle.second 73 | 74 | if (x > maxAngle) x = maxAngle 75 | else if (x < -maxAngle) x = -maxAngle 76 | 77 | if (y > maxAngle) y = maxAngle 78 | else if (y < -maxAngle) y = -maxAngle 79 | 80 | angle = Pair(x, y) 81 | start = end 82 | } 83 | } 84 | } 85 | true 86 | } 87 | ) { 88 | Box( 89 | contentAlignment = Alignment.Center, 90 | modifier = Modifier 91 | .weight(1f) 92 | .size(250.dp) 93 | ) { 94 | Card( 95 | shape = RoundedCornerShape(12.dp), 96 | backgroundColor = Color.White, 97 | elevation = 0.dp, 98 | modifier = Modifier 99 | .graphicsLayer( 100 | transformOrigin = TransformOrigin(0.5f, 0.5f), 101 | rotationY = animateFloatAsState(-angle.first).value, 102 | rotationX = animateFloatAsState(angle.second).value, 103 | cameraDistance = 16.dp.value 104 | ) 105 | .width(300.dp) 106 | .aspectRatio(1f) 107 | ) { 108 | Image( 109 | imageVector = ImageVector.vectorResource(id = R.drawable.parallax_n_back), 110 | contentDescription = "Parallax Background", 111 | modifier = Modifier.fillMaxSize() 112 | ) 113 | Box(contentAlignment = Alignment.BottomStart) { 114 | Text( 115 | text = " Made with Jetpack Compose", 116 | color = Color.White, 117 | fontSize = 9.sp, 118 | fontFamily = FontFamily.Monospace, 119 | modifier = Modifier 120 | .alpha(0.8f) 121 | .padding(start = 12.dp, bottom = 13.dp) 122 | ) 123 | } 124 | } 125 | 126 | Box( 127 | modifier = Modifier 128 | .graphicsLayer( 129 | transformOrigin = TransformOrigin(0.5f, 0.5f), 130 | rotationY = animateFloatAsState(-angle.first).value, 131 | rotationX = animateFloatAsState(angle.second).value, 132 | cameraDistance = 16.dp.value, 133 | translationX = -getTranslation(angle.first, maxTranslation), 134 | translationY = -getTranslation(angle.second, maxTranslation) 135 | ) 136 | .size(250.dp) 137 | .align(Alignment.Center) 138 | ){ 139 | Image(imageVector = ImageVector.vectorResource(id = R.drawable.parallax_n_front), contentDescription = "Parallax Background") 140 | } 141 | 142 | } 143 | } 144 | } 145 | 146 | /** 147 | * This method converts the current touch input to rotation values based on the original point 148 | * at which the touch event started. 149 | * 150 | * @param start : coordinates of first touch event 151 | * @param end : coordinates of final touch event 152 | */ 153 | fun getRotationAngles( 154 | start: Pair, 155 | end: Pair, 156 | size: Size 157 | ): Pair { 158 | /** 159 | * 1. get the magnitude of drag event, based on screen's width & height & acceleration 160 | * 2. get the direction/angle of the drag event 161 | */ 162 | val acceleration = 3 163 | val distances = getDistances(end, start) 164 | val rotationX = (distances.first / size.width) * maxAngle * acceleration 165 | val rotationY = (distances.second / size.height) * maxAngle * acceleration 166 | return Pair(rotationX, rotationY) 167 | } 168 | 169 | fun getDistances(p1: Pair, p2: Pair): Pair { 170 | return Pair( 171 | p2.first - p1.first, 172 | p2.second - p1.second 173 | ) 174 | } 175 | 176 | fun getTranslation(angle: Float, maxDistance: Float): Float { 177 | return (angle/90f) * maxDistance 178 | } 179 | 180 | -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/screens/Static.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.screens 2 | 3 | import android.view.Choreographer 4 | import androidx.compose.foundation.Canvas 5 | import androidx.compose.foundation.background 6 | import androidx.compose.foundation.layout.* 7 | import androidx.compose.foundation.shape.CircleShape 8 | import androidx.compose.foundation.shape.RoundedCornerShape 9 | import androidx.compose.material.* 10 | import androidx.compose.runtime.* 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.geometry.CornerRadius 14 | import androidx.compose.ui.geometry.Offset 15 | import androidx.compose.ui.geometry.Size 16 | import androidx.compose.ui.graphics.Brush 17 | import androidx.compose.ui.graphics.Color 18 | import androidx.compose.ui.graphics.vector.ImageVector 19 | import androidx.compose.ui.platform.LocalDensity 20 | import androidx.compose.ui.res.vectorResource 21 | import androidx.compose.ui.tooling.preview.Preview 22 | import androidx.compose.ui.unit.dp 23 | import com.prafullm.jetcomposer.R 24 | import com.prafullm.jetcomposer.ui.theme.Black950 25 | import kotlinx.coroutines.delay 26 | import kotlin.random.Random 27 | 28 | val staticColors = listOf( 29 | Color.Black, 30 | Color.White, 31 | Color.Gray, 32 | Color.LightGray, 33 | Color.DarkGray 34 | ) 35 | 36 | @Preview 37 | @Composable 38 | fun Television() { 39 | var isSwitchedOn by remember { mutableStateOf(false) } 40 | var isScreenOn by remember { mutableStateOf(false) } 41 | 42 | Column( 43 | modifier = Modifier 44 | .fillMaxSize() 45 | .background(Color.DarkGray), 46 | horizontalAlignment = Alignment.CenterHorizontally, 47 | ) { 48 | Spacer(Modifier.weight(1f)) 49 | Card( 50 | elevation = 8.dp, 51 | shape = RoundedCornerShape(2.dp), 52 | backgroundColor = Color.Black, 53 | modifier = Modifier 54 | .width(300.dp) 55 | .aspectRatio(1.77f) 56 | ) { 57 | Column( 58 | Modifier 59 | .padding(top = 5.dp, start = 5.dp, end = 5.dp) 60 | .fillMaxSize()) { 61 | Card( 62 | elevation = 0.dp, 63 | shape = RoundedCornerShape(1.dp), 64 | backgroundColor = Color.Black, 65 | modifier = Modifier 66 | .fillMaxWidth() 67 | .weight(1f) 68 | ){ 69 | if(isSwitchedOn) { 70 | LaunchedEffect(isSwitchedOn) { 71 | delay(500) 72 | isScreenOn = true 73 | } 74 | } else { 75 | isScreenOn = false 76 | } 77 | if(isScreenOn) StaticCanvas() 78 | else Surface(color = Black950, modifier = Modifier.fillMaxSize()) {} 79 | } 80 | 81 | Box( 82 | modifier = Modifier 83 | .height(5.dp) 84 | .fillMaxWidth() 85 | .padding(end = 4.dp), 86 | contentAlignment = Alignment.CenterEnd 87 | ){ 88 | Surface( 89 | shape = CircleShape, 90 | modifier = Modifier.size(2.dp), 91 | color = if(isSwitchedOn) Color.Green else Color.Red 92 | ) {} 93 | } 94 | } 95 | } 96 | Box() { 97 | Canvas(modifier = Modifier.size(20.dp, 24.dp)) { 98 | drawRect( 99 | brush = Brush.verticalGradient( 100 | listOf(Color.LightGray, Color.White, Color.White)), 101 | size = size 102 | ) 103 | } 104 | Canvas(modifier = Modifier.size(20.dp, 24.dp)) { 105 | drawRect( 106 | brush = Brush.horizontalGradient( 107 | listOf(Color.LightGray, Color.Transparent, Color.LightGray)), 108 | size = size 109 | ) 110 | } 111 | } 112 | Canvas(modifier = Modifier.size(150.dp, 4.dp)) { 113 | drawRoundRect( 114 | cornerRadius = CornerRadius(2.dp.toPx(), 2.dp.toPx()), 115 | brush = Brush.verticalGradient( 116 | listOf(Color.White, Color.LightGray)), 117 | size = size 118 | ) 119 | } 120 | Spacer(Modifier.weight(1f)) 121 | Button( 122 | enabled = true, 123 | onClick = { isSwitchedOn = !isSwitchedOn }, 124 | shape = CircleShape, 125 | elevation = ButtonDefaults.elevation( 126 | defaultElevation = 8.dp, 127 | pressedElevation = 0.dp 128 | ), 129 | colors = ButtonDefaults.buttonColors( 130 | backgroundColor = Color.Red, 131 | contentColor = Color.White 132 | ), 133 | modifier = Modifier.align(Alignment.CenterHorizontally) 134 | ) { 135 | Icon( 136 | imageVector = ImageVector.vectorResource(id = R.drawable.ic_round_power_settings_new_24), 137 | contentDescription = null, 138 | modifier = Modifier.padding(0.dp) 139 | ) 140 | } 141 | Spacer(modifier = Modifier.height(16.dp)) 142 | } 143 | } 144 | 145 | @Composable 146 | fun StaticCanvas() { 147 | var isRunning by remember { mutableStateOf(true) } 148 | val pixelSize = with(LocalDensity.current) { 3.dp.toPx() } 149 | var canvasMeasured by remember { mutableStateOf(false) } 150 | var tableSize by remember { mutableStateOf(Size.Zero) } 151 | var pixels by remember { mutableStateOf(listOf()) } 152 | 153 | Canvas(modifier = Modifier.fillMaxSize()) { 154 | 155 | if(!canvasMeasured) { 156 | canvasMeasured = true 157 | tableSize = Size((size.width/pixelSize)+1, (size.height/pixelSize)+1) 158 | } 159 | 160 | if(pixels.isNotEmpty()) { 161 | val numberOfColumns = tableSize.width.toInt() 162 | val numberOfRows = tableSize.height.toInt() 163 | var current = 0 164 | 165 | for(col in 0 until numberOfColumns) { 166 | for(row in 0 until numberOfRows) { 167 | drawRect( 168 | color = pixels[current], 169 | topLeft = Offset( 170 | x = col * pixelSize, 171 | y= row * pixelSize 172 | ), 173 | size = Size(pixelSize, pixelSize) 174 | ) 175 | current++ 176 | } 177 | } 178 | } 179 | } 180 | 181 | val frameCallback = object : Choreographer.FrameCallback { 182 | override fun doFrame(frameTimeNanos: Long) { 183 | if(tableSize != Size.Zero) { 184 | pixels = generatePixelColors(tableSize.width.toInt(), tableSize.height.toInt()) 185 | } 186 | if(isRunning) Choreographer.getInstance().postFrameCallback(this) 187 | } 188 | } 189 | Choreographer.getInstance().postFrameCallback(frameCallback) 190 | 191 | /** 192 | * to clear up the frame callback 193 | */ 194 | DisposableEffect(true) { 195 | onDispose { 196 | isRunning = false 197 | Choreographer.getInstance().removeFrameCallback(frameCallback) 198 | } 199 | } 200 | } 201 | 202 | private fun generatePixelColors(width: Int, height: Int): List { 203 | val pixels = mutableListOf() 204 | for(i in 0 until (width * height)) { 205 | pixels.add(staticColors[Random.nextInt(0, staticColors.size)]) 206 | } 207 | return pixels 208 | } 209 | 210 | -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/screens/TrackPad.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.screens 2 | 3 | import android.view.MotionEvent 4 | import androidx.compose.animation.AnimatedVisibility 5 | import androidx.compose.animation.ExperimentalAnimationApi 6 | import androidx.compose.animation.animateColorAsState 7 | import androidx.compose.foundation.Image 8 | import androidx.compose.foundation.background 9 | import androidx.compose.foundation.layout.* 10 | import androidx.compose.foundation.shape.RoundedCornerShape 11 | import androidx.compose.material.Button 12 | import androidx.compose.material.ButtonDefaults 13 | import androidx.compose.material.Card 14 | import androidx.compose.material.Text 15 | import androidx.compose.runtime.* 16 | import androidx.compose.ui.Alignment 17 | import androidx.compose.ui.ExperimentalComposeUiApi 18 | import androidx.compose.ui.Modifier 19 | import androidx.compose.ui.geometry.Offset 20 | import androidx.compose.ui.geometry.Rect 21 | import androidx.compose.ui.graphics.Color 22 | import androidx.compose.ui.graphics.vector.ImageVector 23 | import androidx.compose.ui.input.pointer.pointerInteropFilter 24 | import androidx.compose.ui.layout.LayoutCoordinates 25 | import androidx.compose.ui.layout.boundsInParent 26 | import androidx.compose.ui.layout.onGloballyPositioned 27 | import androidx.compose.ui.platform.LocalDensity 28 | import androidx.compose.ui.res.vectorResource 29 | import androidx.compose.ui.tooling.preview.Preview 30 | import androidx.compose.ui.unit.dp 31 | import androidx.compose.ui.unit.sp 32 | import com.prafullm.jetcomposer.R 33 | import com.prafullm.jetcomposer.ui.theme.darkBlue 34 | import com.prafullm.jetcomposer.ui.theme.lightBlue 35 | import kotlin.math.max 36 | 37 | @ExperimentalAnimationApi 38 | @ExperimentalComposeUiApi 39 | @Preview 40 | @Composable 41 | fun TrackPad() { 42 | var coordinate by remember { mutableStateOf(Offset(10f, 10f)) } 43 | var buttonBounds by remember { mutableStateOf(Rect(Offset.Zero, Offset.Zero)) } 44 | var isAboveButton by remember { mutableStateOf(false) } 45 | var isButtonTapped by remember { mutableStateOf(false) } 46 | 47 | val backgroundColor = animateColorAsState(targetValue = if(isButtonTapped) lightBlue else Color.White) 48 | var downStartTime = 0L 49 | 50 | Column( 51 | Modifier 52 | .fillMaxSize() 53 | .background(Color.White) 54 | .padding(16.dp)) { 55 | Card( 56 | backgroundColor = backgroundColor.value, 57 | modifier = Modifier 58 | .weight(1f) 59 | .fillMaxWidth(), 60 | elevation = 3.dp, 61 | shape = RoundedCornerShape(5) 62 | ) { 63 | Box(contentAlignment = Alignment.Center) { 64 | Button( 65 | onClick = { }, 66 | shape = RoundedCornerShape(50), 67 | elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp), 68 | colors = ButtonDefaults.buttonColors( 69 | backgroundColor = darkBlue, 70 | contentColor = Color.White 71 | ), 72 | contentPadding = PaddingValues(horizontal = 16.dp), 73 | modifier = Modifier.onGloballyPositioned { c: LayoutCoordinates-> 74 | buttonBounds = c.boundsInParent() 75 | } 76 | ){ 77 | Row(){ 78 | AnimatedVisibility(visible = !isButtonTapped) { 79 | Text( 80 | text = "Tap", 81 | color = Color.White, 82 | fontSize = 15.sp 83 | ) 84 | } 85 | AnimatedVisibility(visible = isButtonTapped) { 86 | Text( 87 | text = "Tapped!", 88 | color = Color.White, 89 | fontSize = 15.sp 90 | ) 91 | } 92 | } 93 | } 94 | Box(modifier = Modifier.fillMaxSize()) { 95 | Box( 96 | modifier = Modifier 97 | .size(24.dp) 98 | .offset( 99 | with(LocalDensity.current) { coordinate.x.toDp() }, 100 | with(LocalDensity.current) { coordinate.y.toDp() } 101 | ) 102 | ) { 103 | Image( 104 | imageVector = ImageVector.vectorResource(if(!isAboveButton) R.drawable.ic_cursor else R.drawable.ic_pointing_hand), 105 | contentDescription = null, 106 | modifier = Modifier 107 | .fillMaxSize(), 108 | ) 109 | } 110 | } 111 | 112 | } 113 | } 114 | Spacer(modifier = Modifier.height(16.dp)) 115 | Card( 116 | backgroundColor = Color.LightGray, 117 | modifier = Modifier 118 | .weight(1f) 119 | .fillMaxWidth() 120 | .pointerInteropFilter { m -> 121 | when (m.action) { 122 | MotionEvent.ACTION_UP -> { 123 | if (System.currentTimeMillis() - downStartTime < 200L) { 124 | if (isAboveButton) isButtonTapped = !isButtonTapped 125 | } 126 | } 127 | MotionEvent.ACTION_DOWN -> { 128 | downStartTime = System.currentTimeMillis() 129 | } 130 | MotionEvent.ACTION_MOVE -> { 131 | val eventOffset = Offset(max(0f, m.x), max(0f, m.y)) 132 | coordinate = eventOffset 133 | isAboveButton = buttonBounds.contains(eventOffset) 134 | } 135 | } 136 | true 137 | }, 138 | elevation = 2.dp, 139 | shape = RoundedCornerShape(5) 140 | ) {} 141 | } 142 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.ui.theme 2 | 3 | import androidx.compose.ui.graphics.Color 4 | 5 | val droidGreen = Color(0xFF3ddd86) 6 | val lightBlue = Color(0xFFCAE3FF) 7 | val darkBlue = Color(0xFF006ee6) 8 | 9 | val White = Color(0xFFFFFFFF) 10 | val Black50 = Color(0xFFf6f6f6) 11 | val Black70 = Color(0xFFEEEEEE) 12 | val Black90 = Color(0xFFE9E9E9) 13 | val Black100 = Color(0xFFDDDDDD) 14 | val Black200 = Color(0xFFCCCCCC) 15 | val Black300 = Color(0xFF666666) 16 | val Black500 = Color(0xFF444444) 17 | val Black700 = Color(0xFF424242) 18 | val Black900 = Color(0xFF212121) 19 | val Black950 = Color(0xFF181818) 20 | val Black = Color(0xFF000000) -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/ui/theme/Shape.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.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/prafullm/jetcomposer/ui/theme/Theme.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.ui.theme 2 | 3 | import android.annotation.SuppressLint 4 | import androidx.compose.foundation.isSystemInDarkTheme 5 | import androidx.compose.material.MaterialTheme 6 | import androidx.compose.material.darkColors 7 | import androidx.compose.material.lightColors 8 | import androidx.compose.runtime.Composable 9 | 10 | @SuppressLint("ConflictingOnColor") 11 | private val LightColorPalette = darkColors( 12 | primary = White, 13 | primaryVariant = Black50, 14 | secondary = Black300, 15 | background = Black50, 16 | surface = White, 17 | onSurface = Black, 18 | onBackground = Black 19 | ) 20 | 21 | @SuppressLint("ConflictingOnColor") 22 | private val DarkColorPalette = lightColors( 23 | primary = Black700, 24 | primaryVariant = Black500, 25 | secondary = Black100, 26 | background = Black, 27 | surface = Black900, 28 | onSurface = Black50, 29 | onBackground = Black70 30 | ) 31 | 32 | @Composable 33 | fun JetComposerTheme( 34 | darkTheme: Boolean = isSystemInDarkTheme(), 35 | content: @Composable() () -> Unit 36 | ) { 37 | val colors = if (darkTheme) { 38 | DarkColorPalette 39 | } else LightColorPalette 40 | 41 | MaterialTheme( 42 | colors = colors, 43 | typography = Typography, 44 | shapes = Shapes, 45 | content = content 46 | ) 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/prafullm/jetcomposer/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.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/prafullm/jetcomposer/utils/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.prafullm.jetcomposer.utils 2 | 3 | import android.animation.ArgbEvaluator 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.graphics.Color 6 | import androidx.compose.ui.graphics.toArgb 7 | import androidx.navigation.NavBackStackEntry 8 | import androidx.navigation.NavDeepLink 9 | import androidx.navigation.NavGraphBuilder 10 | import androidx.navigation.compose.NamedNavArgument 11 | import androidx.navigation.compose.composable 12 | import com.prafullm.jetcomposer.model.Destination 13 | 14 | /* 15 | * Utility wrapper ext function for NavGraphBuilder.compose() 16 | */ 17 | fun NavGraphBuilder.composable( 18 | route: Destination, 19 | arguments: List = emptyList(), 20 | deepLinks: List = emptyList(), 21 | content: @Composable (NavBackStackEntry) -> Unit 22 | ) { 23 | composable(route.destinationName, arguments, deepLinks, content) 24 | } 25 | 26 | fun getColorAtProgress(progress: Float, start: Color, end: Color, evaluator: ArgbEvaluator): Color { 27 | return Color(evaluator.evaluate(progress, start.toArgb(), end.toArgb()) as Int) 28 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_cursor.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_image.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 11 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 6 | 8 | 9 | 11 | 14 | 17 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 15 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_mic.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 11 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_phone.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pointing_hand.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_360_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_android_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_chevron_right_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_nightlight_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_photo_camera_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_power_settings_new_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_wb_sunny_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_west_24.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_video.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/parallax_n_back.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 17 | 22 | 27 | 32 | 37 | 42 | 47 | 52 | 57 | 62 | 65 | 66 | 68 | 73 | 78 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/parallax_n_front.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 52 | 54 | 55 | 56 | 57 | 59 | 60 | 61 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /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/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prafullmishra/JetComposer/5df647c76919e7b1eba2707cd4d0e1738819dae4/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 | JetComposer 3 | 4 | Television Static 5 | The good\'ol 90s 6 | Parallax Effect 7 | Interact in 3D space 8 | Composed iMac 9 | Because why not? 10 | Trackpad 11 | View that mirrors gestures 12 | Instagram Chat 13 | Color shifting messages 14 | 15 | Message… 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 19 | 23 | 24 |