Como adicionar uma lista com marcadores ao aplicativo Android?

89

Eu pesquisei minha pergunta, mas não há uma resposta funcional fornecida. Como adicionar uma lista com marcadores ao meu textview.

user590849
fonte

Respostas:

185

Difícil de fazer, pois ul / li / ol não são suportados. Felizmente, você pode usar isso como açúcar sintático:

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

&#8226;é a entidade html para um marcador de lista, mais opções estão aqui http://www.elizabethcastro.com/html/extras/entities.html

mais sobre quais tags são compatíveis, fornecido por Mark Murphy (@CommonsWare) http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html Carregue isso com Html.fromHtml

((TextView)findViewById(R.id.my_text_view)).setText(Html.fromHtml(myHtmlString));
sobrancelha
fonte
1
Obrigado pelo link para o site commonsware, estou procurando por algo assim há algum tempo!
Norman H
4
Observe que se você estiver obtendo a string de values ​​/ strings.xml (usando context.getString (R.string.yourstring);), você terá que envolvê-la em CDATA : <string name="string_name"><![CDATA[ &#8226; foo<br /> &#8226; bar... ]]></string>
Quentin S.
5
isso não funciona se houver mais de uma linha no item do marcador
thepoosh
parece ul/ lié suportado agora stackoverflow.com/questions/9754076/…
hmac
55
  1. browep explicou de forma agradável o caminho em relação ao HTML. A solução fornecida com a entidade html pode ser útil. Mas inclui apenas a bala. Se o seu texto quebrar, o recuo não ficará correto.

  2. Encontrei outras soluções incorporando uma visualização da web. Isso pode ser apropriado para alguns, mas acho que é um tipo de exagero ... (O mesmo com o uso de uma exibição de lista.)

  3. Gosto da abordagem criativa de Nelson : D, mas não dá a possibilidade de adicionar uma lista não ordenada a uma visualização de texto.

  4. Meu exemplo de uma lista não ordenada com marcadores usando 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));

Positivo:

  • Marcadores com recuo correto após quebra de texto.
  • Você pode combinar outro texto formatado ou não formatado em uma instância de TextView
  • Você pode definir no construtor BulletSpan quão grande deve ser o recuo.

Negativo:

  • Você tem que salvar cada item da lista em um recurso de string separado. Então, você não pode definir sua lista tão confortável quanto você faria em HTML.
Diego frehner
fonte
1
Esta abordagem (imitada exatamente) não funciona no 2.2. Você acaba com apenas uma única bala.
Skone
Olá, Skone, funciona no emulador 2.2 e no Android original. Eu vi uma versão do Android onde o espaço entre o marcador e o texto foi ignorado. Mas a bala ainda apareceu. Você tem uma nova linha no final de suas sequências de marcadores?
Diego Frehner,
Esta solução não funciona quando você altera o espaçamento entre linhas no textview
Marqs
Ótima maneira de fazer isso com o BulletSpan, funciona perfeitamente e é muito fácil!
Moonbloom
7
O código acima funciona para mim !!! Tudo que eu tive que fazer foi adicionar "\ n" no final de cada string em xml ....
Arhat Baid
38

Eu encontrei uma alternativa .. apenas copie este marcador "•" (é um texto) e cole no texto da sua visualização de texto, você pode mudar a cor do marcador mudando a cor do texto e também todos os outros atributos como tamanho, altura largura. .. :)

você pode usar o atalho para obter este marcador enquanto digita

para Windows

ALT + 7

para mac

ALT + 8

Ishtiaq
fonte
2
Alt + 7 não funciona para mim (talvez seja apenas um mac ou linux), mas copiar e colar o caractere Unicode • funcionou.
Jon
2
FYI: ALT + 7 funcionará apenas se o teclado tiver teclado numérico separado.
Aks4125
Se você colar o símbolo no código, ou seja, em uma string, tenha em mente os problemas com caracteres não ASCII e codificação de arquivo (tente alterar a codificação do arquivo no canto inferior direito do IntelliJ). Melhor seria usar a sequência de escape correspondente (por exemplo, \ u1234).
Gil Vegliach de
Caminho a percorrer !! vida de bandido!
goonerDroid
2
\ u2022 é a resposta
user2322082
21

Inspirado pelas várias respostas aqui, criei uma classe Utilitário para tornar este um liner fácil . Isso criará uma lista com marcadores com recuo para texto quebrado. Ele tem métodos para combinar strings, recursos de string e recursos de array de string.

Ele criará um CharSequence que você pode passar para um TextView. Por exemplo:

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

Espero que seja útil. Aproveitar.

Nota: Isso usará o marcador padrão do sistema, um pequeno círculo da mesma cor do texto. Se você quiser um marcador personalizado, considere subclassificar BulletSpan e substituí-lo drawLeadingMargin()para desenhar o marcador que deseja. Dê uma olhada no código-fonte do BulletSpan para ter uma ideia de como ele funciona.

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

}
cottonBallPaws
fonte
Obrigado caro senhor! Usei a função makeBulletList e ela funciona perfeitamente: D
Aba
É incrivel! Obrigado)
kulikovman
10

