Comment ajouter une liste à puces à l'application Android?


89

J'ai googlé ma question mais il n'y a pas de réponse de travail fournie. Comment ajouter une liste à puces à ma vue de texte.

Réponses:


185

Difficile à faire car ul / li / ol ne sont pas pris en charge. Heureusement, vous pouvez l'utiliser comme sucre syntaxique:

&#8226; foo<br/>
&#8226; bar<br/>
&#8226; baz<br/>

&#8226;est l'entité html pour une puce de liste plus de choix sont ici http://www.elizabethcastro.com/html/extras/entities.html

en savoir plus sur les balises prises en charge fournies par Mark Murphy (@CommonsWare) http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html Chargez cela avec Html.fromHtml

((TextView)findViewById(R.id.my_text_view)).setText(Html.fromHtml(myHtmlString));

1
Merci pour le lien vers le site commonsware, je cherchais quelque chose comme ça depuis un certain temps!
Norman H

4
Veuillez noter que si vous obtenez la chaîne à partir du fichier values ​​/ strings.xml (en utilisant context.getString (R.string.yourstring);), vous devrez l'envelopper dans CDATA : <string name="string_name"><![CDATA[ &#8226; foo<br /> &#8226; bar... ]]></string>
Quentin S.

5
cela ne fonctionne pas s'il y a plus d'une ligne dans l'élément de
puce

il ressemble à ul/ liest pris en charge maintenant stackoverflow.com/questions/9754076/…
hmac

55
  1. browep a bien expliqué le chemin sur HTML. La solution fournie avec l'entité html peut être utile. Mais cela ne comprend que la balle. Si votre texte est renvoyé à la ligne, le retrait ne sera pas correct.

  2. J'ai trouvé d'autres solutions intégrant une vue Web. C'est peut-être approprié pour certains, mais je pense que c'est un peu exagéré ... (La même chose avec l'utilisation d'une vue de liste.)

  3. J'aime l' approche créative de Nelson : D, mais cela ne vous donne pas la possibilité d'ajouter une liste non ordonnée à une vue texte.

  4. Mon exemple de liste non ordonnée avec des puces en utilisant BulletSpan

    CharSequence t1 = getText(R.string.xxx1);
    SpannableString s1 = new SpannableString(t1);
    s1.setSpan(new BulletSpan(15), 0, t1.length(), 0);
    CharSequence t2 = getText(R.string.xxx2);
    SpannableString s2 = new SpannableString(t2);
    s2.setSpan(new BulletSpan(15), 0, t2.length(), 0);
    textView.setText(TextUtils.concat(s1, s2));

Positif:

  • Puces avec un retrait correct après les retours à la ligne.
  • Vous pouvez combiner d'autres textes formatés ou non dans une seule instance de TextView
  • Vous pouvez définir dans le constructeur BulletSpan la taille du retrait.

Négatif:

  • Vous devez enregistrer chaque élément de la liste dans une ressource de chaîne distincte. Donc, vous ne pouvez pas définir votre liste aussi facilement que vous le pourriez en HTML.

1
Cette approche (imitée exactement) ne fonctionne pas sur 2.2. Vous vous retrouvez avec une seule balle.
Skone du

Salut Skone, cela fonctionne dans l'émulateur 2.2 et les versions Android originales. J'ai vu une version Android où l'espace entre la puce et le texte était ignoré. Mais la balle est toujours apparue. Avez-vous une nouvelle ligne à la fin de vos chaînes de puces?
Diego Frehner du

Cette solution ne fonctionne pas lorsque vous modifiez l'interligne dans la vue de texte
Marqs

Excellent moyen de le faire avec BulletSpan, fonctionne parfaitement et est très facile!
Moonbloom

7
Le code ci-dessus fonctionne pour moi !!! Tout ce que j'avais à faire est d'ajouter "\ n" à la fin de chaque chaîne en xml ....
Arhat Baid

38

J'ai trouvé une alternative .. il suffit de copier cette puce "•" (c'est un texte) et de la coller dans le texte de votre vue texte, vous pouvez changer la couleur de la puce en changeant la couleur du texte et aussi tous les autres attributs comme la taille, la largeur de la hauteur. .. :)

