¿Cómo agregar una lista con viñetas a la aplicación de Android?

89

Busqué en Google mi pregunta pero no se proporcionó una respuesta que funcione. ¿Cómo agrego una lista con viñetas a mi vista de texto?

usuario590849
fuente

Respuestas:

185

Difícil de hacer, ya que no se admiten ul / li / ol. Afortunadamente, puedes usar esto como azúcar sintáctico:

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

&#8226;es la entidad html para una lista de viñetas. Más opciones están aquí http://www.elizabethcastro.com/html/extras/entities.html

más sobre qué etiquetas son compatibles proporcionadas por Mark Murphy (@CommonsWare) http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html Cargue eso con Html.fromHtml

((TextView)findViewById(R.id.my_text_view)).setText(Html.fromHtml(myHtmlString));
ceja
fuente
1
Gracias por el enlace al sitio commonsware, ¡he estado buscando algo así durante algún tiempo!
Norman H
4
Tenga en cuenta que si obtiene la cadena de valores / cadenas.xml (usando context.getString (R.string.yourstring);), tendrá que envolverla en CDATA : <string name="string_name"><![CDATA[ &#8226; foo<br /> &#8226; bar... ]]></string>
Quentin S.
5
esto no funciona si hay más de una línea en el elemento de
viñeta
parece que ul/ lies compatible ahora stackoverflow.com/questions/9754076/…
hmac
55
  1. Browep explicó bien el camino sobre HTML. La solución proporcionada con la entidad html puede ser útil. Pero incluye solo la bala. Si su texto se ajusta, la sangría no será correcta.

  2. Encontré otras soluciones que incorporan una vista web. Eso tal vez sea apropiado para algunos, pero creo que es un poco exagerado ... (Lo mismo con el uso de una vista de lista).

  3. Me gusta el enfoque creativo de Nelson : D, pero no te da la posibilidad de agregar una lista desordenada a una vista de texto.

  4. Mi ejemplo de una lista desordenada con viñetas 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:

  • Viñetas con sangría correcta después del ajuste del texto.
  • Puede combinar otro texto formateado o no formateado en una instancia de TextView
  • Puede definir en el constructor BulletSpan qué tan grande debe ser la sangría.

Negativo:

  • Debe guardar cada elemento de la lista en un recurso de cadena separado. Por lo tanto, no puede definir su lista tan cómodo como podría hacerlo en HTML.
Diego Frehner
fuente
1
Este enfoque (imitado exactamente) no funciona en 2.2. Terminas con una sola bala.
Skone
Hola Skone, funciona en el emulador 2.2 y en versiones originales de Android. Vi una versión de Android donde se ignoraba el espacio entre la viñeta y el texto. Pero la bala todavía apareció. ¿Tiene una nueva línea al final de sus cadenas de balas?
Diego Frehner
Esta solución no funciona cuando cambia el espaciado de línea en la vista de texto
Marqs
¡Excelente forma de hacerlo con BulletSpan, funciona perfectamente y es muy fácil!
Moonbloom
7
¡El código anterior funciona para mí! Todo lo que tuve que hacer fue agregar "\ n" al final de cada cadena en xml ...
Arhat Baid
38

Encontré una alternativa ... simplemente copie esta viñeta "•" (es un texto) y péguela en el texto de su vista de texto, puede cambiar el color de la viñeta cambiando el color del texto y también todos los demás atributos como tamaño, alto ancho. .. :)

puede usar el atajo para obtener esta viñeta mientras escribe

para ventanas

ALT + 7

para Mac

ALT + 8

Ishtiaq
fuente
2
Alt + 7 no funciona para mí (quizás sea sólo una cosa de mac o linux) pero copiar y pegar el carácter • Unicode funcionó.
Jon
2
FYI: ALT + 7 funcionará solo si el teclado tiene un teclado numérico separado.
Aks4125
Si pega el símbolo en el código, es decir, en una cadena, tenga en cuenta los problemas con los caracteres no ascii y la codificación de archivos (intente cambiar la codificación del archivo desde la esquina inferior derecha de IntelliJ). Mejor sería usar la secuencia de escape correspondiente (por ejemplo, \ u1234).
Gil Vegliach
¡¡Así se hace !! ¡vida de matón!
goonerDroid
2
\ u2022 es la respuesta
user2322082
21

Inspirado por las diversas respuestas aquí, creé una clase de utilidad para que esto sea fácil . Esto creará una lista con viñetas con sangría para el texto ajustado. Tiene métodos para combinar cadenas, recursos de cadenas y recursos de matriz de cadenas.

Creará una CharSequence que puede pasar a TextView. Por ejemplo:

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

Espero que sea de ayuda. Disfrutar.

Nota: Esto usará la viñeta estándar del sistema, un pequeño círculo del mismo color que el texto. Si desea una viñeta personalizada, considere subclasificar BulletSpan y anularladrawLeadingMargin() para dibujar la viñeta que desee. Eche un vistazo a la fuente de BulletSpan para tener una idea de cómo 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;
}

}
algodón
fuente
¡Gracias querido señor! Usé la función makeBulletList y funciona como un encanto: D
Aba
¡Es impresionante! Gracias)
kulikovman
10

