implement show/hide header on scroll in LibraryScreen and prevent haptic feedback on re-selecting the current bottom bar item
This commit is contained in:
@@ -207,8 +207,10 @@ fun BottomNavigationBar(
|
|||||||
NavigationBarItem(
|
NavigationBarItem(
|
||||||
selected = isSelected,
|
selected = isSelected,
|
||||||
onClick = {
|
onClick = {
|
||||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
if (!isSelected) {
|
||||||
if (screen == Screen.More) showMoreMenu = true else onItemSelected(screen)
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
if (screen == Screen.More) showMoreMenu = true else onItemSelected(screen)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
label = if (showLabels) {
|
label = if (showLabels) {
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
@@ -315,6 +316,7 @@ fun AllCardsView(
|
|||||||
onItemClick: (VocabularyItem) -> Unit,
|
onItemClick: (VocabularyItem) -> Unit,
|
||||||
onItemLongClick: (VocabularyItem) -> Unit,
|
onItemLongClick: (VocabularyItem) -> Unit,
|
||||||
onDeleteClick: (VocabularyItem) -> Unit,
|
onDeleteClick: (VocabularyItem) -> Unit,
|
||||||
|
listState: LazyListState,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
if (vocabularyItems.isEmpty()) {
|
if (vocabularyItems.isEmpty()) {
|
||||||
@@ -340,6 +342,7 @@ fun AllCardsView(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
state = listState,
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(bottom = 100.dp)
|
contentPadding = PaddingValues(bottom = 100.dp)
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ package eu.gaudian.translator.view.library
|
|||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.expandVertically
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.shrinkVertically
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -42,6 +46,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -122,6 +127,10 @@ fun LibraryScreen(
|
|||||||
|
|
||||||
val vocabularyItems by vocabularyItemsFlow.collectAsStateWithLifecycle(initialValue = emptyList())
|
val vocabularyItems by vocabularyItemsFlow.collectAsStateWithLifecycle(initialValue = emptyList())
|
||||||
|
|
||||||
|
var isHeaderVisible by remember { mutableStateOf(true) }
|
||||||
|
var previousIndex by remember { mutableStateOf(0) }
|
||||||
|
var previousScrollOffset by remember { mutableStateOf(0) }
|
||||||
|
|
||||||
// Set navigation context when vocabulary items are loaded
|
// Set navigation context when vocabulary items are loaded
|
||||||
LaunchedEffect(vocabularyItems) {
|
LaunchedEffect(vocabularyItems) {
|
||||||
if (vocabularyItems.isNotEmpty()) {
|
if (vocabularyItems.isNotEmpty()) {
|
||||||
@@ -129,6 +138,24 @@ fun LibraryScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(isCategoriesView, isInSelectionMode) {
|
||||||
|
if (isCategoriesView || isInSelectionMode) {
|
||||||
|
isHeaderVisible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(lazyListState, isCategoriesView, isInSelectionMode) {
|
||||||
|
if (isCategoriesView || isInSelectionMode) return@LaunchedEffect
|
||||||
|
snapshotFlow { lazyListState.firstVisibleItemIndex to lazyListState.firstVisibleItemScrollOffset }
|
||||||
|
.collect { (index, offset) ->
|
||||||
|
val isScrollingDown = index > previousIndex || (index == previousIndex && offset > previousScrollOffset)
|
||||||
|
val isAtTop = index == 0 && offset <= 4
|
||||||
|
isHeaderVisible = if (isAtTop) true else !isScrollingDown
|
||||||
|
previousIndex = index
|
||||||
|
previousScrollOffset = offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.TopCenter
|
contentAlignment = Alignment.TopCenter
|
||||||
@@ -139,47 +166,55 @@ fun LibraryScreen(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(horizontal = 24.dp),
|
.padding(horizontal = 24.dp),
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
AnimatedVisibility(
|
||||||
|
visible = isHeaderVisible,
|
||||||
if (isInSelectionMode) {
|
enter = fadeIn() + expandVertically(),
|
||||||
SelectionTopBar(
|
exit = fadeOut() + shrinkVertically()
|
||||||
selectionCount = selection.size,
|
) {
|
||||||
onCloseClick = { selection = emptySet() },
|
Column {
|
||||||
onSelectAllClick = {
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
selection = if (selection.size == vocabularyItems.size) emptySet()
|
|
||||||
else vocabularyItems.map { it.id.toLong() }.toSet()
|
if (isInSelectionMode) {
|
||||||
},
|
SelectionTopBar(
|
||||||
onDeleteClick = {
|
selectionCount = selection.size,
|
||||||
vocabularyViewModel.deleteVocabularyItemsById(selection.map { it.toInt() })
|
onCloseClick = { selection = emptySet() },
|
||||||
selection = emptySet()
|
onSelectAllClick = {
|
||||||
},
|
selection = if (selection.size == vocabularyItems.size) emptySet()
|
||||||
onMoveToCategoryClick = { showCategoryDialog = true },
|
else vocabularyItems.map { it.id.toLong() }.toSet()
|
||||||
onMoveToStageClick = { showStageDialog = true },
|
},
|
||||||
isRemoveEnabled = false,
|
onDeleteClick = {
|
||||||
onRemoveFromCategoryClick = {}
|
vocabularyViewModel.deleteVocabularyItemsById(selection.map { it.toInt() })
|
||||||
)
|
selection = emptySet()
|
||||||
} else {
|
},
|
||||||
LibraryTopBar(
|
onMoveToCategoryClick = { showCategoryDialog = true },
|
||||||
onAddClick = { /* TODO: Add new card/category */ }
|
onMoveToStageClick = { showStageDialog = true },
|
||||||
)
|
isRemoveEnabled = false,
|
||||||
|
onRemoveFromCategoryClick = {}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LibraryTopBar(
|
||||||
|
onAddClick = { /* TODO: Add new card/category */ }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
SearchBar(
|
||||||
|
searchQuery = filterState.searchQuery,
|
||||||
|
onQueryChanged = { filterState = filterState.copy(searchQuery = it) },
|
||||||
|
onFilterClick = { showFilterSheet = true }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
SegmentedControl(
|
||||||
|
isCategoriesView = isCategoriesView,
|
||||||
|
onTabSelected = { isCategoriesView = it }
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
|
|
||||||
SearchBar(
|
|
||||||
searchQuery = filterState.searchQuery,
|
|
||||||
onQueryChanged = { filterState = filterState.copy(searchQuery = it) },
|
|
||||||
onFilterClick = { showFilterSheet = true }
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
|
|
||||||
SegmentedControl(
|
|
||||||
isCategoriesView = isCategoriesView,
|
|
||||||
onTabSelected = { isCategoriesView = it }
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
|
|
||||||
LibraryViewContainer(
|
LibraryViewContainer(
|
||||||
isCategoriesView = isCategoriesView,
|
isCategoriesView = isCategoriesView,
|
||||||
@@ -199,6 +234,7 @@ fun LibraryScreen(
|
|||||||
vocabularyItems = vocabularyItems,
|
vocabularyItems = vocabularyItems,
|
||||||
allLanguages = allLanguages,
|
allLanguages = allLanguages,
|
||||||
selection = selection,
|
selection = selection,
|
||||||
|
listState = lazyListState,
|
||||||
onItemClick = { item ->
|
onItemClick = { item ->
|
||||||
if (isInSelectionMode) {
|
if (isInSelectionMode) {
|
||||||
selection = if (selection.contains(item.id.toLong())) {
|
selection = if (selection.contains(item.id.toLong())) {
|
||||||
|
|||||||
@@ -268,6 +268,7 @@ fun NewVocListScreen(
|
|||||||
vocabularyItems = vocabularyItems,
|
vocabularyItems = vocabularyItems,
|
||||||
allLanguages = allLanguages,
|
allLanguages = allLanguages,
|
||||||
selection = selection,
|
selection = selection,
|
||||||
|
listState = lazyListState,
|
||||||
onItemClick = { item ->
|
onItemClick = { item ->
|
||||||
if (isInSelectionMode) {
|
if (isInSelectionMode) {
|
||||||
selection = if (selection.contains(item.id.toLong())) {
|
selection = if (selection.contains(item.id.toLong())) {
|
||||||
@@ -588,7 +589,8 @@ fun AllCardsView(
|
|||||||
selection: Set<Long>,
|
selection: Set<Long>,
|
||||||
onItemClick: (VocabularyItem) -> Unit,
|
onItemClick: (VocabularyItem) -> Unit,
|
||||||
onItemLongClick: (VocabularyItem) -> Unit,
|
onItemLongClick: (VocabularyItem) -> Unit,
|
||||||
onDeleteClick: (VocabularyItem) -> Unit
|
onDeleteClick: (VocabularyItem) -> Unit,
|
||||||
|
listState: androidx.compose.foundation.lazy.LazyListState
|
||||||
) {
|
) {
|
||||||
if (vocabularyItems.isEmpty()) {
|
if (vocabularyItems.isEmpty()) {
|
||||||
Column(
|
Column(
|
||||||
@@ -613,6 +615,7 @@ fun AllCardsView(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
|
state = listState,
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentPadding = PaddingValues(bottom = 100.dp)
|
contentPadding = PaddingValues(bottom = 100.dp)
|
||||||
|
|||||||
Reference in New Issue
Block a user