Как добавить маркированный список в приложение для Android?


91

Я задал свой вопрос в Google, но ответа на него нет. Как добавить маркированный список в текстовое представление.

Ответы:


189

Трудно сделать, поскольку ul / li / ol не поддерживаются. К счастью, вы можете использовать это как синтаксический сахар:

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

&#8226;- это html-объект для списка, больше вариантов здесь http://www.elizabethcastro.com/html/extras/entities.html

подробнее о том, какие теги поддерживаются, предоставил Марк Мерфи (@CommonsWare) http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html Загрузите это с помощью Html.fromHtml

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

1
Спасибо за ссылку на сайт Commonsware, давно искал что-то подобное!
Norman H

4
Обратите внимание, что если вы получаете строку из файла values ​​/ strings.xml (используя context.getString (R.string.yourstring);), вам придется обернуть ее в CDATA : <string name="string_name"><![CDATA[ &#8226; foo<br /> &#8226; bar... ]]></string>
Квентин С.

5
это не работает, если в элементе
bulletpoint

похоже, что ul/ liтеперь поддерживается stackoverflow.com/questions/9754076/…
hmac

55
  1. Browep красиво объяснил, как HTML. Предлагаемое решение с html-сущностью может оказаться полезным. Но он включает только пулю. Если ваш текст переносится, отступ будет неправильным.

  2. Я нашел другие решения, встраивающие веб-представление. Возможно, это подходит для некоторых, но я думаю, что это своего рода излишество ... (То же самое с использованием представления списка.)

  3. Мне нравится творческий подход Nelson : D, но он не дает вам возможности добавить неупорядоченный список в текстовое представление.

  4. Мой пример неупорядоченного списка с маркерами с использованием 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));
    

Положительный:

  • Маркеры с правильным отступом после переноса текста.
  • Вы можете комбинировать другой форматированный или неформатированный текст в одном экземпляре TextView
  • Вы можете определить в конструкторе BulletSpan, насколько большим должен быть отступ.

Отрицательный:

  • Вы должны сохранить каждый элемент списка в отдельном строковом ресурсе. Итак, вы не можете определить свой список так удобно, как в HTML.

1
Этот подход (точно имитированный) не работает в версии 2.2. Вы получаете только одну пулю.
Skone

Привет, Skone, работает в эмуляторе 2.2 и оригинальных сборках андроида. Я видел версию для Android, где пробел между маркером и текстом игнорировался. Но пуля все же появилась. Есть ли у вас новая строка в конце строки?
Диего Френер,

Это решение не работает, когда вы изменяете межстрочный интервал в текстовом представлении
Marqs

Отличный способ сделать это с BulletSpan, отлично работает и очень просто!
Moonbloom

7
У меня работает приведенный выше код !!! Все, что мне нужно было сделать, это добавить "\ n" в конце каждой строки в xml ....
Архат Байд,

38

Я нашел альтернативу ... просто скопируйте этот маркер «•» (это текст) и вставьте в текст своего текстового представления, вы можете изменить цвет маркера, изменив цвет текста, а также все другие атрибуты, такие как размер, высота и ширина. .. :)

вы можете использовать ярлык, чтобы получить эту пулю при вводе

для окон

ALT + 7

для Mac

ALT + 8


2
Alt + 7 у меня не работает (возможно, это только для Mac или Linux), но копирование и вставка символа • Unicode сработали.
Джон

2
К вашему сведению: ALT + 7 будет работать, только если клавиатура имеет отдельную цифровую клавиатуру.
Aks4125

Если вы вставляете символ в код, то есть в строку, имейте в виду проблемы с символами, отличными от ascii, и кодировкой файла (попробуйте изменить кодировку файла в правом нижнем углу IntelliJ). Лучше было бы использовать соответствующую escape-последовательность (например, \ u1234).
Gil Vegliach

Вперед !! бандитская жизнь!
goonerDroid

2
\ u2022 - это ответ
user2322082

21

Вдохновленный различными ответами здесь, я создал класс Utility, чтобы упростить этот лайнер . Это создаст маркированный список с отступом для обернутого текста. В нем есть методы для объединения строк, строковых ресурсов и ресурсов строковых массивов.

Он создаст CharSequence, который вы можете передать в TextView. Например:

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

Надеюсь, это поможет. Наслаждаться.

Примечание: будет использоваться стандартный системный маркер - маленький кружок того же цвета, что и текст. Если вам нужна настраиваемая пуля, рассмотрите возможность создания подкласса BulletSpan и переопределения его drawLeadingMargin()для рисования нужной пули. Взгляните на исходный код BulletSpan, чтобы понять, как это работает.

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

}

