Android drawable speech bubble
Asked Answered
V

6

59

I've looked for days and can not find any good leads on how I can draw a bubble or where a draw 9 patch images is to use as a background. I am a terrible artist. Can anyone help?

The best sample I found is here on Stack Overflow, but it's written in Objective C.

How to draw a "speech bubble" on an iPhone?

Vamp answered 2/11, 2011 at 1:29 Comment(2)
Have you tried using a image and making it a nine patch?Shirk
Check My Answer. This is exactly what you need.Economic
E
90

If you are creating a chat screen you are probably going to want to implement an incoming speech bubble and an outgoing speech bubble. Here is how I did that :

shape_bg_incoming_bubble.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="-45"
            android:pivotX="0%"
            android:pivotY="0%"
            android:toDegrees="0" >
            <shape android:shape="rectangle" >
                <solid android:color="@color/primary" />
            </shape>
        </rotate>
    </item>
    <item android:left="16dp">
        <shape android:shape="rectangle" >
            <solid android:color="@color/primary" />
            <corners android:radius="4dp" />
        </shape>
    </item>
</layer-list>

shape_bg_outgoing_bubble.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="45"
            android:pivotX="100%"
            android:pivotY="0%"
            android:toDegrees="0" >
            <shape android:shape="rectangle" >
                <solid android:color="@color/grey_500" />
            </shape>
        </rotate>
    </item>
    <item android:right="16dp">
        <shape android:shape="rectangle" >
            <solid android:color="@color/grey_500" />
            <corners android:radius="4dp" />
        </shape>
    </item>
</layer-list>
Employer answered 25/6, 2016 at 2:42 Comment(4)
How do I rotate the entire shape in .xml file? Shows up as vertical when I try to implement it in layout fileFarseeing
How to give corner radius for the top right corner in shape_bg_incoming_bubble.xmlNiche
To fix this missing corner radius replace <solid android:color="@color/grey_500" /> within the first item with <stroke android:width="8dp" android:color="@color/grey_500" /> and set android:width="8dp" to TWICE your radius. (If you have have a radius of 4dp set it to 8dp.)Bronchiole
any of this will not look proper if colors were transparentAlonzo
R
78

I know its bit too late for this. For those, who don't want to use 9-patch images yet want to cast shadows from speech bubble. This is closest I could get to WhatsApp speech bubble. And thanks to @toobsco42 for the answer above.

Here you go..

Incoming Speech Bubble :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!--Shadow Layers-->

<item>
    <rotate
        android:fromDegrees="-35"
        android:pivotX="0%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp"/>
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px"/>
            <solid android:color="#01000000" />
        </shape>
    </rotate>
</item>
<item android:left="8dp">
    <shape android:shape="rectangle">
        <padding
            android:bottom="1px"
            android:left="1px"
            android:right="1px"/>
        <solid android:color="#01000000" />
        <corners android:radius="8dp" />
    </shape>
</item>

<!--===============-->
<item>
    <rotate
        android:fromDegrees="-35"
        android:pivotX="0%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp"/>
            <padding
                android:bottom="1px" />
            <solid android:color="#09000000" />
        </shape>
    </rotate>
</item>
<item android:left="8dp">
    <shape android:shape="rectangle">
        <padding
            android:bottom="1px" />
        <solid android:color="#09000000" />
        <corners android:radius="8dp" />
    </shape>
</item>

<!--===============-->

<item>
    <rotate
        android:fromDegrees="-35"
        android:pivotX="0%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp"/>
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px"/>
            <solid android:color="#10000000" />
        </shape>
    </rotate>
</item>
<item android:left="8dp">
    <shape android:shape="rectangle">
        <padding
            android:bottom="1px"
            android:left="1px"
            android:right="1px"/>
        <solid android:color="#10000000" />
        <corners android:radius="8dp" />
    </shape>
</item>

<!--ForeGround-->

<item>
    <rotate
        android:fromDegrees="-35"
        android:pivotX="0%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp"/>
            <solid android:color="@color/colorWhite" />
        </shape>
    </rotate>
</item>
<item android:left="8dp">
    <shape android:shape="rectangle">
        <solid android:color="@color/colorWhite" />
        <corners android:radius="8dp" />
    </shape>
</item>

</layer-list>

Outgoing Speech Bubble :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!--Shadow Layer-->

