chat android tv adaptation
This commit is contained in:
@@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
@@ -18,6 +19,7 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialExpressiveTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarDefaults
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationRail
|
||||
import androidx.compose.material3.NavigationRailItem
|
||||
@@ -30,6 +32,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
@@ -37,7 +40,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.shadowsparky.ui.nav.Route
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.ui.theme.getColorScheme
|
||||
|
||||
@Immutable
|
||||
@@ -138,8 +140,8 @@ private fun <T : Route> BottomBar(
|
||||
.windowInsetsPadding(WindowInsets.navigationBars)
|
||||
) {
|
||||
NavigationBar(
|
||||
containerColor = ComponentDefaults.navBarContentColor(),
|
||||
modifier = ComponentDefaults.roundedClip().blurEffect()
|
||||
containerColor = navBarContentColor(),
|
||||
modifier = Modifier.clip(RoundedCornerShape(24.dp)).blurEffect()
|
||||
) {
|
||||
entries.forEach { entry ->
|
||||
NavigationBarItem(
|
||||
@@ -153,6 +155,14 @@ private fun <T : Route> BottomBar(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun navBarContentColor(): Color {
|
||||
return if (isBlurEnabled()) {
|
||||
MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = 0.5f)
|
||||
} else {
|
||||
NavigationBarDefaults.containerColor
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
||||
@@ -11,10 +11,11 @@ import androidx.compose.material3.SearchBarState
|
||||
import androidx.compose.material3.rememberSearchBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import ru.shadowsparky.ui.blurEffect
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.ui.isBlurEnabled
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -25,7 +26,7 @@ fun AppBarWithSearch(
|
||||
navigationIcon: @Composable (() -> Unit)? = null,
|
||||
actions: @Composable (RowScope.() -> Unit)? = null,
|
||||
shape: Shape = SearchBarDefaults.inputFieldShape,
|
||||
colors: AppBarWithSearchColors = ComponentDefaults.appBarWithSearchDefaults(),
|
||||
colors: AppBarWithSearchColors = appBarWithSearchDefaults(),
|
||||
tonalElevation: Dp = SearchBarDefaults.TonalElevation,
|
||||
shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
|
||||
contentPadding: PaddingValues = SearchBarDefaults.AppBarContentPadding,
|
||||
@@ -47,3 +48,15 @@ fun AppBarWithSearch(
|
||||
scrollBehavior
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun appBarWithSearchDefaults(): AppBarWithSearchColors {
|
||||
return if (isBlurEnabled()) {
|
||||
SearchBarDefaults.appBarWithSearchColors(
|
||||
appBarContainerColor = Color.Transparent
|
||||
)
|
||||
} else {
|
||||
SearchBarDefaults.appBarWithSearchColors()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,10 @@ import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import ru.shadowsparky.ui.blurEffect
|
||||
import ru.shadowsparky.ui.theme.ComponentDefaults
|
||||
import ru.shadowsparky.ui.isBlurEnabled
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -23,7 +24,7 @@ fun TopAppBar(
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
|
||||
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
|
||||
colors: TopAppBarColors = ComponentDefaults.topAppBarColors(),
|
||||
colors: TopAppBarColors = topAppBarColors(),
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||
contentPadding: PaddingValues = TopAppBarDefaults.ContentPadding
|
||||
) {
|
||||
@@ -39,3 +40,16 @@ fun TopAppBar(
|
||||
contentPadding = contentPadding
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun topAppBarColors(): TopAppBarColors {
|
||||
return if (isBlurEnabled()) {
|
||||
TopAppBarDefaults.topAppBarColors(
|
||||
Color.Transparent,
|
||||
Color.Transparent
|
||||
)
|
||||
} else {
|
||||
TopAppBarDefaults.topAppBarColors()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,56 +1,68 @@
|
||||
package ru.shadowsparky.ui.theme
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.AppBarWithSearchColors
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBarDefaults
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.material3.TopAppBarColors
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ru.shadowsparky.ui.isBlurEnabled
|
||||
|
||||
object ComponentDefaults {
|
||||
|
||||
@Composable
|
||||
fun topAppBarColors(): TopAppBarColors {
|
||||
return if (isBlurEnabled()) {
|
||||
TopAppBarDefaults.topAppBarColors(
|
||||
Color.Transparent,
|
||||
Color.Transparent
|
||||
internal fun focusBorder(
|
||||
modifier: Modifier,
|
||||
needScale: Boolean
|
||||
): Modifier {
|
||||
var isFocused by remember { mutableStateOf(false) }
|
||||
val borderColor by animateColorAsState(
|
||||
targetValue = if (isFocused) MaterialTheme.colorScheme.primary else Color.Transparent,
|
||||
animationSpec = tween(200),
|
||||
label = "borderColor"
|
||||
)
|
||||
val borderWidth by animateDpAsState(
|
||||
targetValue = if (isFocused) 3.dp else 0.dp,
|
||||
animationSpec = tween(200),
|
||||
label = "borderWidth"
|
||||
)
|
||||
val scale by animateFloatAsState(
|
||||
targetValue = if (isFocused) 1.0f else 0.92f,
|
||||
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
|
||||
label = "scale"
|
||||
)
|
||||
val mod = if (needScale) {
|
||||
modifier.graphicsLayer {
|
||||
scaleX = scale
|
||||
scaleY = scale
|
||||
clip = true
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
}
|
||||
} else {
|
||||
modifier
|
||||
}
|
||||
return mod.onFocusChanged { isFocused = it.isFocused }
|
||||
.border(
|
||||
width = borderWidth,
|
||||
color = borderColor,
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
} else {
|
||||
TopAppBarDefaults.topAppBarColors()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun navBarContentColor(): Color {
|
||||
return if (isBlurEnabled()) {
|
||||
MaterialTheme.colorScheme.surfaceContainerHigh.copy(alpha = 0.5f)
|
||||
} else {
|
||||
NavigationBarDefaults.containerColor
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun appBarWithSearchDefaults(): AppBarWithSearchColors {
|
||||
return if (isBlurEnabled()) {
|
||||
SearchBarDefaults.appBarWithSearchColors(
|
||||
appBarContainerColor = Color.Transparent
|
||||
)
|
||||
} else {
|
||||
SearchBarDefaults.appBarWithSearchColors()
|
||||
}
|
||||
}
|
||||
|
||||
fun roundedClip(modifier: Modifier = Modifier): Modifier {
|
||||
return modifier.clip(RoundedCornerShape(24.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Modifier.focusBorder(needScale: Boolean = true): Modifier {
|
||||
return ComponentDefaults.focusBorder(this, needScale)
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ fun hookPageVisibility(lifecycle: LifecycleRegistry) {
|
||||
|
||||
fun onPageHideShow(hidden: Boolean) {
|
||||
if (hidden) {
|
||||
// уходим глубже: STARTED → CREATED
|
||||
when (lifecycle.state) {
|
||||
Lifecycle.State.RESUMED -> {
|
||||
lifecycle.pause(); lifecycle.stop()
|
||||
lifecycle.pause();
|
||||
lifecycle.stop()
|
||||
}
|
||||
|
||||
Lifecycle.State.STARTED -> {
|
||||
@@ -51,14 +51,16 @@ fun hookPageVisibility(lifecycle: LifecycleRegistry) {
|
||||
else -> Unit
|
||||
}
|
||||
} else {
|
||||
// pageshow: поднимемся обратно
|
||||
when (lifecycle.state) {
|
||||
Lifecycle.State.INITIALIZED -> {
|
||||
lifecycle.create(); lifecycle.start(); if (pageVisibilityState() == "visible") lifecycle.resume()
|
||||
lifecycle.create()
|
||||
lifecycle.start()
|
||||
if (pageVisibilityState() == "visible") lifecycle.resume()
|
||||
}
|
||||
|
||||
Lifecycle.State.CREATED -> {
|
||||
lifecycle.start(); if (pageVisibilityState() == "visible") lifecycle.resume()
|
||||
lifecycle.start()
|
||||
if (pageVisibilityState() == "visible") lifecycle.resume()
|
||||
}
|
||||
|
||||
Lifecycle.State.STARTED -> {
|
||||
|
||||
Reference in New Issue
Block a user