Este é de longe o mais fácil ..

<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>
Amit Tumkur
fonte
8

Extensão Kotlin pronta para usar

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

Uso:

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

Cores e tamanho:

Para alterar a cor ou o tamanho do marcador, use CustomBulletSpan em vez 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)
        }
    }
}
Mikhail Sharin
fonte
Você pode alterar o tamanho do marcador para corresponder ao tamanho do texto de alguma forma?
nenur
@NoahTanenholtz você pode aumentar o tamanho do marcador alterando o valor do argumento BulletSpan ()
Mikhail Sharin
Oh, pensei que era o espaçamento
nenur
O espaçamento é aumentado em vez do tamanho do marcador):
Sumit Shukla
@SumitShukla obrigado pelo comentário. Acabei de adicionar BulletCustomSpan para personalização de cor e tamanho
Mikhail Sharin
4

Uma opção que usei foi definir o drawable com marcadores usando um estilo.

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

Uso:

<TextView android:id="@+id/tx_hdr" 
android:text="Item 1" style="@style/Text.Bullet" />
Nelson Ramirez
fonte
Acabei de pegar uma pequena foto com um marcador da web para o drawable. O Layout Gráfico no Eclipse mostra o gráfico esticado sob o texto ... bem longe do que eu queria.
JohnK
1
Acho que ele quis dizerandroid:drawableLeft=
Blundell
4

use TextView simples com um drawable composto. Por exemplo

<TextView     
    android:text="Sample text"
    android:drawableLeft="@drawable/bulletimage" >
</TextView>
Nouman Hanif
fonte
3

Aqui está outra solução, não exatamente adicionar uma lista a um textview, mas acho que o objetivo é o mesmo. Ele usa o TableLayout, que só precisa de XML e é muito simples para pequenas listas ordenadas ou não ordenadas. Abaixo, um exemplo de código que usei para isso, não uma linha de código em Java.

Positivo:

  • você pode colocar o que quiser nas linhas da tabela, não precisa ser um textview
  • você pode usá-lo para criar listas com marcadores e numeradas ou qualquer outra coisa
  • você pode definir recuo usando padding ou layout_weight

Negativo:

  • tedioso para listas muito longas (a menos que você use algum editor de texto habilidoso com regex)
  • cada item da lista é armazenado como um recurso de string separado

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

e o estilo:

<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>
Dorsz
fonte
2

Aqui está uma lista com marcadores com um cabeçalho e uma guia na frente de cada item.

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();
    }

}
Maksim Dmitriev
fonte
2

Foi completamente exagero e fez uma visualização de texto personalizada.

Use-o assim:

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

e o código:

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);
    }

}
Blundell
fonte
Como podemos aumentar o tamanho e o espaçamento dos marcadores?
Sumit Shukla
Este exemplo usa que &#8226;você teria que escolher outro símbolo fsymbols.com/signs/bullet-point
Blundell
1

Acho que essa é a maneira mais fácil, deixe o textView como está no arquivo xml e use o seguinte código java. funcionou perfeitamente bem para mim.

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"));
}
fernand bontemps
fonte
1

A lista com marcadores pode ser criada simplesmente usando as tags <ul>e <li>no recurso de string.

NÃO USE setText (Html.fromHtml (string)) para definir a string no código! Basta definir a string normalmente em xml ou usando setText ( string ).

Por exemplo:

arquivo strings.xml

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


arquivo layout.xml

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


Isso produzirá o seguinte resultado:

  • primeiro item
  • item 2


As seguintes tags são suportadas assim (diretamente incorporadas ao recurso de string):

  • <a> (suporta atributos "href")
  • <anotação>
  • <b>
  • <grande>
  • <font> (suporta os atributos "height", "size", "fgcolor" e "bicolor", como inteiros)
  • <i>
  • <li>
  • <marquee>
  • <pequeno>
  • <strike>
  • <sub>
  • <sup>
  • <tt>
  • <u>
Abhishek
fonte
você não precisa do<ul>
Blundell
5
Não funciona. As tags html suportadas são <b>, <i> e <u> apenas. developer.android.com/guide/topics/resources/…
Wooff
Funcionou perfeitamente para mim! A única coisa que tive que fazer para que tudo funcionasse foi colocar \ n no início de cada linha. ie\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul>
Jack T
1

Pois single line textvocê pode simplesmente usar 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>

Você pode mudar shape, size, colorcom base em sua exigência.

Sumit Shukla
fonte
0

As duas opções que você tem para fazer uma lista com marcadores são

  • crie a lista usando html (ul, ol) e carregue o html em um WebView
  • Carregue os dados em um ListView e defina o drawable esquerdo de sua visualização de texto no layout do item de lista, para uma imagem adequada para o marcador.

A opção 1 é a mais fácil.

Robby Pond
fonte
0

outra maneira de suportar as tags HTML ausentes é substituindo-as bem, como mostrado aqui

desenvolvedor android
fonte
0

Se você deseja criar uma lista de marcadores com a estrutura editText.

Eu me beneficiei dessas referências

Você pode usar estes marcadores

           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());
                    }
                }
            }
        });
Yavuz Yoldaş
fonte