vous pouvez utiliser un raccourci pour obtenir cette puce en tapant

Pour les fenêtres

ALT + 7

pour Mac

ALT + 8


2
Alt + 7 ne fonctionne pas pour moi (peut-être que ce n'est qu'un truc Mac ou Linux) mais copier et coller le caractère Unicode • fonctionnait.
Jon

2
FYI: ALT + 7 ne fonctionnera que si le clavier a un pavé numérique séparé.
Aks4125 du

Si vous collez le symbole dans le code, c'est-à-dire dans une chaîne, gardez à l'esprit les problèmes avec les caractères non-ascii et le codage de fichier (essayez de changer le codage du fichier à partir du coin inférieur droit d'IntelliJ). Mieux vaut utiliser la séquence d'échappement correspondante (par exemple \ u1234).
Gil Vegliach

Bravo !! la vie de voyou!
goonerDroid

2
\ u2022 est la réponse
user2322082

21

Inspiré par les différentes réponses ici, j'ai créé une classe Utilitaire pour en faire une ligne simple . Cela créera une liste à puces avec indentation pour le texte encapsulé. Il a des méthodes pour combiner des chaînes, des ressources de chaîne et des ressources de tableau de chaînes.

Cela créera une CharSequence que vous pourrez passer à un TextView. Par exemple:

CharSequence bulletedList = BulletListUtil.makeBulletList("First line", "Second line", "Really long third line that will wrap and indent properly.");
textView.setText(bulletedList);

J'espère que c'est utile. Prendre plaisir.

Remarque: Cela utilisera la puce standard du système, un petit cercle de la même couleur que le texte. Si vous voulez une puce personnalisée, envisagez de sous- classer BulletSpan et de la remplacerdrawLeadingMargin() pour dessiner la puce souhaitée. Jetez un œil à la source BulletSpan pour avoir une idée de son fonctionnement.

public class BulletTextUtil {

/**
 * Returns a CharSequence containing a bulleted and properly indented list.
 *
 * @param leadingMargin In pixels, the space between the left edge of the bullet and the left edge of the text.
 * @param context
 * @param stringArrayResId A resource id pointing to a string array. Each string will be a separate line/bullet-point.
 * @return
 */
public static CharSequence makeBulletListFromStringArrayResource(int leadingMargin, Context context, int stringArrayResId) {
    return makeBulletList(leadingMargin, context.getResources().getStringArray(stringArrayResId));
}

/**
 * Returns a CharSequence containing a bulleted and properly indented list.
 *
 * @param leadingMargin In pixels, the space between the left edge of the bullet and the left edge of the text.
 * @param context
 * @param linesResIds An array of string resource ids. Each string will be a separate line/bullet-point.
 * @return
 */
public static CharSequence makeBulletListFromStringResources(int leadingMargin, Context context, int... linesResIds) {
    int len = linesResIds.length;
    CharSequence[] cslines = new CharSequence[len];
    for (int i = 0; i < len; i++) {
        cslines[i] = context.getString(linesResIds[i]);
    }
    return makeBulletList(leadingMargin, cslines);
}

/**
 * Returns a CharSequence containing a bulleted and properly indented list.
 *
 * @param leadingMargin In pixels, the space between the left edge of the bullet and the left edge of the text.
 * @param lines An array of CharSequences. Each CharSequences will be a separate line/bullet-point.
 * @return
 */
public static CharSequence makeBulletList(int leadingMargin, CharSequence... lines) {
    SpannableStringBuilder sb = new SpannableStringBuilder();
    for (int i = 0; i < lines.length; i++) {
        CharSequence line = lines[i] + (i < lines.length-1 ? "\n" : "");
        Spannable spannable = new SpannableString(line);
        spannable.setSpan(new BulletSpan(leadingMargin), 0, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        sb.append(spannable);
    }
    return sb;
}

}

Merci cher monsieur! J'ai utilisé la fonction makeBulletList et ça marche comme un charme: D
Aba

C'est génial! Merci)
kulikovman

10

C'est de loin le plus simple.

<string name="bullet_ed_list">\n\u2022 He has been Chairman of CFL Manufacturers Committee of ELCOMA, the All India Association of Lighting Equipment Manufacturers.
\n\u2022 He has been the President of Federation of Industries of India (FII).</string>

8

Extension Kotlin prête à l'emploi

fun List<String>.toBulletedList(): CharSequence {
    return SpannableString(this.joinToString("\n")).apply {
        this@toBulletedList.foldIndexed(0) { index, acc, span ->
            val end = acc + span.length + if (index != this@toBulletedList.size - 1) 1 else 0
            this.setSpan(BulletSpan(16), acc, end, 0)
            end
        }
    }
}

Usage:

val bulletedList = listOf("One", "Two", "Three").toBulletedList()
label.text = bulletedList

Couleurs et taille:

Pour changer la couleur ou la taille des puces, utilisez CustomBulletSpan au lieu de BulletSpan

package com.fbs.archBase.ui.spans

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.text.Layout
import android.text.Spanned
import android.text.style.LeadingMarginSpan
import androidx.annotation.ColorInt

class CustomBulletSpan(
        private val bulletRadius: Int = STANDARD_BULLET_RADIUS,
        private val gapWidth: Int = STANDARD_GAP_WIDTH,
        @ColorInt private val circleColor: Int = STANDARD_COLOR
) : LeadingMarginSpan {

    private companion object {
        val STANDARD_BULLET_RADIUS = Screen.dp(2)
        val STANDARD_GAP_WIDTH = Screen.dp(8)
        const val STANDARD_COLOR = Color.BLACK
    }

    private val circlePaint = Paint().apply {
    color = circleColor
        style = Paint.Style.FILL
        isAntiAlias = true
    }

    override fun getLeadingMargin(first: Boolean): Int {
        return 2 * bulletRadius + gapWidth
    }

    override fun drawLeadingMargin(
            canvas: Canvas, paint: Paint, x: Int, dir: Int,
            top: Int, baseline: Int, bottom: Int,
            text: CharSequence, start: Int, end: Int,
            first: Boolean,
            layout: Layout?
    ) {
        if ((text as Spanned).getSpanStart(this) == start) {
            val yPosition = (top + bottom) / 2f
            val xPosition = (x + dir * bulletRadius).toFloat()

            canvas.drawCircle(xPosition, yPosition, bulletRadius.toFloat(), circlePaint)
        }
    }
}

Pouvez-vous modifier la taille de la puce pour qu'elle corresponde à la taille du texte?
nenur

@NoahTanenholtz, vous pouvez augmenter la taille de la balle en modifiant la valeur de l'argument BulletSpan ()
Mikhail Sharin

Oh, je pensais que c'était l'espacement
nenur

L'espacement est augmenté au lieu de la taille de la balle):
Sumit Shukla

@SumitShukla merci pour le commentaire. Je viens d'ajouter BulletCustomSpan pour la personnalisation de la couleur et de la taille
Mikhail Sharin

4

Une option que j'ai utilisée était de définir la puce pouvant être dessinée à l'aide d'un style.

<style name="Text.Bullet">
    <item name="android:background">@drawable/bullet</item>
    <item name="android:paddingLeft">10dp</item>
</style>

Usage:

<TextView android:id="@+id/tx_hdr" 
android:text="Item 1" style="@style/Text.Bullet" />

Je viens de prendre une petite photo de balle sur le Web pour le dessin. La disposition graphique dans Eclipse montre le graphique étiré sous le texte ... plutôt loin de ce que je voulais.
JohnK

1
Je pense qu'il voulait direandroid:drawableLeft=
Blundell

4

utilisez TextView simple avec un dessin composé. Par exemple

<TextView     
    android:text="Sample text"
    android:drawableLeft="@drawable/bulletimage" >
</TextView>

3

Voici une autre solution, pas exactement l'ajout d'une liste à une vue de texte, mais je suppose que l'objectif est le même. Il utilise TableLayout, qui n'a besoin que de XML et c'est vraiment simple pour les petites listes ordonnées ou non. Ci-dessous, un exemple de code que j'ai utilisé pour cela, pas une ligne de code en Java.

Positif:

  • vous pouvez mettre ce que vous voulez dans les lignes du tableau, il n'est pas nécessaire que ce soit une vue de texte
  • vous pouvez l'utiliser pour créer une liste à puces et numérotée ou autre
  • vous pouvez définir le retrait en utilisant padding ou layout_weight

Négatif:

  • fastidieux pour les très longues listes (sauf si vous utilisez un éditeur de texte astucieux avec regex)
  • chaque élément de liste est stocké en tant que ressource de chaîne distincte

        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
    
            >
    
            <TextView
                style="@style/helpPagePointsStyle"
                android:layout_weight="0.2"
                android:text="1." />
    
            <TextView
                style="@style/helpPagePointsStyle"
                android:layout_weight="3"
                android:text="@string/help_points1" />
        </TableRow>
    
        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            >
            <TextView
                style="@style/helpPagePointsStyle"
                android:layout_weight="0.2"
                android:text="2." />
    
            <TextView
                style="@style/helpPagePointsStyle"
                android:layout_weight="3"
                android:text="@string/help_points2" />
        </TableRow>
        <TableRow
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            >
            <TextView
                style="@style/helpPagePointsStyle"
                android:layout_weight="0.2"
                android:text="3." />
            <TextView
                style="@style/helpPagePointsStyle"
                android:layout_weight="3"
                android:text="@string/help_points3" />
        </TableRow>
    
    
    </TableLayout>

et le style:

<style name="helpPagePointsStyle">
    <item name="android:layout_width">0dp</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:gravity">left</item>
</style>

2

Voici une liste à puces avec un en-tête et un onglet devant chaque élément.

public class BulletListBuilder {

    private static final String SPACE = " ";
    private static final String BULLET_SYMBOL = "&#8226";
    private static final String EOL = System.getProperty("line.separator");
    private static final String TAB = "\t";

    private BulletListBuilder() {

    }

    public static String getBulletList(String header, String []items) {
        StringBuilder listBuilder = new StringBuilder();
        if (header != null && !header.isEmpty()) {
            listBuilder.append(header + EOL + EOL);
        }
        if (items != null && items.length != 0) {
            for (String item : items) {
                Spanned formattedItem = Html.fromHtml(BULLET_SYMBOL + SPACE + item);
                listBuilder.append(TAB + formattedItem + EOL);
            }
        }
        return listBuilder.toString();
    }

}

2

Je suis allé complètement exagéré et a créé une vue de texte personnalisée.

Utilisez-le comme ceci:

<com.blundell.BulletTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="--bullet 1 --bullet two --bullet three --bullet four" />

et le code:

package com.blundell;

import android.content.Context;
import android.text.Html;
import android.util.AttributeSet;
import android.widget.TextView;

public class BulletTextView extends TextView {
    private static final String SPLITTER_CHAR = "--";
    private static final String NEWLINE_CHAR = "<br/>";
    private static final String HTML_BULLETPOINT = "&#8226;";

    public BulletTextView(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.textViewStyle);
    }

    public BulletTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        checkForBulletPointSplitter();
    }

    private void checkForBulletPointSplitter() {
        String text = (String) getText();
        if (text.contains(SPLITTER_CHAR)) {
            injectBulletPoints(text);
        }
    }

    private void injectBulletPoints(String text) {
        String newLinedText = addNewLinesBetweenBullets(text);
        String htmlBulletText = addBulletPoints(newLinedText);
        setText(Html.fromHtml(htmlBulletText));
    }

    private String addNewLinesBetweenBullets(String text) {
        String newLinedText = text.replace(SPLITTER_CHAR, NEWLINE_CHAR + SPLITTER_CHAR);
        newLinedText = newLinedText.replaceFirst(NEWLINE_CHAR, "");
        return newLinedText;
    }

    private String addBulletPoints(String newLinedText) {
        return newLinedText.replace(SPLITTER_CHAR, HTML_BULLETPOINT);
    }

}

