Create a Chat Bubble in Android

Jetpack Compose create chat bubble with arrow and border/elevation

You can define your custom Shape.

For example you can define a Triangle using:

class TriangleEdgeShape(val offset: Int) : Shape {

override fun createOutline(
size: Size,
layoutDirection: LayoutDirection,
density: Density
): Outline {
val trianglePath = Path().apply {
moveTo(x = 0f, y = size.height-offset)
lineTo(x = 0f, y = size.height)
lineTo(x = 0f + offset, y = size.height)
}
return Outline.Generic(path = trianglePath)
}
}

You can also extending the RoundedCornerShape adding the little triangle in the bottom right corner.

Then you can define something like:

Row(Modifier.height(IntrinsicSize.Max)) {
Column(
modifier = Modifier.background(
color = Color.xxx,
shape = RoundedCornerShape(4.dp,4.dp,0.dp,4.dp)
).width(xxxx)
) {
Text("Chat")
}
Column(
modifier = Modifier.background(
color = Color.xxx,
shape = TriangleEdgeShape(10))
.width(8.dp)
.fillMaxHeight()
){
}

Sample Image

Android chat bubble outlined custom design

you can achieve by this 9patch image method through android studio.

Align chat bubble to the left of the RecyclerView

Both your layouts are aligned to the right. You want the others_message.xml to be aligned to the left.

You want your ImageView to be aligned to the start of the parent. And then, you want the TextView to be aligned to the end of that ImageView.

Therefore, you're gonna want to do the following:

  1. Replace android:layout_toEndOf="@+id/others_message_body" with android:layout_alignParentStart="true" in the ImageView
  2. Give the ImageView an id, such as android:id="@+id/imageViewId"
  3. Align the TextView to the end of the ImageView by adding android:layout_alignEnd="@id/imageViewId"

The final result of others_message.xml should look something like this:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingStart="15dp"
android:paddingTop="10dp"
android:paddingEnd="60dp"
android:paddingBottom="10dp">

<TextView
android:id="@+id/others_message_body"
style="@style/ChatBubble"
android:background="@drawable/others_message"
android:layout_alignEnd="@id/imageViewId"
tools:text="Hey! I am a stranger, i'm chatting with you right now! :)" />

<ImageView
android:id="@+id/imageViewId"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignTop="@id/others_message_body"
android:layout_alignBottom="@id/others_message_body"
android:layout_marginStart="10dp"
android:layout_alignParentStart="true"
android:contentDescription="@string/user_avatar"
app:srcCompat="@drawable/ic_user_avatar">

</ImageView>

</RelativeLayout>

android chat bubble with reply UI

I think it would be better for you to use ConstraintLayout in this case.

You want the replyUI width to always match the constraint making it go until to the end of chat_parent but at the same time you want its minimum width constrained to its own content width.

chat_parent width needs to be wrap_content, it will have the width decided by either replyUI (if replyToTxt is longer than the sentTxt) or sentTxt (if sentTxt is longer than replyToTxt)

Using app:layout_constraintWidth_min="wrap" in replyUI is the key to achieving the desired effect

I've played around a little bit changing the dimension, drawables and color values of your snippet just to give you an example. You would probably need to tweak some values (like gravity, maxLines, maxWidth and constraints margins)

Short Reply vs Long Sent Text

Short Reply vs Long Sent Text

Long Reply vs Short Sent Text
Long Reply Short Sent Text

Here is the .xml for these

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/black">

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/chat_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:background="@color/purple_500"
android:elevation="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/replyUI"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:background="@color/purple_200"
android:clickable="true"
android:elevation="4dp"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:maxWidth="160dp"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_min="wrap">

<TextView
android:id="@+id/replyToName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/purple_500"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="You" />

<TextView
android:id="@+id/replyToTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:maxWidth="160dp"
android:textColor="@color/white"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/replyToName"
tools:text="This is a long text" />
</androidx.constraintlayout.widget.ConstraintLayout>

<TextView
android:id="@+id/sentTxt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="4dp"
android:layout_marginBottom="4dp"
android:autoLink="all"
android:maxWidth="160dp"
android:textColor="@color/white"
android:textColorLink="@color/purple_500"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/replyUI"
tools:text="Hi" />

</androidx.constraintlayout.widget.ConstraintLayout>

<TextView
android:id="@+id/timeStamp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:drawablePadding="4dp"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/chat_parent"
app:layout_constraintTop_toBottomOf="@+id/chat_parent"
tools:text="13:45" />

</androidx.constraintlayout.widget.ConstraintLayout>


Related Topics



Leave a reply



Submit