Este es, con mucho, el más 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
fuente
8

Extensión de Kotlin lista 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

Colores y tamaño:

Para cambiar el color o el tamaño de la viñeta, utilice CustomBulletSpan en lugar 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
fuente
¿Puedes cambiar el tamaño de la viñeta para que coincida con el tamaño del texto de alguna manera?
nenur
@NoahTanenholtz puede aumentar el tamaño de la bala cambiando el valor del argumento BulletSpan ()
Mikhail Sharin
Oh, pensé que era el espaciado
nenur
El espaciado aumenta en lugar del tamaño de la bala):
Sumit Shukla
@SumitShukla gracias por el comentario. Acabo de agregar BulletCustomSpan para personalizar el color y el tamaño
Mikhail Sharin
4

Una opción que utilicé fue establecer la viñeta como dibujable usando un 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 Ramírez
fuente
Acabo de tomar una pequeña foto de bala de la web para dibujar. El diseño gráfico en Eclipse muestra el gráfico estirado debajo del texto ... bastante lejos de lo que quería.
JohnK
1
Creo que quiso decirandroid:drawableLeft=
Blundell
4

use TextView simple con un dibujable compuesto. Por ejemplo

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

Aquí hay otra solución, no exactamente agregar una lista a una vista de texto, pero supongo que el objetivo es el mismo. Utiliza TableLayout, que solo necesita XML y es realmente simple para listas pequeñas ordenadas o desordenadas. A continuación, el código de muestra que utilicé para esto, no una línea de código en Java.

Positivo:

  • puede poner lo que quiera en las filas de la tabla, no tiene que ser una vista de texto
  • puede usarlo para crear una lista numerada y con viñetas o lo que sea
  • puede definir la sangría usando padding o layout_weight

Negativo:

  • tedioso para listas muy largas (a menos que use un editor de texto astuto con expresiones regulares)
  • cada elemento de la lista se almacena como un recurso de cadena 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>

y el 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
fuente
2

Aquí hay una lista con viñetas con un encabezado y una pestaña al frente de cada elemento.

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

Fue completamente exagerado e hizo una vista de texto personalizada.

Úselo así:

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

y el 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
fuente
¿Cómo podemos aumentar el tamaño y el espaciado de las viñetas?
Sumit Shukla
En este ejemplo &#8226;, tendría que elegir otro símbolo fsymbols.com/signs/bullet-point
Blundell
1

Encuentro que esta es la forma más fácil, deje el textView como está en el archivo xml y use el siguiente código Java. funcionó perfectamente bien para mí.

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

La lista con viñetas se puede crear simplemente usando el <ul><li> etiquetas y en el recurso de cadena.

NO USE setText (Html.fromHtml (cadena)) para establecer la cadena en el código. Simplemente configure la cadena normalmente en xml o usando setText ( string ).

P.ej:

archivo strings.xml

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


archivo layout.xml

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


Producirá el siguiente resultado:

  • primero elemento
  • elemento 2


Las siguientes etiquetas se admiten así (directamente incrustadas en el recurso de cadena):

  • <a> (admite atributos "href")
  • <anotación>
  • <b>
  • <grande>
  • <font> (admite atributos "altura", "tamaño", "fgcolor" y "bicolor", como números enteros)
  • <i>
  • <li>
  • <marquesina>
  • <pequeño>
  • <golpe>
  • <sub>
  • <sup>
  • <tt>
  • <u>
Abhishek
fuente
no necesitas el<ul>
Blundell
5
No funciona. Las etiquetas html admitidas son <b>, <i> y <u> únicamente. developer.android.com/guide/topics/resources/…
Wooff
¡Funcionó perfectamente para mí! Lo único que tenía que hacer para que todo funcionara era poner \ n al principio de cada línea. es decir\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul>
Jack T
1

Porque single line textsimplemente puede usar dibujables:

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

Puede cambiar shape, size, colorsobre la base de su requisito.

Sumit Shukla
fuente
0

Las dos opciones que tiene para hacer una lista con viñetas son

  • cree la lista usando html (ul, ol) y cargue el html en un WebView
  • Cargue los datos en un ListView y configure el dibujable izquierdo de su vista de texto en el diseño del elemento de la lista, en una imagen adecuada para la viñeta.

La opción 1 es la más sencilla.

Estanque de Robby
fuente
0

otra forma de admitir las etiquetas HTML que faltan es reemplazándolas bien, como se muestra aquí

desarrollador de Android
fuente
0

Si desea crear una lista de viñetas con estructura editText.

Me beneficié de estas referencias

Puedes usar estas viñetas

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