Спасибо, дорогой сэр! Я использовал функцию makeBulletList, и она отлично работает: D
Aba

Это круто! Спасибо)
куликовман 06

10

Это, безусловно, самый простой способ ..

<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

Готовое расширение Kotlin

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

Применение:

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

Цвета и размер:

Чтобы изменить цвет или размер маркера, используйте CustomBulletSpan вместо 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)
        }
    }
}

Можете ли вы как-нибудь изменить размер маркера, чтобы он соответствовал размеру текста?
nenur

@NoahTanenholtz, вы можете увеличить размер маркера, изменив значение аргумента BulletSpan ()
Михаил Шарин

О, я думал, что это интервал
nenur

Увеличен интервал вместо размера пули):
Сумит Шукла

@SumitShukla спасибо за комментарий. Я только что добавил BulletCustomSpan для настройки цвета и размера
Михаил Шарин

4

Вариант, который я использовал, заключался в том, чтобы установить возможность рисования маркера с помощью стиля.

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

Применение:

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

Я только что взял небольшую фотографию из сети для рисования. Графический макет в Eclipse показывает рисунок, растянутый под текстом ... довольно далеко от того, что я хотел.
JohnK

1
Я думаю, он имел в видуandroid:drawableLeft=
Бланделл

4

используйте простой TextView с составным рисунком. Например

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

3

Вот еще одно решение, не совсем добавление списка в одно текстовое представление, но я думаю, цель та же. Он использует TableLayout, которому нужен только XML, и это действительно просто для небольших упорядоченных или неупорядоченных списков. Ниже показан пример кода, который я использовал для этого, а не строку кода на Java.

Положительный:

  • вы можете поместить все, что хотите, в строки таблицы, не обязательно текстовое представление
  • вы можете использовать его для создания маркированного и нумерованного списка или чего-то еще
  • вы можете определить отступ с помощью padding или layout_weight

Отрицательный:

  • утомительно для очень длинных списков (если вы не используете какой-нибудь хитрый текстовый редактор с регулярным выражением)
  • каждый элемент списка хранится как отдельный строковый ресурс

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

и стиль:

<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

Вот маркированный список с заголовком и вкладкой перед каждым элементом.

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

Полностью переборщил и сделал настраиваемый текстовый вид.

Используйте это так:

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

и код:

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

}

Как мы можем увеличить размер пули и расстояние между ними?
Сумит Шукла,

В этом примере &#8226;вам нужно выбрать другой символ fsymbols.com/signs/bullet-point
Blundell

1

Я считаю, что это самый простой способ, оставьте textView таким, как он есть в файле xml, и используйте следующий код java. у меня это сработало отлично.

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

Маркированный список может быть просто создан с помощью <ul>и <li>тегов в строке ресурса.

НЕ ИСПОЛЬЗУЙТЕ setText (Html.fromHtml (string)) для установки строки в коде! Просто установите строку в xml или с помощью setText ( string ).

Например:

файл strings.xml

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


layout.xml файл

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


Это даст следующий результат:

  • первый пункт
  • пункт 2


Следующие теги поддерживаются таким образом (непосредственно встроены в строковый ресурс):

  • <a> (поддерживает атрибуты "href")
  • <аннотация>
  • <b>
  • <большой>
  • <font> (поддерживает атрибуты «высота», «размер», «fgcolor» и «bicolor» в виде целых чисел)
  • <i>
  • <li>
  • <выделение>
  • <маленький>
  • <удар>
  • <sub>
  • <sup>
  • <tt>
  • <u>

вам не нужен<ul>
Бланделл

5
Не работает. Поддерживаются только теги html <b>, <i> и <u>. developer.android.com/guide/topics/resources/…
Wooff

У меня отлично сработало! Единственное, что мне нужно было сделать, чтобы все заработало, - это поставить \ n в начале каждой строки. т.е.\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul>
Джек Т

1

Поскольку single line textвы можете просто использовать чертежи:

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

Вы можете изменить shape, size, colorосновываясь на вашем требовании.


0

Есть два варианта составления маркированного списка:

  • создать список с помощью html (ul, ol) и загрузить html в WebView
  • Загрузите данные в ListView и установите для левой части текстового представления в макете элемента списка подходящее изображение для маркера.

Вариант 1 самый простой.



0

Если вы хотите создать список маркеров со структурой editText.

Я получил пользу от этой ссылки

Вы можете использовать эти пули

           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());
                    }
                }
            }
        });
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.