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()
){
}
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:
- Replace
android:layout_toEndOf="@+id/others_message_body"
withandroid:layout_alignParentStart="true"
in theImageView
- Give the
ImageView
anid
, such asandroid:id="@+id/imageViewId"
- Align the
TextView
to the end of theImageView
by addingandroid: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
Long Reply vs 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
Nullpointerexception from Google Maps
Refresh or Force Redraw the Fragment
Size of Android Notification Bar and Title Bar
Highlighting the Selected Item in the Listview in Android
Android Sax Parser Not Getting Full Text from Between Tags
How to Delete from Firebase Realtime Database
Video Compression on Android Using New Mediacodec Library
My Android Camera Uri Is Returning a Null Value, But the Samsung Fix Is in Place, Help
Inflate Layout Programmatically Within Another Layout
Proxy Which Requires Authentication with Android Emulator
Add an Image from Url into Custom Infowindow Google Maps V2
Android Can't Record Video with Front Facing Camera, Mediarecorder Start Failed: -19