Comment pouvons-nous augmenter la taille et l'espacement des balles?
Sumit Shukla le

Cet exemple utilise que &#8226;vous auriez à choisir un autre symbole fsymbols.com/signs/bullet-point
Blundell

1

Je trouve que c'est le moyen le plus simple, laissez le textView tel qu'il est dans le fichier xml et utilisez le code java suivant. cela a parfaitement fonctionné pour moi.

private static final String BULLET_SYMBOL = "&#8226";

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_tutorial);

    TextView tv = (TextView) findViewById(R.id.yourTextView);

    tv.setText("To perform this exercise you will need the following: "
                        + System.getProperty("line.separator")//this takes you to the next Line
                        + System.getProperty("line.separator")
                        + Html.fromHtml(BULLET_SYMBOL + " Bed")
                        + System.getProperty("line.separator")
                        + Html.fromHtml(BULLET_SYMBOL + " Pillow"));
}

1

La liste à puces peut être simplement créée en utilisant les balises <ul>et <li>dans la ressource chaîne.

N'UTILISEZ PAS setText (Html.fromHtml (string)) pour définir la chaîne dans le code! Définissez simplement la chaîne normalement en xml ou en utilisant setText ( string ).

Par exemple:

fichier strings.xml

<string name="str1">
    <ul>
        <li><i>first</i> item</li>
        <li>item 2</li>
    </ul>
