Initial commit
This commit is contained in:
176
app/src/main/java/com/example/superheroes/HeroesScreen.kt
Normal file
176
app/src/main/java/com/example/superheroes/HeroesScreen.kt
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
// This file uses Experimental APIs.
|
||||
// Caution: Experimental APIs can change in the future or may be removed entirely.
|
||||
@file:OptIn(ExperimentalAnimationApi::class)
|
||||
|
||||
package com.example.superheroes
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.animation.core.MutableTransitionState
|
||||
import androidx.compose.animation.core.Spring.DampingRatioLowBouncy
|
||||
import androidx.compose.animation.core.Spring.StiffnessVeryLow
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.superheroes.model.Hero
|
||||
import com.example.superheroes.model.HeroesRepository
|
||||
import com.example.superheroes.ui.theme.SuperheroesTheme
|
||||
|
||||
@Composable
|
||||
fun HeroesList(
|
||||
heroes: List<Hero>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val visibleState = remember {
|
||||
MutableTransitionState(false).apply {
|
||||
// Start the animation immediately.
|
||||
targetState = true
|
||||
}
|
||||
}
|
||||
|
||||
// Fade in entry animation for the entire list
|
||||
AnimatedVisibility(
|
||||
visibleState = visibleState,
|
||||
enter = fadeIn(
|
||||
animationSpec = spring(dampingRatio = DampingRatioLowBouncy)
|
||||
),
|
||||
exit = fadeOut()
|
||||
) {
|
||||
LazyColumn {
|
||||
itemsIndexed(heroes) { index, hero ->
|
||||
HeroListItem(
|
||||
hero = hero,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
// Animate each list item to slide in vertically
|
||||
.animateEnterExit(
|
||||
enter = slideInVertically(
|
||||
animationSpec = spring(
|
||||
stiffness = StiffnessVeryLow,
|
||||
dampingRatio = DampingRatioLowBouncy
|
||||
),
|
||||
initialOffsetY = { it * (index + 1) } // staggered entrance
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HeroListItem(
|
||||
hero: Hero,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Card(
|
||||
elevation = 2.dp,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(16.dp)
|
||||
.sizeIn(minHeight = 72.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.weight(1f)) {
|
||||
Text(
|
||||
text = stringResource(hero.nameRes),
|
||||
style = MaterialTheme.typography.h3
|
||||
)
|
||||
Text(
|
||||
text = stringResource(hero.descriptionRes),
|
||||
style = MaterialTheme.typography.body1
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.width(16.dp))
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(72.dp)
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(hero.imageRes),
|
||||
contentDescription = null,
|
||||
alignment = Alignment.TopCenter,
|
||||
contentScale = ContentScale.FillWidth
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview("Light Theme")
|
||||
@Preview("Dark Theme", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
fun HeroPreview() {
|
||||
val hero = Hero(
|
||||
R.string.hero1,
|
||||
R.string.description1,
|
||||
R.drawable.android_superhero1
|
||||
)
|
||||
SuperheroesTheme {
|
||||
HeroListItem(hero = hero)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview("Heroes List")
|
||||
@Composable
|
||||
fun HeroesPreview() {
|
||||
SuperheroesTheme(darkTheme = false) {
|
||||
Surface (
|
||||
color = MaterialTheme.colors.background
|
||||
) {
|
||||
/* Important: It is not a good practice to access data source directly from the UI.
|
||||
In later units you will learn how to use ViewModel in such scenarios that takes the
|
||||
data source as a dependency and exposes heroes.
|
||||
*/
|
||||
HeroesList(heroes = HeroesRepository.heroes)
|
||||
}
|
||||
}
|
||||
}
|
||||
96
app/src/main/java/com/example/superheroes/MainActivity.kt
Normal file
96
app/src/main/java/com/example/superheroes/MainActivity.kt
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.superheroes.model.HeroesRepository
|
||||
import com.example.superheroes.ui.theme.SuperheroesTheme
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
SuperheroesTheme {
|
||||
SuperheroesApp()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable that displays an app bar and a list of heroes.
|
||||
*/
|
||||
@Composable
|
||||
fun SuperheroesApp() {
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
TopAppBar()
|
||||
}
|
||||
) {
|
||||
/* Important: It is not a good practice to access data source directly from the UI.
|
||||
In later units you will learn how to use ViewModel in such scenarios that takes the
|
||||
data source as a dependency and exposes heroes.
|
||||
*/
|
||||
val heroes = HeroesRepository.heroes
|
||||
HeroesList(heroes = heroes, Modifier.padding(it))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Composable that displays a Top Bar with an icon and text.
|
||||
*
|
||||
* @param modifier modifiers to set to this composable
|
||||
*/
|
||||
@Composable
|
||||
fun TopAppBar(modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.size(56.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.app_name),
|
||||
style = MaterialTheme.typography.h1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun SuperHeroesPreview() {
|
||||
SuperheroesTheme {
|
||||
SuperheroesApp()
|
||||
}
|
||||
}
|
||||
26
app/src/main/java/com/example/superheroes/model/Hero.kt
Normal file
26
app/src/main/java/com/example/superheroes/model/Hero.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import com.example.superheroes.R
|
||||
|
||||
data class Hero(
|
||||
@StringRes val nameRes: Int,
|
||||
@StringRes val descriptionRes: Int,
|
||||
@DrawableRes val imageRes: Int
|
||||
)
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes.model
|
||||
|
||||
import com.example.superheroes.R
|
||||
|
||||
object HeroesRepository {
|
||||
val heroes = listOf(
|
||||
Hero(
|
||||
nameRes = R.string.hero1,
|
||||
descriptionRes = R.string.description1,
|
||||
imageRes = R.drawable.android_superhero1
|
||||
),
|
||||
Hero(
|
||||
nameRes = R.string.hero2,
|
||||
descriptionRes = R.string.description2,
|
||||
imageRes = R.drawable.android_superhero2
|
||||
),
|
||||
Hero(
|
||||
nameRes = R.string.hero3,
|
||||
descriptionRes = R.string.description3,
|
||||
imageRes = R.drawable.android_superhero3
|
||||
),
|
||||
Hero(
|
||||
nameRes = R.string.hero4,
|
||||
descriptionRes = R.string.description4,
|
||||
imageRes = R.drawable.android_superhero4
|
||||
),
|
||||
Hero(
|
||||
nameRes = R.string.hero5,
|
||||
descriptionRes = R.string.description5,
|
||||
imageRes = R.drawable.android_superhero5
|
||||
),
|
||||
Hero(
|
||||
nameRes = R.string.hero6,
|
||||
descriptionRes = R.string.description6,
|
||||
imageRes = R.drawable.android_superhero6
|
||||
)
|
||||
)
|
||||
}
|
||||
35
app/src/main/java/com/example/superheroes/ui/theme/Color.kt
Normal file
35
app/src/main/java/com/example/superheroes/ui/theme/Color.kt
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
//Light Theme
|
||||
val md_theme_light_background = Color(0xFFFDFCF4)
|
||||
val md_theme_light_surface = Color(0xFFE0EACE)
|
||||
val md_theme_light_secondary = Color(0xFF596148)
|
||||
val md_theme_light_onSurface = Color(0xFF1B1C18)
|
||||
val md_theme_light_primary = Color(0xFF466800)
|
||||
val md_theme_light_onPrimary = Color(0xFF223600)
|
||||
|
||||
|
||||
// Dark Theme
|
||||
val md_theme_dark_background = Color(0xFF1B1C18)
|
||||
val md_theme_dark_surface = Color(0xFF373F29)
|
||||
val md_theme_dark_secondary = Color(0xFFDDE6C6)
|
||||
val md_theme_dark_onSurface = Color(0xFFE4E3DB)
|
||||
val md_theme_dark_primary = Color(0xFFC1CAAB)
|
||||
val md_theme_dark_onPrimary = Color(0xFFDDE6C6)
|
||||
26
app/src/main/java/com/example/superheroes/ui/theme/Shape.kt
Normal file
26
app/src/main/java/com/example/superheroes/ui/theme/Shape.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes.ui.theme
|
||||
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Shapes
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val Shapes = Shapes(
|
||||
small = RoundedCornerShape(8.dp),
|
||||
medium = RoundedCornerShape(16.dp),
|
||||
large = RoundedCornerShape(16.dp)
|
||||
)
|
||||
56
app/src/main/java/com/example/superheroes/ui/theme/Theme.kt
Normal file
56
app/src/main/java/com/example/superheroes/ui/theme/Theme.kt
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes.ui.theme
|
||||
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
private val DarkColorPalette = darkColors(
|
||||
background = md_theme_dark_background,
|
||||
surface = md_theme_dark_surface,
|
||||
onSurface = md_theme_dark_onSurface,
|
||||
primary = md_theme_dark_primary,
|
||||
onPrimary = md_theme_dark_onPrimary,
|
||||
secondary = md_theme_dark_secondary
|
||||
)
|
||||
|
||||
private val LightColorPalette = lightColors(
|
||||
background = md_theme_light_background,
|
||||
surface = md_theme_light_surface,
|
||||
onSurface = md_theme_light_onSurface,
|
||||
primary = md_theme_light_primary,
|
||||
onPrimary = md_theme_light_onPrimary,
|
||||
secondary = md_theme_light_secondary
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SuperheroesTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
|
||||
val colors = if (darkTheme) {
|
||||
DarkColorPalette
|
||||
} else {
|
||||
LightColorPalette
|
||||
}
|
||||
|
||||
MaterialTheme(
|
||||
colors = colors,
|
||||
typography = Typography,
|
||||
shapes = Shapes,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
51
app/src/main/java/com/example/superheroes/ui/theme/Type.kt
Normal file
51
app/src/main/java/com/example/superheroes/ui/theme/Type.kt
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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 com.example.superheroes.ui.theme
|
||||
|
||||
import androidx.compose.material.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.example.superheroes.R
|
||||
|
||||
val Cabin = FontFamily(
|
||||
Font(R.font.cabin_regular, FontWeight.Normal),
|
||||
Font(R.font.cabin_bold, FontWeight.Bold)
|
||||
)
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
defaultFontFamily = Cabin,
|
||||
h1 = TextStyle(
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 30.sp
|
||||
),
|
||||
h2 = TextStyle(
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 20.sp
|
||||
),
|
||||
h3 = TextStyle(
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 20.sp
|
||||
),
|
||||
|
||||
body1 = TextStyle(
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user