menu: лончер приложений → bottom-sheet на пол-экрана (v0.5.116/124)

F7AppMenuSheet был fillMaxSize с непрозрачным фоном (закрывал весь экран).
Теперь выезжает снизу и занимает ~пол-экрана: якорь BottomCenter,
fillMaxHeight(0.6f), скруглённый верх 20dp + тень, ручка-хендл, лёгкий
скрим над листом (тап закрывает), зазор под нижнюю панель, сетка иконок
скроллится. Экран под меню виден сверху. Бамп версии 0.5.115→0.5.116.
This commit is contained in:
b-dev-mobile
2026-07-08 12:14:36 +00:00
parent 8cee4d61bf
commit 530663754a
3 changed files with 78 additions and 33 deletions
+2
View File
@@ -2,6 +2,8 @@
Формат: `ГГГГ-ММ-ДД | версия | изменение | контракты | риск`
- 2026-07-08 | v0.5.116 (124) | Меню-лончер (сетка приложений) → bottom-sheet на пол-экрана (требование владельца «выходить снизу вверх только на пол экрана»). `F7AppMenuSheet` был `fillMaxSize` с непрозрачным фоном → закрывал весь экран. Теперь: якорь снизу (`Alignment.BottomCenter`), высота `fillMaxHeight(0.6f)`, скруглённый верх (20dp) + тень, ручка-хендл, лёгкий скрим (0.18) над листом с тапом-для-закрытия, зазор `BottomBarReserve` под нижнюю панель, сетка иконок скроллится (`weight(1f)`). Экран под меню теперь виден сверху. Компилируется | контракты не менялись | низкий: только оверлей меню
- 2026-07-08 | v0.5.115 (123) | Бамп версии под дизайн-веху (0.5.114→0.5.115, code 122→123, стиль проекта: патч +1 / code +1). До этого Этапы 0/1 + весь дизайн ошибочно шли одной WIP-линией 0.5.114 (122) — теперь ревью-сборки дизайна помечены отдельной версией. Дальше — бампить на каждую заметную веху/ревью-сборку | версионирование | нет: только versionCode/Name
- 2026-07-08 | v0.5.114 (122) | Дизайн Календаря (месячная сетка): по «Календарь · Месяц» — дни недели вынесены в серые пилюли; сетка стала безрамочной с тонкими гридлайнами (0.5dp Grey3) вместо скруглённых боксов; номер дня сверху-слева; сегодня — белое число в зелёном круге; событие — зелёная пилюля PrimaryLight (до 2 шт + «+N») вместо одного превью/точки. Компактная мобильная модель (месяц сверху + список событий выбранного дня снизу) сохранена — не десктопная таблица. `CalendarMonthGrid`/`CalendarDayCell`, убран неиспользуемый параметр daysWithEvents. Проверено сборкой | контракты не менялись | низкий: только вид месяца
+2 -2
View File
@@ -39,8 +39,8 @@ android {
applicationId 'ru.forbion.f7cloud.mobile'
minSdk 26
targetSdk 36
versionCode 123
versionName '0.5.115'
versionCode 124
versionName '0.5.116'
missingDimensionStrategy 'default', 'f7'
multiDexEnabled true
@@ -9,10 +9,12 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
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.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@@ -35,6 +37,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.layout.ContentScale
@@ -51,6 +54,10 @@ private val BottomBarReserve: Dp = 90.dp
private val MenuIconSize = 62.dp
private val MenuGridGap = 20.dp
// Меню-лист выезжает снизу и занимает ~пол-экрана (не весь), по требованию владельца
private const val MenuSheetHeightFraction = 0.6f
private val MenuSheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)
data class F7AppMenuItem(
val label: String,
val iconUrl: String,
@@ -78,41 +85,76 @@ fun F7AppMenuSheet(
}
val base = serverUrl.trimEnd('/')
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(250)) + slideInVertically(
animationSpec = tween(350),
initialOffsetY = { it },
),
exit = fadeOut(tween(200)) + slideOutVertically(
animationSpec = tween(300),
targetOffsetY = { it },
),
modifier = modifier,
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(bottom = BottomBarReserve)
.navigationBarsPadding()
.background(F7Colors.Background)
.padding(start = 16.dp, end = 16.dp, top = 16.dp, bottom = 8.dp),
Box(modifier = modifier.fillMaxSize()) {
// Затемнение над листом — тап закрывает меню (лист занимает только низ экрана)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(200)),
exit = fadeOut(tween(200)),
modifier = Modifier.fillMaxSize(),
) {
F7AppMenuSearchField(
serverUrl = base,
value = searchQuery,
onValueChange = { searchQuery = it },
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 0.18f))
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onDismiss,
),
)
}
// Сам лист — выезжает снизу вверх на ~пол-экрана, скруглённый верх + тень
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(250)) + slideInVertically(
animationSpec = tween(350),
initialOffsetY = { it },
),
exit = fadeOut(tween(200)) + slideOutVertically(
animationSpec = tween(300),
targetOffsetY = { it },
),
modifier = Modifier.align(Alignment.BottomCenter),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 24.dp),
)
LazyVerticalGrid(
columns = GridCells.Fixed(4),
horizontalArrangement = Arrangement.spacedBy(MenuGridGap),
verticalArrangement = Arrangement.spacedBy(MenuGridGap),
contentPadding = PaddingValues(horizontal = 2.dp),
modifier = Modifier.fillMaxSize(),
.fillMaxHeight(MenuSheetHeightFraction)
.padding(bottom = BottomBarReserve)
.navigationBarsPadding()
.shadow(16.dp, MenuSheetShape, clip = false)
.clip(MenuSheetShape)
.background(F7Colors.Background)
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
) {
// Ручка-хендл
Box(
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(top = 2.dp, bottom = 10.dp)
.width(40.dp)
.height(4.dp)
.clip(RoundedCornerShape(2.dp))
.background(F7Colors.Border),
)
F7AppMenuSearchField(
serverUrl = base,
value = searchQuery,
onValueChange = { searchQuery = it },
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 20.dp),
)
LazyVerticalGrid(
columns = GridCells.Fixed(4),
horizontalArrangement = Arrangement.spacedBy(MenuGridGap),
verticalArrangement = Arrangement.spacedBy(MenuGridGap),
contentPadding = PaddingValues(horizontal = 2.dp),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
) {
itemsIndexed(
items = filteredItems,
key = { index, item -> "${item.label}-$index" },
@@ -132,6 +174,7 @@ fun F7AppMenuSheet(
)
}
}
}
}
}
}