Jak dodać listę punktowaną do aplikacji na Androida?

91

Wyszukałem w Google moje pytanie, ale nie ma działającej odpowiedzi. Jak dodać listę punktowaną do mojego widoku tekstu.

user590849
źródło

Odpowiedzi:

189

Trudne do zrobienia, ponieważ ul / li / ol nie są obsługiwane. Na szczęście możesz użyć tego jako cukru syntaktycznego:

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

&#8226;jest jednostką html dla listy punktorów więcej opcji jest tutaj http://www.elizabethcastro.com/html/extras/entities.html

więcej o tym, które tagi są obsługiwane, dostarcza Mark Murphy (@CommonsWare) http://commonsware.com/blog/Android/2010/05/26/html-tags-supported-by-textview.html Załaduj to za pomocą Html.fromHtml

((TextView)findViewById(R.id.my_text_view)).setText(Html.fromHtml(myHtmlString));
browep
źródło
1
Dzięki za link do strony commonsware, szukałem czegoś takiego od jakiegoś czasu!
Norman H
4
Zwróć uwagę, że jeśli otrzymujesz ciąg z wartości / strings.xml (używając context.getString (R.string.yourstring);), będziesz musiał zawinąć go w CDATA : <string name="string_name"><![CDATA[ &#8226; foo<br /> &#8226; bar... ]]></string>
Quentin S.
5
to nie działa, jeśli jest więcej niż jedna linia w pozycji
punktora
wygląda na to, że ul/ lijest teraz obsługiwany stackoverflow.com/questions/9754076/ ...
hmac
55
  1. Browep ładnie wyjaśnił sposób korzystania z HTML. Przydatne może być dostarczone rozwiązanie z encją html. Ale zawiera tylko kulę. Jeśli tekst się zawija, wcięcie nie będzie poprawne.

  2. Znalazłem inne rozwiązania osadzające widok sieciowy. To może być odpowiednie dla niektórych, ale myślę, że to przesada ... (To samo dotyczy korzystania z widoku listy).

  3. Podoba mi się kreatywne podejście Nelson : D, ale nie daje ono możliwości dodawania nieuporządkowanej listy do widoku tekstu.

  4. Mój przykład nieuporządkowanej listy z punktorami przy użyciu 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));
    

Pozytywny:

  • Punktory z poprawnym wcięciem po zawijaniu tekstu.
  • W jednym wystąpieniu TextView można łączyć inny sformatowany lub niesformatowany tekst
  • W konstruktorze BulletSpan można zdefiniować, jak duże powinno być wcięcie.

Negatywny:

  • Musisz zapisać każdy element listy w osobnym zasobie ciągu. Więc nie możesz zdefiniować swojej listy tak wygodnie, jak można by to zrobić w HTML.
Diego Frehner
źródło
1
To podejście (dokładnie naśladowane) nie działa w wersji 2.2. Kończysz tylko z jedną kulą.
Skone
Cześć Skone, działa w emulatorze 2.2 i oryginalnych kompilacjach Androida. Widziałem wersję Androida, w której przestrzeń między punktorem a tekstem została zignorowana. Ale kula wciąż się pojawiała. Czy masz nową linię na końcu swoich ciągów pocisków?
Diego Frehner
To rozwiązanie nie działa, gdy zmienisz odstępy między wierszami w widoku
tekstu
Świetny sposób na zrobienie tego z BulletSpan, działa doskonale i jest bardzo łatwy!
Moonbloom
7
Powyższy kod u mnie działa !!! Wszystko, co musiałem zrobić, to dodać „\ n” na końcu każdego ciągu w
formacie
38

Znalazłem alternatywę ... po prostu skopiuj ten punktor „•” (jest to tekst) i wklej w tekście widoku tekstu. Możesz zmienić kolor punktora, zmieniając kolor tekstu i wszystkie inne atrybuty, takie jak rozmiar, wysokość, szerokość. .. :)

możesz użyć skrótu, aby uzyskać ten punktor podczas pisania

dla Windowsa

ALT + 7

dla Maca

ALT + 8

Ishtiaq
źródło
2
Alt + 7 nie działa dla mnie (być może to tylko kwestia Maca lub Linuksa), ale kopiowanie i wklejanie znaku Unicode • działało.
Jon
2
FYI: ALT + 7 będzie działać tylko wtedy, gdy klawiatura ma oddzielny numer.
Aks4125
Jeśli wkleisz symbol w kodzie, tj. W ciągu znaków, pamiętaj o problemach ze znakami innymi niż ASCII i kodowaniem plików (spróbuj zmienić kodowanie pliku z prawego dolnego rogu IntelliJ). Lepiej byłoby użyć odpowiedniej sekwencji ucieczki (np. \ U1234).
Gil Vegliach
Tak trzymaj !! życie bandytów!
goonerDroid
2
\ u2022 jest odpowiedzią
user2322082
21

Zainspirowany różnymi odpowiedziami tutaj, stworzyłem klasę Utility, aby uczynić to prostym . Spowoduje to utworzenie listy punktowanej z wcięciem dla zawiniętego tekstu. Zawiera metody łączenia ciągów, zasobów ciągów i zasobów tablic ciągów.

Utworzy CharSequence, które możesz przekazać do TextView. Na przykład:

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

Mam nadzieję, że to pomocne. Cieszyć się.

Uwaga: zostanie użyty standardowy punktor systemowy, małe kółko w tym samym kolorze co tekst. Jeśli chcesz niestandardowy punktor, rozważ podklasę BulletSpan i zastąpienie jej, drawLeadingMargin()aby narysować żądany punktor. Spójrz na źródło BulletSpan, aby dowiedzieć się, jak to działa.

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

}
bawełny
źródło
Dziękuję drogi panie! Skorzystałem z funkcji makeBulletList i działa jak marzenie: D
Aba
To jest zajebiste! Dziękuję)
kulikovman
10