<item>
    <rotate
        android:fromDegrees="40"
        android:pivotX="100%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp" />
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px" />
            <solid android:color="#01000000" />
        </shape>
    </rotate>
</item>
<item android:right="10dp">
    <shape android:shape="rectangle">
        <corners android:radius="4dp" />
        <padding
            android:bottom="1px"
            android:left="1px"
            android:right="1px" />
        <solid android:color="#01000000" />
    </shape>
</item>

<!--===============-->

<item>
    <rotate
        android:fromDegrees="40"
        android:pivotX="100%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp" />
            <padding android:bottom="1px" />
            <solid android:color="#09000000" />
        </shape>
    </rotate>
</item>
<item android:right="10dp">
    <shape android:shape="rectangle">
        <corners android:radius="4dp" />
        <padding android:bottom="1px" />
        <solid android:color="#09000000" />
    </shape>
</item>

<!--===============-->

<item>
    <rotate
        android:fromDegrees="40"
        android:pivotX="100%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <corners android:radius="4dp" />
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px" />
            <solid android:color="#10000000" />
        </shape>
    </rotate>
</item>
<item android:right="10dp">
    <shape android:shape="rectangle">
        <corners android:radius="4dp" />
        <padding
            android:bottom="1px"
            android:left="1px"
            android:right="1px" />
        <solid android:color="#10000000" />
    </shape>
</item>

<!--===============-->


<!--ForeGround-->

<item>
    <rotate
        android:fromDegrees="40"
        android:pivotX="100%"
        android:pivotY="0%"
        android:toDegrees="0">
        <shape android:shape="rectangle">
            <solid android:color="#CBEBFC" />
        </shape>
    </rotate>
</item>
<item android:right="10dp">
    <shape android:shape="rectangle">
        <solid android:color="#CBEBFC" />
        <corners android:radius="4dp" />
    </shape>
</item>

</layer-list>

Use the paddings properly in the layout. I used these values :

<TextView
    android:id="@+id/text_message_incoming"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:background="@drawable/bg_speech_bubble_incoming"
    android:lineSpacingExtra="2dp"
    android:paddingLeft="20dp"
    android:paddingTop="4dp"
    android:paddingRight="10dp"
    android:paddingBottom="10dp"
    android:text="Hi, How are you?"
    android:textColor="@color/colorBlack"
    android:textSize="13.5dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintWidth_max="wrap"
    app:layout_constraintWidth_percent="0.8" />

My output came out like this:

enter image description here

Rockabilly answered 27/3, 2019 at 13:4 Comment(3)
@HarviSirja Oh great :DCalorie
Very good answer but there is a problem when the bubble is small enough, width of rectangle is smaller than width of the triangle, triangle overflows from the left side. Any solution to clip triangle?Victor
I wish I could help you. I've quit native and switched to Flutter now. You can try tweaking degrees or pivot values. If you're able to get it, feel free to edit my answer here.Rockabilly
M
48

Here is a simple speech bubble drawable I made. Hopefully, it's start in the right direction for someone. The view that this drawable is used in needs a height of at least 70-80dp and a similar minimum width to show properly.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:top="30dp">
        <rotate
            android:fromDegrees="-45"
            android:pivotX="0%"
            android:pivotY="0%"
            android:toDegrees="0" >
            <shape android:shape="rectangle" >
                <solid android:color="#CCC" />
            </shape>
        </rotate>
    </item>
    <item android:left="20dp">
        <shape android:shape="rectangle" >
            <solid android:color="#CCC" />

            <corners android:radius="5dp" />
        </shape>
    </item>

</layer-list>

Android Drawables leave a lot to be desired in terms of how usable they are for drawing anything even slightly complex.

This version looks like this:

Old speech bubble version

UPDATE I've been working on XML speech bubbles again and was a little dissatisfied with my 2014 solution. In 2018, we have vector drawables which enable better solutions than the one above. Here are some more modern alternatives. They allow things like small messages and transparency.

