Part 1 : Implementing Splash & OnBoarding Screen Integration in App

Mohit Damke
6 min readJul 4, 2024

--

Here we will implement splash screen and onboarding screen

Implement Splash Screen

  • First open theme.xml file
  • Add following code in it
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.App.Starting.Theme" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">#FFFFFF</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/book</item>
<item name="postSplashScreenTheme">@style/Theme.NewsApp</item>
</style>

<style name="Theme.App.Starting.Theme.Night" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">#1C1E21</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/book</item>
<item name="postSplashScreenTheme">@style/Theme.NewsApp</item>
</style>

<style name="Theme.NewsApp" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
  • Here we have implement the splash screen for both day and night mode of our app.
  • Make sure to add your theme project file name in name section

Make Changes in the Manifest File

  • Change the theme
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.App.Starting.Theme"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.App.Starting.Theme">
<intent-filter>
  • Call the Splash Screen in the Main Activity
installSplashScreen()
  • If the Top NavBar is been visible on your app so simply add code to hide it.
getActionBar()?.hide();
  • Check the app splash screen by running it.

Implementing OnBoarding Screen

  • Here we want to implement the onboarding screen after the splash screen been visible
  • First we have to make package in repository name presentation
  • Make one package under it name as onboarding
  • Make New File Page.kt
package com.example.newsapp.presentation.onboarding

import androidx.annotation.DrawableRes
import com.example.newsapp.R

data class Page(
val title: String,
val description : String,
@DrawableRes val image: Int
)


val pages = listOf(
Page(
title = "Welcome to NewsConnect!",
description = "Stay informed with the latest news from around the world. NewsConnect brings you real-time updates on current events, politics, sports, entertainment, and more.",
image = R.drawable.onboarding1
),

Page(
title = "Stay Updated, Anywhere, Anytime",
description = "Get notifications on breaking news and trending stories. With NewsConnect, you'll never miss an important update, whether you're at home or on the go.",
image = R.drawable.onboarding2
),
Page(
title = "Get Started with NewsConnect",
description = "Dive into a world of news tailored just for you. Tap the button below to begin exploring!",
image = R.drawable.onboarding3
)

)
  • Here we will create a data class as Page title, description, image.
  • And name a listOf page and give some Demo Data in it.
  • Create Package name components where we will add components
  • We will design this part here
package com.example.newsapp.presentation.onboarding.components

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import com.example.newsapp.R
import com.example.newsapp.presentation.Dimens.MediumPadding1
import com.example.newsapp.presentation.Dimens.MediumPadding2
import com.example.newsapp.presentation.onboarding.Page
import com.example.newsapp.presentation.onboarding.pages
import com.example.newsapp.ui.theme.NewsAppTheme


@Composable
fun OnBoardingPage(modifier: Modifier = Modifier, page: Page) {
Column(modifier = modifier) {
Image(
painter = painterResource(id = page.image),
contentDescription = "",
modifier = modifier
.fillMaxWidth()
.fillMaxHeight(0.6f),
contentScale = ContentScale.Crop
)
Spacer(modifier = modifier.height(MediumPadding1))
Text(
modifier = modifier.padding(horizontal = MediumPadding2),
text = page.title,
style = MaterialTheme.typography.displaySmall.copy(fontWeight = FontWeight.Bold),
color = colorResource(id = R.color.display_small)
)
Text(
modifier = modifier.padding(horizontal = MediumPadding2),
text = page.description,
style = MaterialTheme.typography.bodyMedium,
color = colorResource(id = R.color.text_medium)
)
}

}

NOTE : I have created one object file in the project where there is all the dimensions written properly

package com.example.newsapp.presentation

import androidx.compose.ui.unit.dp

object Dimens {


val ExtraSmallPadding = 3.dp
val ExtraSmallPadding2 = 6.dp
val MediumPadding1 = 24.dp
val MediumPadding2 = 30.dp
val MediumPadding3 = 40.dp

val IndicatorSize = 14.dp

val SmallIconSize = 11.dp
val IconSize = 20.dp

val ArticleCardSize = 96.dp

val ArticleImageHeight = 248.dp
}

Button Content

  • We have to make new file name as NewsButton.kt where we will make UI of the button so we can use the button in the onboarding screen.
package com.example.newsapp.presentation.common

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color.Companion.White
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.newsapp.ui.theme.Black
import com.example.newsapp.ui.theme.NewsAppTheme
import com.example.newsapp.ui.theme.WhiteGray

@Composable
fun NewsButton(modifier: Modifier = Modifier, text: String, onClick: () -> Unit) {
Button(
onClick = onClick, colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.primary,
contentColor = White
), shape = RoundedCornerShape(6.dp)
) {
Text(
text = text,
style = MaterialTheme.typography.labelMedium.copy(fontWeight = FontWeight.SemiBold)
)
}

}