To jest zdecydowanie najłatwiejsze.

<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
źródło
8

Gotowe do użycia rozszerzenie 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
        }
    }
}

Stosowanie:

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

Kolory i rozmiar:

Aby zmienić kolor lub rozmiar punktora, użyj CustomBulletSpan zamiast 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)
        }
    }
}
Michaił Sharin
źródło
Czy możesz jakoś zmienić rozmiar punktora, aby pasował do rozmiaru tekstu?
nenur
@NoahTanenholtz możesz zwiększyć rozmiar pocisku, zmieniając wartość argumentu BulletSpan ()
Mikhail Sharin
Och, myślałem, że to odstęp
nenur
Zwiększono odstępy zamiast rozmiaru pocisku):
Sumit Shukla
@SumitShukla dziękuję za komentarz. Właśnie dodałem BulletCustomSpan, aby dostosować kolor i rozmiar
Mikhail Sharin
4

Opcją, której użyłem, było ustawienie pocisku do rysowania za pomocą stylu.

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

Stosowanie:

<TextView android:id="@+id/tx_hdr" 
android:text="Item 1" style="@style/Text.Bullet" />
Nelson Ramirez
źródło
Właśnie złapałem mały obrazek z kulą z sieci, aby go wyciągnąć. Układ graficzny w Eclipse pokazuje grafikę rozciągniętą pod tekstem ... raczej daleko od tego, co chciałem.
JohnK,
1
Myślę, że miał na myśliandroid:drawableLeft=
Blundell
4

użyj prostego TextView ze złożonym rysowalnym. Na przykład

<TextView     
    android:text="Sample text"
    android:drawableLeft="@drawable/bulletimage" >
</TextView>
Nouman Hanif
źródło
3

Oto inne rozwiązanie, niezupełnie dodając listę do jednego widoku tekstu, ale myślę, że cel jest ten sam. Używa TableLayout, który potrzebuje tylko XML i jest naprawdę prosty w przypadku małych uporządkowanych lub nieuporządkowanych list. Poniżej przykładowy kod, którego użyłem do tego, a nie wiersz kodu w Javie.

Pozytywny:

  • możesz umieścić cokolwiek chcesz w wierszach tabeli, nie musi to być widok tekstu
  • możesz go użyć do stworzenia listy wypunktowanej i numerowanej lub cokolwiek innego
  • możesz zdefiniować wcięcie za pomocą dopełnienia lub układu_wagi

Negatywny:

  • nużące dla bardzo długich list (chyba że używasz jakiegoś sprytnego edytora tekstu z wyrażeniem regularnym)
  • każdy element listy jest przechowywany jako oddzielny zasób ciągu

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

i styl:

<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
źródło
2

Oto lista punktowana z nagłówkiem i kartą przed każdym elementem.

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
źródło
2

Całkowicie przesadziłem i stworzyłem niestandardowy widok tekstu.

Użyj tego w ten sposób:

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

i kod:

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
źródło
Jak możemy zwiększyć rozmiar i odstępy między pociskami?
Sumit Shukla
W tym przykładzie &#8226;musisz wybrać inny symbol fsymbols.com/signs/bullet-point
Blundell
1

Uważam, że jest to najłatwiejszy sposób, pozostaw textView tak, jak jest w pliku xml i użyj następującego kodu java. dla mnie działało doskonale.

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
źródło
1

Listę punktowaną można po prostu utworzyć za pomocą tagów <ul>i <li>w zasobie ciągu.

NIE UŻYWAJ setText (Html.fromHtml (string)), aby ustawić ciąg w kodzie! Po prostu ustaw ciąg normalnie w xml lub za pomocą setText ( string ).

Na przykład:

plik strings.xml

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


plik layout.xml

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


To da następujący wynik:

  • pierwsza pozycja
  • poz.2


Następujące tagi są obsługiwane w ten sposób (bezpośrednio osadzone w zasobie ciągu):

  • <a> (obsługuje atrybuty „href”)
  • <adnotacja>
  • <b>
  • <big>
  • <font> (obsługuje atrybuty „wysokość”, „rozmiar”, „fgcolor” i „bicolor” jako liczby całkowite)
  • <i>
  • <li>
  • <marquee>
  • <small>
  • <strike>
  • <sub>
  • <sup>
  • <tt>
  • <u>
Abhishek
źródło
nie potrzebujesz<ul>
Blundell
5
Nie działa. Obsługiwane tagi html to tylko <b>, <i> i <u>. developer.android.com/guide/topics/resources/…
Wooff,
U mnie zadziałało idealnie! Jedyną rzeczą, jaką musiałem zrobić, aby wszystko działało, było umieszczenie \ n na początku każdego wiersza. tj.\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul>
Jack T
1

Dla single line textmożesz po prostu użyć kanału alfa:

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

Możesz zmienić shape, sizew colorzależności od swoich wymagań.

Sumit Shukla
źródło
0

Dwie opcje tworzenia listy punktowanej to

  • utwórz listę za pomocą html (ul, ol) i załaduj HTML do WebView
  • Załaduj dane do ListView i ustaw lewy element rysunkowy widoku tekstu w układzie elementu listy na odpowiedni obraz dla punktora.

Opcja 1 jest najłatwiejsza.

Robby Pond
źródło
0

innym sposobem obsługi brakujących tagów HTML jest ich ładna zamiana, jak pokazano tutaj

programista Androida
źródło
0

Jeśli chcesz utworzyć listę punktowaną ze strukturą editText.

Skorzystałem na tym referencji

Możesz użyć tych kul

           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ş
źródło