speech_bubble_simple_user.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >

    <item
        android:bottom="@dimen/speech_bubble_tail"
        tools:width="100dp"
        tools:height="50dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_user"/>
            <corners
                android:topLeftRadius="@dimen/speech_bubble_corners"
                android:topRightRadius="@dimen/speech_bubble_corners"
                android:bottomRightRadius="0dp"
                android:bottomLeftRadius="@dimen/speech_bubble_corners"/>
        </shape>
    </item>

    <item
        android:width="@dimen/speech_bubble_tail"
        android:height="@dimen/speech_bubble_tail"
        android:gravity="bottom|right">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_tail"
            android:height="@dimen/speech_bubble_tail"
            android:viewportWidth="25.0"
            android:viewportHeight="25.0">
            <path
                android:pathData="M25,25 25,0 0,0z"
                android:fillColor="@color/speech_bubble_user"/>
        </vector>
    </item>

</layer-list>

speech_bubble_simple_agent.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >

    <item
        android:bottom="@dimen/speech_bubble_tail"
        tools:width="100dp"
        tools:height="50dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_agent"/>
            <corners
                android:topLeftRadius="@dimen/speech_bubble_corners"
                android:topRightRadius="@dimen/speech_bubble_corners"
                android:bottomLeftRadius="0dp"
                android:bottomRightRadius="@dimen/speech_bubble_corners"/>
        </shape>
    </item>

    <item
        android:width="@dimen/speech_bubble_tail"
        android:height="@dimen/speech_bubble_tail"
        android:gravity="bottom|left">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_tail"
            android:height="@dimen/speech_bubble_tail"
            android:viewportWidth="25.0"
            android:viewportHeight="25.0">
            <path
                android:pathData="M0,25 25,0 0,0z"
                android:fillColor="@color/speech_bubble_agent"/>
        </vector>
    </item>

</layer-list>

The two above look like this: (These versions don't quite work with transparency and I'm not sure why when the versions below seem to work fine.)

Two simple speech bubbles

speech_bubble_nine_patch_user.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >

    <item
        android:left="@dimen/speech_bubble_corners"
        android:right="@dimen/speech_bubble_corners_plus_tail"
        android:bottom="@dimen/speech_bubble_spacing"
        tools:width="50dp"
        tools:height="50dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_user"/>
        </shape>
    </item>

    <item
        android:top="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_corners_plus_tail"
        android:gravity="left"
        android:width="@dimen/speech_bubble_corners">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_user"/>
        </shape>
    </item>

    <item
        android:top="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_corners_plus_tail"
        android:right="@dimen/speech_bubble_spacing"
        android:gravity="right"
        android:width="@dimen/speech_bubble_corners">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_user"/>
        </shape>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners"
        android:height="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_spacing"
        android:gravity="bottom|left">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners"
            android:height="@dimen/speech_bubble_corners"
            android:viewportWidth="10.0"
            android:viewportHeight="10.0">
            <path
                android:pathData="M0,0 A10,10 0 0,0 10,10 L10,0 Z"
                android:fillColor="@color/speech_bubble_user"/>
        </vector>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners"
        android:height="@dimen/speech_bubble_corners"
        android:right="@dimen/speech_bubble_spacing"
        android:gravity="top|right">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners"
            android:height="@dimen/speech_bubble_corners"
            android:viewportWidth="10.0"
            android:viewportHeight="10.0">
            <path
                android:pathData="M10,10 A10,10 0 0,0 0,0 L0,10 Z"
                android:fillColor="@color/speech_bubble_user"/>
        </vector>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners"
        android:height="@dimen/speech_bubble_corners"
        android:gravity="top|left">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners"
            android:height="@dimen/speech_bubble_corners"
            android:viewportWidth="10.0"
            android:viewportHeight="10.0">
            <path
                android:pathData="M10,0 A10,10 0 0,0 0,10 L10,10 Z"
                android:fillColor="@color/speech_bubble_user"/>
        </vector>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners_plus_tail"
        android:height="@dimen/speech_bubble_corners_plus_tail"
        android:gravity="bottom|right">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners_plus_tail"
            android:height="@dimen/speech_bubble_corners_plus_tail"
            android:viewportWidth="150.0"
            android:viewportHeight="150.0">
            <path
                android:pathData="M0,100 C7.67309143,100 14.1935201,100.346373 20.500756,99.0996492 C43.6628959,129.872031 94.1698247,146.306561 150.320843,150.792562 C113.168693,130.799632 87.2808993,98.5054948 81.0808824,68.6524321 C94.1277117,51.7595331 100,23.9957121 100,0 L0,0 L0,100 Z"
                android:fillColor="@color/speech_bubble_user"/>
        </vector>
    </item>

