[go: nahoru, domu]

blob: b84abe565e339e83b9e65d6730cd958768f356f2 [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.material.demos
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.ui.core.Modifier
import androidx.ui.core.setContent
import androidx.compose.foundation.Box
import androidx.compose.foundation.ContentGravity
import androidx.compose.foundation.ScrollableColumn
import androidx.compose.foundation.Text
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.graphics.toArgb
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.preferredHeight
import androidx.compose.material.BottomAppBar
import androidx.compose.material.ColorPalette
import androidx.compose.material.ExtendedFloatingActionButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.TopAppBar
import androidx.compose.material.lightColorPalette
import androidx.compose.ui.unit.dp
import kotlin.math.round
/**
* Demo activity that animates the primary, secondary, and background colours in the [MaterialTheme]
* as the user scrolls. This has the effect of going from a 'light' theme to a 'dark' theme.
*/
class DynamicThemeActivity : ComponentActivity() {
private val scrollFraction = mutableStateOf(0f)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val palette = interpolateTheme(scrollFraction.value)
val darkenedPrimary = palette.darkenedPrimary
window.statusBarColor = darkenedPrimary
window.navigationBarColor = darkenedPrimary
DynamicThemeApp(scrollFraction, palette)
}
}
private val ColorPalette.darkenedPrimary: Int
get() {
return with(primary) {
copy(
red = red * 0.75f,
green = green * 0.75f,
blue = blue * 0.75f
)
}.toArgb()
}
}
private typealias ScrollFraction = MutableState<Float>
@Composable
private fun DynamicThemeApp(scrollFraction: ScrollFraction, palette: ColorPalette) {
MaterialTheme(palette) {
val scrollState = rememberScrollState()
val fraction =
round((scrollState.value / scrollState.maxValue) * 100) / 100
remember(fraction) { scrollFraction.value = fraction }
Scaffold(
topBar = { TopAppBar({ Text("Scroll down!") }) },
bottomBar = { BottomAppBar(cutoutShape = CircleShape) {} },
floatingActionButton = { Fab(scrollFraction) },
floatingActionButtonPosition = Scaffold.FabPosition.Center,
isFloatingActionButtonDocked = true,
bodyContent = { innerPadding ->
ScrollableColumn(scrollState = scrollState, children = {
Column(Modifier.padding(innerPadding)) {
repeat(20) { index ->
Card(index)
}
}
})
}
)
}
}
@Composable
private fun Fab(scrollFraction: ScrollFraction) {
val fabText = emojiForScrollFraction(scrollFraction.value)
ExtendedFloatingActionButton(
text = { Text(fabText, style = MaterialTheme.typography.h5) },
onClick = {}
)
}
@Composable
private fun Card(index: Int) {
val shapeColor = lerp(Color(0xFF303030), Color.White, index / 19f)
val textColor = lerp(Color.White, Color(0xFF303030), index / 19f)
// TODO: ideally this would be a Card but currently Surface consumes every
// colour from the Material theme to work out text colour, so we end up doing a
// large amount of work here when the top level theme changes
Box(
Modifier.padding(25.dp).fillMaxWidth().preferredHeight(150.dp),
shape = RoundedCornerShape(10.dp),
backgroundColor = shapeColor,
gravity = ContentGravity.Center
) {
Text("Card ${index + 1}", color = textColor)
}
}
private fun interpolateTheme(fraction: Float): ColorPalette {
val interpolatedFraction = FastOutSlowInEasing(fraction)
val primary = lerp(Color(0xFF6200EE), Color(0xFF303030), interpolatedFraction)
val secondary = lerp(Color(0xFF03DAC6), Color(0xFFBB86FC), interpolatedFraction)
val background = lerp(Color.White, Color(0xFF121212), interpolatedFraction)
return lightColorPalette(
primary = primary,
secondary = secondary,
background = background
)
}
/**
* 'Animate' the emoji in the FAB from 'sun' to 'moon' as we darken the theme
*/
private fun emojiForScrollFraction(fraction: Float): String {
return when {
// Sun
fraction < 1 / 7f -> "\u2600"
// Sun behind small cloud
fraction < 2 / 7f -> "\uD83C\uDF24"
// Sun behind cloud
fraction < 3 / 7f -> "\uD83C\uDF25"
// Cloud
fraction < 4 / 7f -> "\u2601"
// Cloud with rain
fraction < 5 / 7f -> "\uD83C\uDF27"
// Cloud with lightning
fraction < 6 / 7f -> "\uD83C\uDF29"
// Moon
else -> "\uD83C\uDF15"
}
}