How to overlay texts on an Image using jetpack compose - android

I am trying to make something that uses the same concept as the image below;
An image like background with text overlaying it.
I tried to make a card and give it a backgroundColor of the image, but I got an error;
What I want to do is overlay some texts on an image, like the image above.
So please how do I arrange this code. I need everything to be in a single composable because I need to populate it.
Thanks for your understanding and assistance, In advance.
Please, I'd happily provide any more info needed.

Use a Box to overlay composables.
Something like:
#Composable
fun ImageAndText(
modifier: Modifier = Modifier,
painter: Painter,
contentDescription: String,
text: String
) {
val shape = RoundedCornerShape(8.dp)
val height = 100.dp
Box(
modifier = modifier
.height(height)
.fillMaxWidth()
.background(White, shape = shape),
contentAlignment = Alignment.Center
) {
Image(
painter = painter,
contentDescription = contentDescription,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxSize()
.clip(shape)
)
Text(
text = text,
color = White
)
}
}

You can use Box as a direct Child of your Card and put the Image and Text in it and set its contentAlignment to Alignment.Center.
Use the Image composable to host your desired image instead of card's backgroundColor since it only accepts Color.
#Composable
fun ImageWithTextInMiddle() {
Card {
Box(
modifier = Modifier
.height(100.dp)
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Image(
// painterResource(successInfo.successInfoImageId)
painterResource(R.drawable.img),
contentDescription = "",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
// will display in the middle of the image
Text("Some Text In the middle")
}
}
}

Related

How to make all images from API be in one size in Jetpack Compose?

I have the following composable that represents a list model -
#Composable
fun DashboardCard(
modifier: Modifier = Modifier,
model: DashboardCardModel,
onCardClicked: (model: DashboardCardModel) -> Unit
) {
Column(
modifier = modifier
.size(200.dp, 200.dp)
.background(Color.Transparent)
.padding(16.dp)
.clickable {
onCardClicked(model)
},
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.SpaceAround
) {
if (model.showDefaultThumbnail) {
AsyncImage(
modifier = Modifier
.size(90.dp)
.clip(RoundedCornerShape(10.dp)),
model = model.thumbnailUrl, contentDescription = ""
)
} else {
Image(
modifier = Modifier
.size(90.dp)
.clip(RoundedCornerShape(10.dp)),
painter = painterResource(id = com.tinytap.R.drawable.tinytap),
contentDescription = ""
)
}
Image(
modifier = Modifier
.size(25.dp)
.padding(top = 10.dp)
.alpha(if (model.isCurrentPostOfInterest) 1f else 0f),
painter = painterResource(id = com.tinytap.R.drawable.post_of_interest),
contentDescription = null
)
Text(
modifier = Modifier.padding(top = 10.dp),
fontSize = 16.sp,
color = Color.White,
text = model.title,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = model.author,
fontSize = 12.sp,
color = Color.LightGray,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
The issue is that I am using a fixed size for both my Image and AsyncImage but sometimes the API gives me images that are very wide, causing me to have the following inconsistency in the UI -
How can I make it that my images show up exactly the same? I tried using all kind of crops but the results ended up messing my image
Putting into consideration that image might be shorter, taller, wider or smaller.
To solve this issue, I recommend you to use Coil here is a sample of code that will solve your issue :
Card(
modifier = Modifier.size(119.dp, 92.dp),
shape = RoundedCornerShape(10.dp)
) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(imageURL)
.build(),
placeholder = painterResource(R.drawable.complex_placeholder),
error = painterResource(R.drawable.complex_placeholder),
contentDescription = "complex image",
contentScale = ContentScale.Crop,//The line that will affect your image size and help you solve the problem.
)
}
The above code will always show fully covered box with image for any case, also don't forget to determine size of container (Card in my example '119,92' ).
To know more about different attributes and their effect on your code, select what suits you the best
Check more here (reference of image attached) : Content scaletype fully illustrated

How to draw gradient and customize your splash screen in compose?

I am trying to have a splash screen in our application and I got stuck Abit with the jetpack Compose design. So I want to have a background gradient, I am now using the image which does not fit well in the phone and want to center my logo and text in the middle of the screen how can I achieve that. Mostly centering since I have tried the gradient part and I have no success. Here is my code
Here is my background component
#Composable
fun BackgroundComponents(
#DrawableRes backgroundDrawableRes: Int,
contentDescription: String?,
modifier: Modifier = Modifier,
painter: Painter,
alignment: Alignment = Alignment.Center,
) {
Box(
modifier = modifier
) {
Image(
painter = painterResource(id = backgroundDrawableRes),
contentDescription = contentDescription,
modifier = modifier.matchParentSize()
)
Box(
contentAlignment = Alignment.Center
) {
Image(
painter = painter,
contentDescription = contentDescription,
alignment = alignment
)
}
Text(
modifier =
modifier.padding(top = 36.dp),
text = "Hello and welcome to our app",
color = (colorResource(id = R.color.white)),
fontSize = 16.sp,
)
}
}
This is how I am calling it on the Screen
#Composable
fun Splash(modifier: Modifier = Modifier) {
Column(modifier = modifier.fillMaxSize()) {
BackgroundComponents(
backgroundDrawableRes = R.drawable.ic_launcher_foreground,
contentDescription = "",
modifier = modifier.fillMaxSize(),
painter = painterResource(id = coil.base.R.drawable.notification_bg)
)
}
}
I would like to push the icon and text in the middle and centered, also instead of using an image can I draw that gradient?
You can apply the gradient to the parent Box as background modifier and then just apply the expected alignment to the composable inside the Box.
Something like:
Box(
modifier = Modifier
.fillMaxSize()
.background(
Brush.horizontalGradient(
colors = listOf(
Color.Blue,
Teal200
)
)
),
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Image(
painter = painterResource(id = R.drawable.xx),
contentDescription = "contentDescription",
)
Spacer(Modifier.height(36.dp))
Text(
text = "Hello and welcome to our app",
color = White,
fontSize = 16.sp,
)
}
}

I don't know where my background comes from

I have developed my bottom sheet in Compose.
The goal is to have the top of the bottom sheet (where the picture is) to be transparent to see the background picture.
The rest of the bottom sheet with the text will have a background
Here is what I came up with:
#ExperimentalMaterialApi
#Composable
fun EntryFragment() {
val bottomSheetScaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberBottomSheetState(BottomSheetValue.Collapsed)
)
BottomSheetScaffold(
scaffoldState = bottomSheetScaffoldState,
sheetContent = {
Box(
Modifier
.fillMaxWidth()
.fillMaxHeight().background(Color.Transparent)
) {
Column(Modifier.background(Color.Transparent)) {
Image(
painter = painterResource(R.drawable.main_screen_picture),
contentDescription = "Picture",
/*contentScale = ContentScale.Crop, */
modifier = Modifier.width(150.dp).height(150.dp)
)
Box(
Modifier
.fillMaxWidth()
.fillMaxHeight()
.background(Color.Blue)
){
Text(text = "Hello from sheet")
}
}
}
}, sheetPeekHeight = 600.dp
, modifier = Modifier.background(Color.Green)
) {
//Under the bottom sheet
Image(
painter = painterResource(R.drawable.main_screen_background),
contentDescription = "Background",
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxWidth()
)
}
}
I have this issue where there is a white/black (depending on day/night) background put next to my picture.
Apparently it comes from the column, but everything has a transparent background.
I put a green background in my bottom sheet, and it is not shown, so the issue must come from above.
Where this issue comes from?
It's controlled by sheetBackgroundColor parameter of BottomSheetScaffold. As the next step you probably gonna need to disable shadows too:
sheetBackgroundColor = Color.Transparent,
sheetElevation = 0.dp,
Try to put your background as a first Modifier because the order matters. For example:
Box(
Modifier
.background(Color.Transparent)
.fillMaxWidth()
.fillMaxHeight()
)