</layer-list>

speech_bubble_nine_patch_agent.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" >

    <item
        android:left="@dimen/speech_bubble_corners_plus_tail"
        android:right="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_spacing"
        tools:width="50dp"
        tools:height="50dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_agent"/>
        </shape>
    </item>

    <item
        android:top="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_corners_plus_tail"
        android:left="@dimen/speech_bubble_spacing"
        android:gravity="left"
        android:width="@dimen/speech_bubble_corners">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_agent"/>
        </shape>
    </item>

    <item
        android:top="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_corners_plus_tail"
        android:gravity="right"
        android:width="@dimen/speech_bubble_corners">
        <shape android:shape="rectangle">
            <solid android:color="@color/speech_bubble_agent"/>
        </shape>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners"
        android:height="@dimen/speech_bubble_corners"
        android:bottom="@dimen/speech_bubble_spacing"
        android:gravity="bottom|right">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners"
            android:height="@dimen/speech_bubble_corners"
            android:viewportWidth="10.0"
            android:viewportHeight="10.0">
            <path
                android:pathData="M0,10 A10,10 0 0,0 10,0 L0,0 Z"
                android:fillColor="@color/speech_bubble_agent"/>
        </vector>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners"
        android:height="@dimen/speech_bubble_corners"
        android:gravity="top|right">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners"
            android:height="@dimen/speech_bubble_corners"
            android:viewportWidth="10.0"
            android:viewportHeight="10.0">
            <path
                android:pathData="M10,10 A10,10 0 0,0 0,0 L0,10 Z"
                android:fillColor="@color/speech_bubble_agent"/>
        </vector>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners"
        android:height="@dimen/speech_bubble_corners"
        android:left="@dimen/speech_bubble_spacing"
        android:gravity="top|left">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners"
            android:height="@dimen/speech_bubble_corners"
            android:viewportWidth="10.0"
            android:viewportHeight="10.0">
            <path
                android:pathData="M10,0 A10,10 0 0,0 0,10 L10,10 Z"
                android:fillColor="@color/speech_bubble_agent"/>
        </vector>
    </item>

    <item
        android:width="@dimen/speech_bubble_corners_plus_tail"
        android:height="@dimen/speech_bubble_corners_plus_tail"
        android:gravity="bottom|left">
        <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="@dimen/speech_bubble_corners_plus_tail"
            android:height="@dimen/speech_bubble_corners_plus_tail"
            android:viewportWidth="150.0"
            android:viewportHeight="150.0">
            <path
                android:pathData="M150,100 L150,0 L50,0 C50,11.9054549 52.5180742,22.2130322 55.2200144,32.2289993 C59.25,47.1679688 65.7054859,60.8615415 68.15625,65.5820312 C55.2200144,107.207031 41.7460938,127.800781 0,151 C61.5311854,147.539062 101.691406,129.675781 124.615295,97.6602593 C132.823321,99.8389881 141.106342,100 150,100 Z"
                android:fillColor="@color/speech_bubble_agent"/>
        </vector>
    </item>

</layer-list>

The two above look like this:

Speech bubbles with curly tails

dimens.xml (for both)

