Skip to content

Commit

Permalink
Merge pull request #66 from snuhcs-course/feat/symbol-selection
Browse files Browse the repository at this point in the history
�선택한 상징 목록 크게 보기 화면 구현
  • Loading branch information
89645321 authored Nov 25, 2023
2 parents c1a6069 + 43515db commit 2374014
Show file tree
Hide file tree
Showing 17 changed files with 441 additions and 158 deletions.
1 change: 1 addition & 0 deletions frontend/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.SpeechBuddy"
android:usesCleartextTraffic="true"
android:windowSoftInputMode="adjustResize"
tools:targetApi="31">
<activity
android:name=".HomeActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.view.MotionEvent
import android.view.inputmethod.InputMethodManager
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.core.view.WindowCompat
import com.example.speechbuddy.compose.SpeechBuddyAuth
import com.example.speechbuddy.ui.SpeechBuddyTheme
import com.example.speechbuddy.viewmodel.LoginViewModel
Expand All @@ -20,9 +19,6 @@ class AuthActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Displaying edge-to-edge
WindowCompat.setDecorFitsSystemWindows(window, false)

subscribeObservers()
checkPreviousAuthUser()

Expand Down Expand Up @@ -61,4 +57,5 @@ class AuthActivity : BaseActivity() {
}
return super.dispatchTouchEvent(event)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.os.Bundle
import android.view.MotionEvent
import android.view.inputmethod.InputMethodManager
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.annotation.RequiresApi
import androidx.core.view.WindowCompat
Expand All @@ -15,7 +16,6 @@ import com.example.speechbuddy.ui.SpeechBuddyTheme
import com.example.speechbuddy.viewmodel.DisplaySettingsViewModel
import dagger.hilt.android.AndroidEntryPoint


@AndroidEntryPoint
class HomeActivity : BaseActivity() {

Expand All @@ -25,8 +25,6 @@ class HomeActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)
// Displaying edge-to-edge
WindowCompat.setDecorFitsSystemWindows(window, false)

val isBeingReloadedForDarkModeChange = intent.getBooleanExtra("isBeingReloadedForDarkModeChange", false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package com.example.speechbuddy.compose

import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
Expand All @@ -15,6 +17,9 @@ import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -69,10 +74,12 @@ fun SpeechBuddyHome(
)
)

val bottomNavBarState = rememberSaveable { mutableStateOf(true) }

