diff --git a/app/src/main/java/com/example/androiddevchallenge/BottomNavType.kt b/app/src/main/java/com/example/androiddevchallenge/BottomNavType.kt new file mode 100644 index 0000000..7231d3e --- /dev/null +++ b/app/src/main/java/com/example/androiddevchallenge/BottomNavType.kt @@ -0,0 +1,7 @@ +package com.example.androiddevchallenge + +enum class BottomNavType { + HOME, + PLAY, + PROFILE, +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androiddevchallenge/HomeScreen.kt b/app/src/main/java/com/example/androiddevchallenge/HomeScreen.kt index 4518a24..ebc6871 100644 --- a/app/src/main/java/com/example/androiddevchallenge/HomeScreen.kt +++ b/app/src/main/java/com/example/androiddevchallenge/HomeScreen.kt @@ -1,11 +1,14 @@ package com.example.androiddevchallenge import androidx.compose.animation.Crossfade +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -14,54 +17,153 @@ import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.BottomNavigation +import androidx.compose.material.BottomNavigationItem import androidx.compose.material.Divider +import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Scaffold +import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.TextField import androidx.compose.material.TextFieldDefaults import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Search +import androidx.compose.material.icons.outlined.Home +import androidx.compose.material.icons.outlined.Person +import androidx.compose.material.icons.outlined.PlayArrow import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import com.example.androiddevchallenge.data.DemoDataProvider +import com.example.androiddevchallenge.ui.PlayScreen +import com.example.androiddevchallenge.ui.ProfileScreen import com.example.androiddevchallenge.ui.common.HorizontalListItem import com.example.androiddevchallenge.ui.list.InstagramStories import com.example.androiddevchallenge.ui.theme.AppThemeState import kotlinx.coroutines.delay import kotlinx.coroutines.launch +@ExperimentalMaterialApi @ExperimentalComposeUiApi @Composable -fun HomeOnboard(value: AppThemeState, navController: NavHostController) { - var loggedIn by remember { mutableStateOf(false) } - val coroutineScope = rememberCoroutineScope() - Crossfade(targetState = loggedIn) { - - HomeScreen(value) { - coroutineScope.launch { - delay(2000) - loggedIn = true +fun HomeOnboard(appThemeState: MutableState, navController: NavHostController) { + + //Default home screen state is always HOME + val homeScreenState = rememberSaveable { mutableStateOf(BottomNavType.HOME) } + val bottomNavBarContentDescription = stringResource(id = R.string.navigation_bar) + + Column { + HomeScreenContent( + homeScreen = homeScreenState.value, + appThemeState = appThemeState, + modifier = Modifier.weight(1f) + ) + BottomNavigationContent( + modifier = Modifier + .semantics { contentDescription = bottomNavBarContentDescription } + .testTag("bottom_navigation_bar"), + homeScreenState = homeScreenState + ) + } + +} + +@Composable +fun BottomNavigationContent( + modifier: Modifier = Modifier, + homeScreenState: MutableState +) { + var animate by remember { mutableStateOf(false) } + BottomNavigation(modifier = modifier) { + BottomNavigationItem( + icon = { Icon(imageVector = Icons.Outlined.Home, contentDescription = null) }, + selected = homeScreenState.value == BottomNavType.HOME, + onClick = { + homeScreenState.value = BottomNavType.HOME + animate = false + }, + label = { Text(text = stringResource(id = R.string.home).toUpperCase()) }, + ) + BottomNavigationItem( + icon = { Icon(imageVector = Icons.Outlined.PlayArrow, contentDescription = null) }, + selected = homeScreenState.value == BottomNavType.PLAY, + onClick = { + homeScreenState.value = BottomNavType.PLAY + animate = true + }, + label = { Text(text = stringResource(id = R.string.play)) } + ) + BottomNavigationItem( + icon = { Icon(imageVector = Icons.Outlined.Person, contentDescription = null) }, + selected = homeScreenState.value == BottomNavType.PROFILE, + onClick = { + homeScreenState.value = BottomNavType.PROFILE + animate = false + }, + label = { Text(text = stringResource(id = R.string.profile)) } + ) + + } +} + +@ExperimentalComposeUiApi +@ExperimentalMaterialApi +@Composable +fun HomeScreenContent( + homeScreen: BottomNavType, + appThemeState: MutableState, + modifier: Modifier +) { + Column(modifier = modifier) { + Crossfade(homeScreen) { screen -> + Surface(color = MaterialTheme.colors.background) { + when (screen) { + BottomNavType.HOME -> { + var loggedIn by remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope() + HomeScreen(appThemeState.value) { + coroutineScope.launch { + delay(2000) + loggedIn = true + } + } + } + BottomNavType.PLAY -> PlayScreen(appThemeState.value) + BottomNavType.PROFILE -> ProfileScreen(appThemeState.value) + + + } } } } } + @ExperimentalComposeUiApi @Composable fun HomeScreen(value: AppThemeState, onLoginSuccess: () -> Unit) { @@ -76,17 +178,22 @@ fun HomeScreen(value: AppThemeState, onLoginSuccess: () -> Unit) { .fillMaxHeight() .padding(vertical = 16.dp), horizontalAlignment = Alignment.CenterHorizontally, - ) { + ) { item { searchBar() - itemTitle(Modifier.height(40.dp), LocalContext.current.getString(R.string.favorite_collection).toUpperCase()) + itemTitle( + Modifier.height(40.dp), + LocalContext.current.getString(R.string.favorite_collection).toUpperCase() + ) horizontalListView() horizontalListView() - itemTitle(Modifier.height(40.dp), + itemTitle( + Modifier.height(40.dp), LocalContext.current.getString(R.string.align_body).toUpperCase(), ) InstagramStories() - itemTitle(Modifier.height(40.dp), + itemTitle( + Modifier.height(40.dp), LocalContext.current.getString(R.string.align_mind).toUpperCase() ) InstagramStories() @@ -99,9 +206,11 @@ fun HomeScreen(value: AppThemeState, onLoginSuccess: () -> Unit) { @Composable fun itemTitle(modifier: Modifier, title: String) { - Row(modifier = modifier.fillMaxWidth(), - verticalAlignment = Alignment.Bottom, - horizontalArrangement = Arrangement.Start){ + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.Start + ) { Text( text = title, style = MaterialTheme.typography.h2, @@ -114,18 +223,18 @@ fun itemTitle(modifier: Modifier, title: String) { @Composable fun horizontalListView() { val list = remember { DemoDataProvider.itemList } - LazyRow( - modifier = Modifier.padding(end = 16.dp) - ) { - items( - items = list, - itemContent = { - HorizontalListItem( - it, - Modifier.padding(start = 16.dp, bottom = 16.dp) - ) - }) - } + LazyRow( + modifier = Modifier.padding(end = 16.dp) + ) { + items( + items = list, + itemContent = { + HorizontalListItem( + it, + Modifier.padding(start = 16.dp, bottom = 16.dp) + ) + }) + } } @@ -145,8 +254,7 @@ fun searchBar() { TextField( modifier = Modifier .fillMaxWidth(.9f) - .padding(top = 56.dp) - , + .padding(top = 56.dp), value = query, onValueChange = { query = it }, label = { diff --git a/app/src/main/java/com/example/androiddevchallenge/MainActivity.kt b/app/src/main/java/com/example/androiddevchallenge/MainActivity.kt index c1e3632..ef3b684 100644 --- a/app/src/main/java/com/example/androiddevchallenge/MainActivity.kt +++ b/app/src/main/java/com/example/androiddevchallenge/MainActivity.kt @@ -21,6 +21,7 @@ import android.view.View import android.view.WindowManager import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity +import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.runtime.Composable @@ -40,6 +41,7 @@ import com.example.androiddevchallenge.ui.theme.SystemUiController @ExperimentalComposeUiApi class MainActivity : AppCompatActivity() { + @ExperimentalMaterialApi override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.apply { @@ -52,8 +54,6 @@ class MainActivity : AppCompatActivity() { setContent { val systemUiController = remember { SystemUiController(window) } val appTheme = remember { mutableStateOf(AppThemeState()) } - - val navController = rememberNavController() NavHost( @@ -62,7 +62,7 @@ class MainActivity : AppCompatActivity() { ) { composable(NavRoutes.HOME) { BaseView(appTheme.value, systemUiController, content = { - HomeOnboard(appTheme.value, navController = navController) + HomeOnboard(appTheme, navController = navController) }) } diff --git a/app/src/main/java/com/example/androiddevchallenge/ui/PlayScreen.kt b/app/src/main/java/com/example/androiddevchallenge/ui/PlayScreen.kt new file mode 100644 index 0000000..10e5842 --- /dev/null +++ b/app/src/main/java/com/example/androiddevchallenge/ui/PlayScreen.kt @@ -0,0 +1,60 @@ +package com.example.androiddevchallenge.ui + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.androiddevchallenge.R +import com.example.androiddevchallenge.ui.theme.AppThemeState + + +@Composable +fun PlayScreen(value: AppThemeState) { + Scaffold { + Box(modifier = Modifier.fillMaxHeight(), content = { + Image( + imageVector = ImageVector.vectorResource(id = if (value.darkTheme) R.drawable.dark_welcome else R.drawable.light_welcome), + contentDescription = "background", + modifier = Modifier.fillMaxSize(), + contentScale = ContentScale.FillBounds + ) + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + + ) { + item { + Text( + text = stringResource(id = R.string.play).toUpperCase(), + style = MaterialTheme.typography.h1, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) + } + } + }) + } +} diff --git a/app/src/main/java/com/example/androiddevchallenge/ui/ProfileScreen.kt b/app/src/main/java/com/example/androiddevchallenge/ui/ProfileScreen.kt new file mode 100644 index 0000000..f041394 --- /dev/null +++ b/app/src/main/java/com/example/androiddevchallenge/ui/ProfileScreen.kt @@ -0,0 +1,60 @@ +package com.example.androiddevchallenge.ui + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.example.androiddevchallenge.R +import com.example.androiddevchallenge.ui.theme.AppThemeState + + +@Composable +fun ProfileScreen(value: AppThemeState) { + Scaffold { + Box(modifier = Modifier.fillMaxHeight(), content = { + Image( + imageVector = ImageVector.vectorResource(id = if (value.darkTheme) R.drawable.dark_welcome else R.drawable.light_welcome), + contentDescription = "background", + modifier = Modifier.fillMaxSize(), + contentScale = ContentScale.FillBounds + ) + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .padding(horizontal = 16.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + + ) { + item { + Text( + text = stringResource(id = R.string.profile).toUpperCase(), + style = MaterialTheme.typography.h1, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) + } + } + }) + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 29a056e..5ed483a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -18,4 +18,8 @@ Favorite collection Align your body Align your mind + Bottom navigationBar + Home + Play + Profile \ No newline at end of file