<dimen name="speech_bubble_corners">10dp</dimen>
<dimen name="speech_bubble_corners_plus_tail">15dp</dimen>
<dimen name="speech_bubble_spacing">5dp</dimen>
<dimen name="speech_bubble_tail">25dp</dimen>
Morelock answered 22/12, 2014 at 17:31 Comment(18)
I like the new ones, but they seem to need api >= 23.Ifni
Good point. They are using vector, which is only API 21 and above I think. It looks wrong on API 21 for me. It's showing as a single rectangle. I'm not sure why that is. One option is to have two set of drawables (and possibly layouts as well). The ones for below 23 in drawable and the ones with vectors in drawable-v23.Morelock
My IDE say the width/height fields are only considered in 23 and above. Therefore with api 21/22 the android isnt able to puzzle the bubble correctly. For the vector-items it just explains, they are not allowed on the position you placed them (with min api 21 for me).Ifni
you can extract the vectors into separate xml and access them inside the item tag. As per the width and height you can play with the size tagCruickshank
@DominikusK. I had the same thing with the width. Removing them changed nothing to the bubble except for the width in second item tag. Replacing that width with "right" fixed it for me. Same with the other bubble, replacing with "left"... Not saying this is ideal, but it worked and all my messages display correctly without those annoying warnings in android studio.Eberhard
In my 2014 answer, I assumed that people could just work that out. toobsco42's versions have both. With the newer vector based versions I included both sides. I'd recommend using those or VipiN Negi's drawables are really nice looking and have very good backwards compatibility. You can now use app:srcCompat to get the vector versions working on older API versions but they get stretched out as they are first converted to PNGs. developer.android.com/guide/topics/graphics/…Morelock
nice, how can you draw a stroke line around the bubbles that will match the shape of the bubbles?Rakish
@ZlilKorman I think creating new path below the current paths in the vector sections of the XML that are exact copies and then use a stroke with no fill. Then remove the bits of the paths that you don't want e.g. the simple L bits and the Z that connects to the start. Not super easy. The easier solution would be to do like VipiN Negi's example and make a larger one behind though that won't be exact.Morelock
@Morelock thanks, That's too much effort to take ;)Rakish
This is better then 9 patch image, Nice Solution,, great..!Fibrinolysis
@Morelock Did you use some tool to draw the bubble's tip (The <path> elements)Douse
@RosenDimov You can use any vector drawing program that can save as SVG (e.g. InkScape, GIMP, Adobe Illustrator, Sketch). You can import the SVG files as Android Vectors (Right click on a folder in the Project window on Android Studio > New > Vector Asset). The SVGs need to be SVG 1.0 only to convert. Higher version things can fail to convert (e.g. text, mask). You can manually move the paths from the <path d= to android:pathData=, if you can't get them to convert. You can also edit the paths by hand but it's extremely slow and confusing to understand SVG path syntax.Morelock
Thanks much for the reply. I actually tried with InkScape first, but a nice looking baloon on desktop would look very odd on the phone itself after conversion to Android vector. What I saw in the SVG from InkScape is version 1.0 which is fine, but also a lot of metadata in the markup and the paths didn't look like traditional SVG to me at least (they had letters like H and V, I expected the traditional M, L, C markers). I'm not UX designer and I'm almost sure I'm doing something wrong (and probably if I ever participate in Android project, I won't be donig that).Douse
But just for practice, I wanted to change a bit the curves and orientation of the baloon in your answer and as you mention, ended up doing lots of calculation to maintain ratios and that sort of stuff. Probably I'll consult a designer in the future, as coding SVG isn't practical at all as I see. :) Thanks!Douse
And just out of curiousity, for your latest solution, is there a reason to keep nine_patch in the name when it's vector graphics? (Sorry for the many comments, but SO woudn't allow me edit my latest comment several times).Douse
When I created this, I think I would have started with a circle and cut it and added straight line paths to make a quarter circle vector. Then I would create two curve that close as a path for the bit coming out I would move that independently of the quarter circle until I found a position that I liked and edit and try out different curves. Then I'd copy the shapes, move them somewhere else, join the two copied shapes to make one vector shape. If I wanted to try more different positions, I'd make more copies. Then put an artboard around the final version the I liked.Morelock
I would be unlikely to use nine_patch in the name in a real project. I'd call it something like speech_bubble_agent.xml. Though the way it works is conceptually the same a nine patch PNG.Morelock
The corners and tail work great, and the sides scale, but that center square, that's 50dp by 50dp, when I use this in my view, that part didn't stretch. I removed the height and width, and it looked wonky on the design page, but worked great in use.Endo
A
16

just in case anyone needs another style of bubble here you go tnx @vipin Negi

chat_receiver_bubble.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!--Shadow Layer-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <corners android:radius="100dp" />
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px" />
            <solid android:color="#01000000" />
        </shape>
    </item>

    <!--===============-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <corners android:radius="100dp" />
            <padding android:bottom="1px" />
            <solid android:color="#09000000" />
        </shape>
    </item>

    <!--===============-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <corners android:radius="100dp" />
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px" />
            <solid android:color="#10000000" />
        </shape>
    </item>

    <!--===============-->


    <!--ForeGround-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/app_color" />
            <corners android:bottomLeftRadius="0dp" android:radius="100dp" />
        </shape>
    </item>