@Composable
fun NewsTextButton(modifier: Modifier = Modifier, text: String, onClick: () -> Unit) {
Button(
onClick = onClick, colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.background,
contentColor = Black
), shape = RoundedCornerShape(6.dp)
) {
Text(
text = text,
style = MaterialTheme.typography.labelMedium.copy(fontWeight = FontWeight.SemiBold),
color = Black
)
}
}
  • There are two buttons first one is for “next” and second is for “back”

Navigation Dot on the Screens

  • Here we have implemented the dot on the onboarding screen.
package com.example.newsapp.presentation.onboarding.components

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.example.newsapp.presentation.Dimens.IndicatorSize
import com.example.newsapp.ui.theme.BlueGray

@Composable
fun PageIndicator(
modifier: Modifier = Modifier, pageSize: Int,
selectedPage: Int,
selectedColor: Color = MaterialTheme.colorScheme.primary,
unselectedColor: Color = BlueGray

) {
Row(
modifier = Modifier.padding(horizontal = 4.dp),
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically
) {
repeat(pageSize) { page ->
Box(
modifier = modifier
.size(24.dp)
.padding(vertical = 4.dp, horizontal = 2.dp)
.clip(CircleShape)
.background(color = if (page == selectedPage) selectedColor else unselectedColor)
)
}
}
}

Implement onboarding Screen

package com.example.newsapp.presentation.onboarding.components

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.example.newsapp.presentation.common.NewsButton
import com.example.newsapp.presentation.common.NewsTextButton
import com.example.newsapp.presentation.Dimens.IndicatorSize
import com.example.newsapp.presentation.onboarding.OnBoardingEvent
import com.example.newsapp.presentation.onboarding.pages
import kotlinx.coroutines.launch

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun OnBoardingScreen(
modifier: Modifier = Modifier, event: (OnBoardingEvent) -> Unit
) {
Column(modifier = modifier.fillMaxSize()) {
val pagerState = rememberPagerState(initialPage = 0) {
pages.size
}
val buttonState = remember {
derivedStateOf {
when (pagerState.currentPage) {
0 -> listOf("", "Next")
1 -> listOf("Back", "Next")
2 -> listOf("Back", "Get Started")
else -> listOf("", "")
}
}
}

HorizontalPager(state = pagerState) { index ->
OnBoardingPage(page = pages[index])
}

Spacer(modifier = Modifier.weight(1f))
Row(
modifier = modifier
.fillMaxWidth()
.padding(horizontal = 10.dp)
.navigationBarsPadding(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
PageIndicator(
pageSize = pages.size,
selectedPage = pagerState.currentPage,
modifier = Modifier.width(IndicatorSize)
)
Row(
modifier = Modifier.weight(1f),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically
) {
val scope = rememberCoroutineScope()

if (buttonState.value[0].isNotEmpty()) {
NewsTextButton(text = buttonState.value[0], onClick = {
scope.launch {
pagerState.animateScrollToPage(page = pagerState.currentPage - 1)
}
})
}
Spacer(modifier = Modifier.width(10.dp))
NewsButton(text = buttonState.value[1], onClick = {
scope.launch {
if (pagerState.currentPage == 2) {
event(OnBoardingEvent.SaveAppEntry)
} else {
pagerState.animateScrollToPage(page = pagerState.currentPage + 1)
}
}
})

}

}
Spacer(modifier = Modifier.weight(0.5f))
}

}
  • We have added pages, button, dots in the screen
  • Added Horizontal Pager for sliding the pages
  • And added a logic for the button as not showing back button on the first screen and adding it on second screen and added some functionality onClick for making page change to next, back.
  • Here we have implemented the onboarding screen properly
if (pagerState.currentPage == 2) {
event(OnBoardingEvent.SaveAppEntry) TODO// We have to add Onboarding event
} else {
pagerState.animateScrollToPage(page = pagerState.currentPage + 1)
}
  • We will add this later

Now next Part 2 will be showing how to implement the Preferences datastore and what is it and we will add dependency injection in the app with the help of Dagger Hilt

Part 2 : Implementing Preferences Datastore and Dependency Injection

You can visit the introduction article for the news app with the link below

You can add 50 clap by just pressing on clap icon

Visit my GitHub Repository : https://github.com/mohitdamke/NewsApp

Make sure to follow me on
Link-tree :
https://linktr.ee/MohitDamke01
LinkedIn :
https://www.linkedin.com/in/mohitdamke01

--

--

Mohit Damke

Junior Android Developer | Kotlin | Jetpack | Firebase | Android Studio | MVVM & Clean Code Architecture