Wyszukałem w Google moje pytanie, ale nie ma działającej odpowiedzi. Jak dodać listę punktowaną do mojego widoku tekstu.
91
Trudne do zrobienia, ponieważ ul / li / ol nie są obsługiwane. Na szczęście możesz użyć tego jako cukru syntaktycznego:
• foo<br/>
• bar<br/>
• baz<br/>
•
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));
<string name="string_name"><![CDATA[ • foo<br /> • bar... ]]></string>
ul
/li
jest teraz obsługiwany stackoverflow.com/questions/9754076/ ...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.
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).
Podoba mi się kreatywne podejście Nelson : D, ale nie daje ono możliwości dodawania nieuporządkowanej listy do widoku tekstu.
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:
Negatywny:
źródło
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
dla Maca
źródło
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; } }
źródło
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>
źródło
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) } } }
źródło
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" />
źródło
android:drawableLeft=
użyj prostego TextView ze złożonym rysowalnym. Na przykład
<TextView android:text="Sample text" android:drawableLeft="@drawable/bulletimage" > </TextView>
źródło
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:
Negatywny:
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>
źródło
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 = "•"; 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(); } }
źródło
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 = "•"; 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); } }
źródło
•
musisz wybrać inny symbol fsymbols.com/signs/bullet-pointUważ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 = "•"; @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")); }
źródło
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:
Następujące tagi są obsługiwane w ten sposób (bezpośrednio osadzone w zasobie ciągu):
źródło
<ul>
\n<ul><li>a</li> \n<li>b</li> \n<li>c</li></ul>
Dla
single line text
moż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
,size
wcolor
zależności od swoich wymagań.źródło
Dwie opcje tworzenia listy punktowanej to
Opcja 1 jest najłatwiejsza.
źródło
innym sposobem obsługi brakujących tagów HTML jest ich ładna zamiana, jak pokazano tutaj
źródło
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()); } } } });
źródło