Выводной пузырь речи для Android

Я искал дни и не могу найти никаких хороших примеров, как я могу нарисовать пузырь или где в качестве фона можно использовать 9 патч-изображений. я ужасный художник --Can кто-нибудь помогает?

лучший образец, который я нашел, находится здесь, в stackoverflow, но он написан в объективе c

Как нарисовать "пузырь речи" на iPhone?

спасибо

Ответ 1

Если вы создаете экран чата, вероятно, вам захочется реализовать входящий речевой пузырь и исходящий пузырь речи. Вот как я это сделал:

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>

Ответ 2

Вот простой речевой пузырь, который я нарисовал. Надеюсь, это начнется в правильном направлении для кого-то. Представление о том, что это рисование используется, нуждается в высоте не менее 70-80 dp и аналогичной минимальной ширине для правильного отображения.

<?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 оставляет желать лучшего с точки зрения того, насколько они полезны для рисования чего-либо, даже немного сложного.

Эта версия выглядит так:

Old speech bubble version

ОБНОВЛЕНИЕ Я снова работал над речевыми пузырями XML и был немного недоволен своим решением 2014 года. В 2018 году у нас есть векторные графики, которые обеспечивают лучшие решения, чем приведенные выше. Вот еще несколько современных альтернатив. Они позволяют такие вещи, как небольшие сообщения и прозрачность.

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>

Два выше выглядят так: (Эти версии не совсем работают с прозрачностью, и я не уверен, почему, когда версии ниже, кажется, работают нормально.)

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>

Два выше выглядят так:

Speech bubbles with curly tails

Dimens.xml (для обоих)

<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>

Ответ 3

Я знаю, что слишком поздно для этого. Для тех, кто не хочет использовать изображения с 9 участками, но хочет отбрасывать тени из речевого пузыря. Это самое близкое, что я мог получить к речевому пузырю в WhatsApp. И спасибо @toobsco42 за ответ выше.

Ну вот..

Пузырь входящей речи:

<?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>

Исходящая речь 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>

Используйте прокладки правильно в макете. Я использовал эти значения:

<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" />

Мой вывод вышел так:

enter image description here

Ответ 4

Вы должны сделать изображение в каком-то редакторе изображений, а затем создать из него 9 патчей. Вы можете установить область, в которой вы хотите, чтобы контент использовал метод 9 patch. Тогда вы можете просто иметь TextView с фоном, установленным для вашего 9 патча. Посмотрите на приложение под названием Bnter на рынке, оно использует речевые пузыри для отображения разговоров, похожих на то, что вы ищете.