Jetpack compose design like twitter header

How can we achieve this kind of layout in jetpack compose?
I am interested in positioning the round picture 'GD', on top of the header image like it is here. I tried to use Box layout like this
Box(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
Column(){
Coil(
modifier = Modifier
.fillMaxWidth()
.height(200.dp),
)
}
Coil(
modifier = Modifier
.height(120.dp)
.width(120.dp)
.padding(top = 140.dp, start = 20.dp)
.clip(CircleShape),
contentScale = COntentScale.Crop
)
}
but this is not taking correct shape.
Thanks.
You can use a Box.
Align the circular in the Box with the align(BottomStart) modifier and then apply an offset and finally clip the Image in a CircleShape.
Something like:
Box(Modifier.padding(top=40.dp)){
Image(
painterResource(/* ... */ ),
"contentDescription",
)
Image(
painter = rememberImagePainter("...."),
modifier = Modifier
.height(50.dp)
.width(50.dp)
.align(BottomStart) //align in the Box
.offset(12.dp, 25.dp) //apply an offset
.clip(CircleShape) //clip the image
.border(color= White, shape = CircleShape, width= 2.dp),
contentDescription = "",
contentScale = ContentScale.Crop
)
Note: rememberImagePainter requires the coil-compose implementation.

Android Jetpack Compose - Image can't scale to box's width and Height

Created ImageCard view for creating the list in android jetpack compose
but some images can't scratch to Box widget's width and height.
Using 640*427 image and output like image 1.
Using 6720*4480 image and it's looking good like image 2.
Use below code to create ImageCard.
Usage of ImageCard function: Call ImageCardData function in setContent{} function
#Composable
fun ImageCard(
painter: Painter,
title: String,
contentDescription: String,
modifier: Modifier = Modifier
) {
Card(
modifier = modifier.fillMaxWidth(),
shape = RoundedCornerShape(10.dp),
elevation = 5.dp
) {
Box(
modifier = Modifier.height(200.dp)
) {
Image(
painter = painter,
contentDescription = contentDescription,
contentScale = ContentScale.Crop
)
Box(
modifier = Modifier
.fillMaxSize()
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Black
),
startY = 50f
)
)
)
Box(
modifier = Modifier
.fillMaxSize()
.padding(12.dp),
contentAlignment = Alignment.BottomStart
) {
Text(
text = title,
style = TextStyle(color = Color.White, fontSize = 16.sp)
)
}
}
}
}
#Composable
fun ImageCardData() {
val painter = painterResource(id = R.drawable.engagement)
val title = "Sample Text Title"
val description = "This is sample Image Description"
Box(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
ImageCard(
painter = painter,
title = title,
contentDescription = description
)
}
}
Your image view size gets calculated by it content, because it doesn't have any size modifiers.
Add fillMaxSize to the image:
Image(
painter = painter,
contentDescription = contentDescription,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize()
)
It depends by the Image implementation with a Painter
Creates a composable that lays out and draws a given Painter. This will attempt to size the composable according to the Painter's intrinsic size. However, an optional Modifier parameter can be provided to adjust sizing or draw additional content (ex. background)
It means that using an 640*427 image in a parent container with larger dimensions the Image composable size is the original size of the Painter.
The scale factor applied by the ContentScale is based on these dimensions and source = destination and doesn't change the intrinsic size of the original Painter.
Image(
painter = painter,
contentDescription = contentDescription,
contentScale = ContentScale.Crop
)
Using a 6720*4480 image the Image size is larger than the parent container and in this way the Image composable fills all the available space.
In your case you can solve using the modifier fillMaxWidth() in your Image
Image(
modifier =Modifier.fillMaxWidth(),
painter = painter,
contentDescription = contentDescription,
contentScale = ContentScale.Crop
)
In this way the Image composable fills the parent space.

Categories

Resources