Part 6: Implementing News Detail Screen in app

Mohit Damke
3 min readJul 4, 2024

--

Here i have implement news detail screen where the image , title, description is been visible and more option such as adding back, bookmark, web visit, share button is been visible

  • First we have to make the top nav bar for detail screen
package com.example.newsapp.presentation.details.components

import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.example.newsapp.R
import com.example.newsapp.ui.theme.NewsAppTheme

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DetailsTopBar(
modifier: Modifier = Modifier,
onBrowsingClick: () -> Unit,
onShareClick: () -> Unit,
onBookMarkClick: () -> Unit,
onBackClick: () -> Unit,
) {
TopAppBar(
modifier = Modifier.fillMaxWidth(),
colors = TopAppBarDefaults.mediumTopAppBarColors(
containerColor = Color.Transparent,
actionIconContentColor = colorResource(id = R.color.body),
navigationIconContentColor = colorResource(id = R.color.body),
),
title = {},
navigationIcon = {
IconButton(onClick = onBackClick) {
Icon(
painter = painterResource(id = R.drawable.baseline_arrow_back_24),
contentDescription = null,
)
}
},
actions = {

IconButton(onClick = onBookMarkClick) {
Icon(
painter = painterResource(id = R.drawable.baseline_bookmark_24),
contentDescription = null
)
}
IconButton(onClick = onShareClick) {
Icon(
imageVector = Icons.Default.Share,
contentDescription = null
)
}
IconButton(onClick = onBrowsingClick) {
Icon(
painter = painterResource(id = R.drawable.baseline_web_24),
contentDescription = null
)
}
},
)
}

@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
@Composable
fun DetailsTopBarPreview() {
NewsAppTheme(dynamicColor = false) {
Box(modifier = Modifier
.background(MaterialTheme.colorScheme.background)) {
DetailsTopBar(
onShareClick = { /*TODO*/ },
onBookMarkClick = { /*TODO*/ },
onBrowsingClick = {}) {

}
}
}
}
  • Then make the detail event
package com.example.newsapp.presentation.details

import com.example.newsapp.domain.model.Article

sealed class DetailsEvent {

data class UpsertDeleteArticle(val article: Article) : DetailsEvent()

object RemoveSideEffect : DetailsEvent()

}

NOTE : You have to add some Configuration in the Manifest File

  • Below Application Class
</application>

<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
</intent>
<intent>
<action android:name="android.intent.action.SEND"/>
</intent>
</queries>

</manifest>
  • We have to make UI of the Detail Screen
package com.example.newsapp.presentation.details

import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.example.newsapp.R
import com.example.newsapp.domain.model.Article
import com.example.newsapp.domain.model.Source
import com.example.newsapp.presentation.Dimens.ArticleImageHeight
import com.example.newsapp.presentation.Dimens.MediumPadding1
import com.example.newsapp.presentation.details.components.DetailsTopBar
import com.example.newsapp.ui.theme.NewsAppTheme

@Composable
fun DetailsScreen(
modifier: Modifier = Modifier, article: Article,
event: (DetailsEvent) -> Unit,
navigateUp: () -> Unit
) {
val context = LocalContext.current
Column(modifier = Modifier
.fillMaxSize()
.statusBarsPadding()) {
DetailsTopBar(
onBrowsingClick = {
Intent(Intent.ACTION_VIEW).also {
it.data = Uri.parse(article.url)
if (it.resolveActivity(context.packageManager) != null) {
context.startActivity(it)
}
}
},
onShareClick = {
Intent(Intent.ACTION_SEND).also {
it.putExtra(Intent.EXTRA_TEXT, article.url)
it.type = "text/plain"
if (it.resolveActivity(context.packageManager) != null) {
context.startActivity(it)
}
}
},
onBookMarkClick = {
event(DetailsEvent.UpsertDeleteArticle(article))
},
onBackClick = navigateUp
)

LazyColumn(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(
start = MediumPadding1,
end = MediumPadding1,
top = MediumPadding1
)
) {
item {
AsyncImage(
model = ImageRequest.Builder(context = context).data(article.urlToImage)
.build(),
contentDescription = null,
modifier = Modifier
.fillMaxWidth()
.height(ArticleImageHeight)
.clip(MaterialTheme.shapes.medium),
contentScale = ContentScale.Crop
)
Spacer(modifier = Modifier.height(MediumPadding1))
Text(
text = article.title,
style = MaterialTheme.typography.displaySmall,
color = colorResource(
id = R.color.text_title
)
)
Text(
text = article.content,
style = MaterialTheme.typography.bodyMedium,
color = colorResource(
id = R.color.body
)
)
Spacer(modifier = Modifier.padding(top = 20.dp))
}
}
}
}

@Preview(showBackground = true)
@Composable
fun DetailsScreenPreview() {
NewsAppTheme(dynamicColor = false) {
DetailsScreen(
article = Article(
author = "",
title = "Coinbase says Apple blocked its last app release on NFTs in Wallet ... - CryptoSaurus",
description = "Coinbase says Apple blocked its last app release on NFTs in Wallet ... - CryptoSaurus",
content = "We use cookies and data to Deliver and maintain Google services Track outages and protect against spam, fraud, and abuse Measure audience engagement and site statistics ",
publishedAt = "2023-06-16T22:24:33Z",
source = Source(
id = "", name = "bbc"
),
url = "https://consent.google.com/ml?continue=https://news.google.com/rss/articles/CBMiaWh0dHBzOi8vY3J5cHRvc2F1cnVzLnRlY2gvY29pbmJhc2Utc2F5cy1hcHBsZS1ibG9ja2VkLWl0cy1sYXN0LWFwcC1yZWxlYXNlLW9uLW5mdHMtaW4td2FsbGV0LXJldXRlcnMtY29tL9IBAA?oc%3D5&gl=FR&hl=en-US&cm=2&pc=n&src=1",
urlToImage = "https://media.wired.com/photos/6495d5e893ba5cd8bbdc95af/191:100/w_1280,c_limit/The-EU-Rules-Phone-Batteries-Must-Be-Replaceable-Gear-2BE6PRN.jpg"
),
event = {}
) {

}
}
}

If you have not read Part 5 of the series the here is the link below

https://medium.com/@mohitrdamke/part-5-implementing-search-screen-in-app-2b42e5300c9d

You can visit the introduction article for the news app with the link below
https://medium.com/@mohitrdamke/news-app-clean-code-architecture-paging-room-db-in-android-studio-24919ba7d16a

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