web-dev-qa-db-fra.com

Android bulle de dialogue dessinable

J'ai cherché pendant des jours et je ne trouve pas de bonnes pistes sur la façon dont je peux dessiner une bulle ou où dessiner des images de patch 9 à utiliser comme arrière-plan. je suis un artiste terrible - quelqu'un peut-il aider?

le meilleur échantillon que j'ai trouvé est ici sur stackoverflow, mais il est écrit en objectif C

Comment dessiner une "bulle de dialogue" sur un iPhone?

Je vous remercie

36
user1024776

Si vous créez un écran de discussion, vous souhaiterez probablement implémenter une bulle de dialogue entrante et une bulle de dialogue sortante. Voici comment j'ai fait ça:

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

Voici une simple bulle de dialogue que j'ai dessinée. Espérons que cela commence dans la bonne direction pour quelqu'un. Le point de vue selon lequel ce dessinable est utilisé nécessite une hauteur d'au moins 70 à 80 dp et une largeur minimale similaire pour s'afficher correctement.

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

Les Drawables Android laissent beaucoup à désirer quant à leur utilité pour dessiner quoi que ce soit, même légèrement complexe.

Cette version ressemble à ceci:

Old speech bubble version

[~ # ~] mise à jour [~ # ~] J'ai de nouveau travaillé sur des bulles de langage XML et j'étais un peu insatisfait de ma solution de 2014. En 2018, nous avons des dessinables vectoriels qui permettent de meilleures solutions que celle ci-dessus. Voici quelques alternatives plus modernes. Ils permettent des choses comme les petits messages et la transparence.

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>

Les deux ci-dessus ressemblent à ceci: (Ces versions ne fonctionnent pas tout à fait avec transparence et je ne sais pas pourquoi quand les versions ci-dessous semblent bien fonctionner.)

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>

Les deux ci-dessus ressemblent à ceci:

Speech bubbles with curly tails

dimens.xml (pour les deux)

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

Je sais que c'est un peu trop tard pour ça. Pour ceux qui ne veulent pas utiliser d'images à 9 patchs mais veulent projeter des ombres à partir d'une bulle de dialogue. C'est le plus proche que j'ai pu trouver dans la bulle de dialogue WhatsApp. Et merci à @ toobsco42 pour la réponse ci-dessus.

Voici..

Bulle de dialogue entrante:

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

Bulle de dialogue sortante:

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

Utilisez les rembourrages correctement dans la disposition. J'ai utilisé ces valeurs:

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

Ma sortie est sortie comme ceci:

enter image description here

36
VipiN Negi

Vous devez créer une image dans une sorte d'éditeur d'image, puis en créer un patch. Vous pouvez définir la zone dans laquelle vous souhaitez que le contenu utilise la méthode des 9 patchs. Ensuite, vous pouvez simplement avoir une TextView avec l'arrière-plan défini sur votre patch 9. Jetez un œil à une application appelée Bnter sur le marché, elle utilise des bulles pour afficher des conversations similaires à ce que vous recherchez.

4
Bobbake4