</layer-list>

chat_sender_bubble.xml

<?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!--Shadow Layer-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <corners android:radius="100dp" />
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px" />
            <solid android:color="#01000000" />
                </shape>
    </item>

    <!--===============-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <corners android:radius="100dp" />
            <padding android:bottom="1px" />
            <solid android:color="#09000000" />
        </shape>
    </item>

    <!--===============-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <corners android:radius="100dp" />
            <padding
                android:bottom="1px"
                android:left="1px"
                android:right="1px" />
            <solid android:color="#10000000" />
        </shape>
    </item>

    <!--===============-->


    <!--ForeGround-->


    <item android:right="10dp">
        <shape android:shape="rectangle">
            <solid android:color="@color/settings_bg" />
            <corners android:bottomRightRadius="0dp" android:radius="100dp" />
        </shape>
    </item>

</layer-list>

use like this

<RelativeLayout
            android:gravity="center"
            android:id="@+id/chatLayout"
            android:background="@drawable/chat_receiver_bubble" //or @drawable/chat_sender_bubble
            android:visibility="gone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
            <TextView
                android:textSize="14sp"
                android:textColor="@color/text_colour"
                android:id="@+id/message"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:text=""
                android:fontFamily="@font/regular"/>
        </RelativeLayout>

final look

enter image description here

Adjuvant answered 20/6, 2020 at 21:16 Comment(2)
hey nice one :)Rockabilly
If the box gets too tall, then the border radius grows massively. So a full page message breaks it :(Endo
T
4

You should make an image in some kind of image editor and then create a 9 patch out of it. You can set the area you would like content to be using the 9 patch method. Then you can simply have a TextView with the background set to your 9 patch. Have a look at an app called Bnter on the market, it uses speech bubbles to display conversations similar to what you are looking for.

Thatcher answered 2/11, 2011 at 2:45 Comment(0)
W
3

Here I have created for incoming and outgoing messages by following this Android make oval background drawable with chat corner

itemincoming.xml

<?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"
    app:cardElevation="1dp"
    android:layout_margin="2dp"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="16dp"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Hii how are you ?  11:37"
                android:paddingStart="16dp"
                android:paddingTop="10dp"
                android:paddingEnd="12dp"
                android:paddingBottom="8dp"
                android:textColor="@color/white"
                android:background="@drawable/testrect"/>

            <ImageView
                android:layout_marginTop="-1.5dp"
                android:layout_width="8dp"
                android:layout_height="16dp"
                android:layout_gravity="start"
                android:background="@drawable/testcorner"
                />

        </LinearLayout>


    </RelativeLayout>
</RelativeLayout>

testrect.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#E26841" />
    <corners
        android:bottomRightRadius="5dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="5dp"/>

</shape>

testcorner.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="45"
            android:pivotX="135%"
            android:pivotY="15%"
            android:toDegrees="45"
            >
            <shape android:shape="rectangle">
                <solid android:color="#E26841"/>

            </shape>
        </rotate>
    </item>
</layer-list>

outgoing.xml

<?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"
    app:cardElevation="1dp"
    android:layout_margin="2dp"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="16dp"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="end"
                android:text="11:37 Hii how are you ?"
                android:paddingStart="16dp"
                android:paddingTop="10dp"
                android:paddingEnd="12dp"
                android:paddingBottom="8dp"
                android:textColor="@color/txtcolor_commn"
                android:background="@drawable/testrecty"/>

            <ImageView
                android:layout_marginTop="-4.5dp"
                android:layout_marginRight="4.5dp"
                android:layout_width="8dp"
                android:layout_height="16dp"
                android:layout_gravity="end"
                android:rotation="90"
                android:background="@drawable/testcornery"
                />

        </LinearLayout>

    </RelativeLayout>
</RelativeLayout>

testrecty.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/white" />
    <corners
        android:bottomLeftRadius="5dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="5dp"/>

</shape>

testcornery.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <rotate
            android:fromDegrees="45"
            android:pivotX="135%"
            android:pivotY="15%"
            android:toDegrees="45"
            >
            <shape android:shape="rectangle">
                <solid android:color="@color/white"/>

            </shape>
        </rotate>
    </item>
</layer-list>

now its look like this

enter image description here

Whoa answered 1/7, 2020 at 15:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.