Overview
The Home Screen serves as the main navigation hub for NASA Explorer. It implements a scaffold layout with a custom top app bar, bottom navigation bar, and hosts multiple nested screens including Daily Image, Random Images, Range Images, and Favorites.
Key Features
Bottom Navigation Five navigation items for quick access to all major features
Top App Bar Custom header with branding and logout functionality
Nested Navigation NavHost integration for smooth transitions between sections
Animated Transitions Fade animations for screen transitions (1500ms duration)
Architecture
Main HomeScreen Composable
@Composable
fun HomeScreen (
homeScreenViewModel: HomeScreenViewModel = hiltViewModel (),
onNavigateToLogin: () -> Unit
) {
val navController = rememberNavController ()
BackHandler {
navController. popBackStack (Routes.Home, inclusive = false )
}
Scaffold (
topBar = {
HomeTopBar (
navController = navController,
homeScreenViewModel = homeScreenViewModel,
onNavigateToLogin = onNavigateToLogin
)
},
bottomBar = {
HomeBottomBar (navController = navController)
}
) { paddingValues ->
// NavHost implementation
}
}
Screen Components
Home Content
The default home content displays a grid of NASA images:
@Composable
fun HomeScreenContent () {
Box (
modifier = Modifier. fillMaxSize (),
contentAlignment = Alignment.Center
) {
Image (
painter = painterResource (id = R.drawable.fondo),
contentDescription = "Background" ,
modifier = Modifier. fillMaxSize (),
contentScale = ContentScale.Crop
)
Column (
Modifier. fillMaxSize (),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
// Two rows with two images each
}
}
}
The home content displays 4 sample NASA images in a 2x2 grid layout with rounded corners and borders.
Top App Bar
HomeTopBar Implementation
@OptIn (ExperimentalMaterial3Api:: class )
@Composable
fun HomeTopBar (
navController: NavController ,
homeScreenViewModel: HomeScreenViewModel ,
onNavigateToLogin: () -> Unit
) {
TopAppBar (
title = {
Text (
text = "NASA EXPLORER" ,
style = MaterialTheme.typography.titleLarge
)
},
colors = TopAppBarDefaults. topAppBarColors (
containerColor = MaterialTheme.colorScheme.primary. copy (alpha = 0.8f ),
titleContentColor = MaterialTheme.colorScheme.onPrimary,
navigationIconContentColor = MaterialTheme.colorScheme.onPrimary
),
modifier = Modifier. shadow ( 4 .dp),
navigationIcon = {
IconButton (onClick = { navController. navigate (Routes.Home) }) {
Icon (
painter = painterResource (id = R.drawable.planet_solid),
contentDescription = "Button Home" ,
tint = MaterialTheme.colorScheme.onPrimary
)
}
},
actions = {
Text (
text = stringResource (R.string.close_session),
color = MaterialTheme.colorScheme.onPrimary,
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier
. padding (end = 18 .dp)
. clickable {
homeScreenViewModel. logOut ()
onNavigateToLogin ()
}
)
}
)
}
Top Bar Features
“NASA EXPLORER” displayed in the title using MaterialTheme.typography.titleLarge
Planet icon that navigates back to home screen when clicked
Clickable text that triggers logout and navigation to login screen: homeScreenViewModel. logOut ()
onNavigateToLogin ()
Semi-transparent primary color background (80% alpha)
4dp shadow elevation
OnPrimary color for text and icons
Bottom Navigation Bar
HomeBottomBar Implementation
@Composable
fun HomeBottomBar (navController: NavController ) {
var selectedItem by remember { mutableIntStateOf ( - 1 ) }
NavigationBar (
containerColor = MaterialTheme.colorScheme.primary. copy (alpha = 0.8f )
) {
// Navigation items
}
}
Navigation Items
Home
Daily Image
Random Images
Range Images
Favorites
Icon : Icons.Default.HomeLabel : “Inicio”Route : Routes.HomeNavigationBarItem (
selected = selectedItem == 0 ,
onClick = {
if (selectedItem != 0 ) {
selectedItem = 0
navController. navigate (Routes.Home) {
popUpTo < Routes . Home > { inclusive = false }
}
}
},
icon = { Icon (imageVector = Icons.Default.Home, contentDescription = "Home" ) },
label = { Text (text = "Inicio" ) }
)
Icon : Icons.Filled.TodayLabel : “Diaria”Route : Routes.DailyImageNavigates to the daily NASA image screen.
Icon : Icons.Filled.ShuffleLabel : “Aleatorias”Route : Routes.RandomImageDisplays 5 random NASA images.
Icon : Icons.Default.DateRangeLabel : “Rango”Route : Routes.RangeImagesShows images from a selected date range.
Icon : Icons.Default.FavoriteLabel : “Favoritos”Route : Routes.FavoriteImagesDisplays user’s saved favorite images.
Navigation Bar Styling
colors = NavigationBarItemDefaults. colors (
indicatorColor = MaterialTheme.colorScheme.secondary,
selectedIconColor = MaterialTheme.colorScheme.onSecondary,
selectedTextColor = MaterialTheme.colorScheme.onSecondary,
unselectedIconColor = MaterialTheme.colorScheme.onPrimary,
unselectedTextColor = MaterialTheme.colorScheme.onPrimary
)
Navigation Setup
NavHost Configuration
NavHost (
navController = navController,
startDestination = Routes.Home,
enterTransition = { fadeIn (animationSpec = tween ( 1500 )) },
exitTransition = { fadeOut (animationSpec = tween ( 1500 )) },
modifier = Modifier
. fillMaxSize ()
. background (Color.Black)
. padding (paddingValues)
) {
composable < Routes . Home > { HomeScreenContent () }
composable < Routes . DailyImage > { DailyImageScreen () }
composable < Routes . RandomImage > { RandomImageScreen () }
composable < Routes . RangeImages > { RangeImagesScreen () }
composable < Routes . FavoriteImages > { FavoritesScreen () }
}
Animation Duration : All transitions use 1500ms fade animations for smooth visual effects.
ViewModel
HomeScreenViewModel
Manages logout functionality:
@HiltViewModel
class HomeScreenViewModel @Inject constructor (
private val authService: AuthService
) : ViewModel () {
fun logOut () {
viewModelScope. launch (Dispatchers.IO) {
authService. userLogout ()
}
}
}
Logout operations run on Dispatchers.IO to handle potential network calls asynchronously.
Back Handler
Custom back button behavior ensures users return to home screen:
BackHandler {
navController. popBackStack (Routes.Home, inclusive = false )
}
Image Grid Layout
The home content displays images in a structured grid:
// First row
Row (
Modifier
. fillMaxWidth ()
. padding (bottom = 24 .dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
Image (
painter = painterResource (id = R.drawable.imagen1),
contentDescription = "Image 1" ,
modifier = Modifier
. size ( 160 .dp)
. clip ( RoundedCornerShape ( 16 .dp))
. border (
BorderStroke ( 1 .dp, MaterialTheme.colorScheme.onSurface. copy (alpha = 0.6f )),
shape = RoundedCornerShape ( 16 .dp)
),
contentScale = ContentScale.Crop
)
// Second image
}
Image Styling
Size : 160x160dp
Shape : Rounded corners (16dp radius)
Border : 1dp with 60% opacity
Content Scale : Crop
Routes
The screen uses type-safe navigation routes:
import com.ccandeladev.nasaexplorer.ui.core.Routes
// Available routes:
Routes.Home
Routes.DailyImage
Routes.RandomImage
Routes.RangeImages
Routes.FavoriteImages
Dependencies
Navigation
import androidx.navigation.NavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
Material 3
import androidx.compose.material3.Scaffold
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.TopAppBar
Animation
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
File Location
app/src/main/java/com/ccandeladev/nasaexplorer/ui/homescreen/
├── HomeScreen.kt
└── HomeScreenViewModel.kt
Best Practice : The screen uses Scaffold for structured layout and NavHost for nested navigation, following Material Design 3 guidelines.