Scaffold(
modifier = Modifier.padding(bottom = 48.dp), // System Bar Padding
bottomBar = {
BottomNavigationBar(
bottomNavBarState = bottomNavBarState,
items = navItems,
navController = navController,
onItemClick = {
Expand All @@ -85,42 +92,53 @@ fun SpeechBuddyHome(
navController = navController,
bottomPaddingValues = paddingValues,
initialPage = initialPage,
showBottomNavBar = { bottomNavBarState.value = true },
hideBottomNavBar = { bottomNavBarState.value = false },
isBeingReloadedForDarkModeChange = isBeingReloadedForDarkModeChange
)
}
}

@Composable
private fun BottomNavigationBar(
bottomNavBarState: MutableState<Boolean>,
items: List<BottomNavItem>,
navController: NavController,
onItemClick: (BottomNavItem) -> Unit
) {
val backStackEntry = navController.currentBackStackEntryAsState()

NavigationBar(
modifier = Modifier.height(64.dp),
containerColor = MaterialTheme.colorScheme.secondaryContainer,
windowInsets = WindowInsets(top = 16.dp)
AnimatedVisibility(
visible = bottomNavBarState.value,
enter = slideInVertically(initialOffsetY = { it }),
exit = slideOutVertically(targetOffsetY = { it })
) {
items.forEach { item ->
val selected = item.route == backStackEntry.value?.destination?.route
NavigationBarItem(
selected = selected,
onClick = { onItemClick(item) },
icon = {
Icon(
painter = painterResource(id = item.iconResId),
contentDescription = stringResource(id = item.nameResId)
)
},
modifier = Modifier.size(32.dp),
colors = NavigationBarItemDefaults.colors(
selectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer,
unselectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer.copy(alpha = .5f)
),
interactionSource = NoRippleInteractionSource()
)
val backStackEntry = navController.currentBackStackEntryAsState()

NavigationBar(
modifier = Modifier.height(64.dp),
containerColor = MaterialTheme.colorScheme.secondaryContainer,
windowInsets = WindowInsets(top = 16.dp)
) {
items.forEach { item ->
val selected = item.route == backStackEntry.value?.destination?.route
NavigationBarItem(
selected = selected,
onClick = { onItemClick(item) },
icon = {
Icon(
painter = painterResource(id = item.iconResId),
contentDescription = stringResource(id = item.nameResId)
)
},
modifier = Modifier.size(32.dp),
colors = NavigationBarItemDefaults.colors(
selectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer,
unselectedIconColor = MaterialTheme.colorScheme.onSecondaryContainer.copy(
alpha = .5f
)
),
interactionSource = NoRippleInteractionSource()
)
}
}
}
}
Expand All @@ -131,21 +149,25 @@ private fun SpeechBuddyHomeNavHost(
navController: NavHostController,
bottomPaddingValues: PaddingValues,
initialPage: Boolean,
isBeingReloadedForDarkModeChange: Boolean
showBottomNavBar: () -> Unit,
hideBottomNavBar: () -> Unit,
isBeingReloadedForDarkModeChange: Boolean,
) {
val startDestination = if (isBeingReloadedForDarkModeChange) {
val startDestination =
if (isBeingReloadedForDarkModeChange) {
"settings"
} else if (initialPage) {
"symbol_selection"
} else {
"text_to_speech"
}


NavHost(navController = navController, startDestination = startDestination) {
composable("symbol_selection") {
SymbolSelectionScreen(
bottomPaddingValues = bottomPaddingValues
bottomPaddingValues = bottomPaddingValues,
showBottomNavBar = showBottomNavBar,
hideBottomNavBar = hideBottomNavBar
)
}
composable("text_to_speech") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ fun LoginScreen(
ButtonUi(
text = stringResource(id = R.string.signup),
onClick = onSignupClick,
modifier = Modifier.offset(y = 110.dp),
modifier = Modifier.offset(y = 152.dp),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package com.example.speechbuddy.compose.symbolselection

import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.content.pm.ActivityInfo
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.hilt.navigation.compose.hiltViewModel
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
import com.example.speechbuddy.R
import com.example.speechbuddy.compose.utils.ButtonLevel
import com.example.speechbuddy.compose.utils.ButtonUi
import com.example.speechbuddy.domain.models.Symbol
import com.example.speechbuddy.utils.Constants
import com.example.speechbuddy.viewmodel.SymbolSelectionViewModel

@Composable
fun DisplayMaxScreen(
onExit: () -> Unit,
viewModel: SymbolSelectionViewModel = hiltViewModel()
) {
LockScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

Surface(
modifier = Modifier
.fillMaxSize()
.zIndex(Float.MAX_VALUE),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
verticalArrangement = Arrangement.spacedBy(20.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.background(color = MaterialTheme.colorScheme.surface)
.border(
width = 1.dp,
color = MaterialTheme.colorScheme.surfaceVariant,
shape = RoundedCornerShape(24.dp)
)
) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.CenterStart
) {
LazyRow(
contentPadding = PaddingValues(20.dp),
horizontalArrangement = Arrangement.spacedBy(20.dp)
) {
items(viewModel.selectedSymbols) { symbolItem ->
DisplayMaxSymbolUi(
symbol = symbolItem.symbol
)
}
}
}
}

ButtonUi(
text = stringResource(id = R.string.exit),
onClick = onExit,
modifier = Modifier.widthIn(max = 312.dp),
level = ButtonLevel.QUINARY
)
}
}
}

@OptIn(ExperimentalGlideComposeApi::class)
@Composable
fun DisplayMaxSymbolUi(
symbol: Symbol
) {
val symbolImagePath =
if (symbol.id > Constants.DEFAULT_SYMBOL_COUNT)
LocalContext.current.filesDir.toString().plus("/") // needs to be modified
else
Constants.DEFAULT_SYMBOL_IMAGE_PATH

Card(
modifier = Modifier.size(160.dp),
shape = RoundedCornerShape(20.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.background
),
border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.onBackground)
) {
Box(contentAlignment = Alignment.TopEnd) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
GlideImage(
model = symbolImagePath.plus("symbol_${symbol.id}.png"),
contentDescription = symbol.text,
modifier = Modifier.height(104.dp),
contentScale = ContentScale.FillHeight
)

Box(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.background(color = MaterialTheme.colorScheme.secondaryContainer)
.padding(horizontal = 12.dp),
contentAlignment = Alignment.Center
) {
Text(
text = symbol.text,
textAlign = TextAlign.Center,
maxLines = Constants.MAXIMUM_LINES_FOR_SYMBOL_TEXT,
style = MaterialTheme.typography.bodyLarge
)
}
}
}
}
}

@Composable
fun LockScreenOrientation(orientation: Int) {
val context = LocalContext.current
DisposableEffect(orientation) {
val activity = context.findActivity() ?: return@DisposableEffect onDispose {}
val originalOrientation = activity.requestedOrientation
activity.requestedOrientation = orientation
onDispose {
// restore original orientation when view disappears
activity.requestedOrientation = originalOrientation
}
}
}

fun Context.findActivity(): Activity? = when (this) {
is Activity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}
Loading

0 comments on commit 2374014

Please sign in to comment.