</string>


fichier layout.xml

<TextView
    android:text="@string/str1"
/>


Il produira le résultat suivant:

  • premier élément
  • élément 2


Les balises suivantes sont prises en charge comme ceci (directement intégrées dans la ressource de chaîne):

  • <a> (prend en charge les attributs "href")
  • <annotation>
  • <b>
  • <big>
  • <font> (prend en charge les attributs "hauteur", "taille", "fgcolor" et "bicolore", sous forme d'entiers)
  • <i>
  • <li>
  • <marquee>
  • <petit>
  • <frappe>
  • <sub>
  • <sup>
  • <tt>
  • <u>

vous n'avez pas besoin du<ul>
Blundell

5
Ne marche pas. Les balises HTML prises en charge sont uniquement <b>, <i> et <u>. developer.android.com/guide/topics/resources/…
Wooff

A parfaitement fonctionné pour moi! La seule chose que j'avais à faire pour que tout fonctionne était de mettre \ n au début de chaque ligne. ie\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul>
Jack T

1

Car single line textvous pouvez simplement utiliser des drawables:

<TextView
    android:id="@+id/txtData"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:drawableStart="@drawable/draw_bullet_list"
    android:drawablePadding="@dimen/padding_8dp"
    android:text="Hello"
    android:textColor="@color/colorBlack" />

draw_bullet_list.xml :

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/colorAccent" />

    <size
        android:width="12dp"
        android:height="12dp" />

</shape>

Vous pouvez changer shape, sizeen colorfonction de vos besoins.


0

Les deux options dont vous disposez pour créer une liste à puces sont

  • créer la liste en utilisant html (ul, ol) et charger le html dans une WebView
  • Chargez les données dans un ListView et définissez le dessin de gauche de votre vue de texte dans la disposition de l'élément de liste, sur une image appropriée pour la puce.

L'option 1 est la plus simple.


0

une autre façon de prendre en charge les balises HTML manquantes consiste à les remplacer correctement, comme indiqué ici


0

Si vous souhaitez créer une liste à puces avec la structure editText.

J'ai bénéficié de ces références

Vous pouvez utiliser ces puces

           EditText  edtNoteContent = findViewById(R.id.editText_description_note);            

        edtNoteContent.addTextChangedListener(new TextWatcher(){
            @Override
            public void afterTextChanged(Editable e) {

            }
            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {

            }
            @Override
            public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter)
            {
                if (lengthAfter > lengthBefore) {
                    if (text.toString().length() == 1) {
                        text = "◎ " + text;
                        edtNoteContent.setText(text);
                        edtNoteContent.setSelection(edtNoteContent.getText().length());
                    }
                    if (text.toString().endsWith("\n")) {
                        text = text.toString().replace("\n", "\n◎ ");
                        text = text.toString().replace("◎ ◎", "◎");
                        edtNoteContent.setText(text);
                        edtNoteContent.setSelection(edtNoteContent.getText().length());
                    }
                }
            }
        });
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.