gpt4 book ai didi

android - Android 中 XML 中的有序列表?

转载 作者:搜寻专家 更新时间:2023-11-01 09:12:37 24 4
gpt4 key购买 nike

我正在尝试在 TextView 中从 XML 制作一个有序列表。该列表将用项目符号和副标题适本地证明。不幸的是,似乎 xml 中对此的支持很少。我在 strings.xml 中尝试了以下内容:

<ol>
<li> item 1\n
<li>sub-item1\n</li>
<li>sub-item2\n</li>
<li>item2\n</li>
<li>item3</li>
</ol>

在每个项目周围都有各种排列,等等。结果通常显示子项目 2 和项目 2 缩进远离项目符号。我真的一直在挠头。任何关于这方面的指导都会很棒。

最佳答案

首先,创建一个自定义标签处理程序类:

package com.thecitybank.myca.ui;

import android.text.Editable;
import android.text.Html;
import android.text.Spanned;
import android.text.style.BulletSpan;
import android.text.style.LeadingMarginSpan;
import android.util.Log;

import org.xml.sax.XMLReader;

import java.util.Stack;

public class MyTagHandler implements Html.TagHandler {
private static final String OL_TAG = "ol";
private static final String UL_TAG = "ul";
private static final String LI_TAG = "li";


private static final int INDENT_PX = 10;
private static final int LIST_ITEM_INDENT_PX = INDENT_PX * 2;
private static final BulletSpan BULLET_SPAN = new BulletSpan(INDENT_PX);


private final Stack<ListTag> lists = new Stack<ListTag>();


@Override
public void handleTag(final boolean opening, final String tag, final Editable output, final XMLReader xmlReader) {
if (UL_TAG.equalsIgnoreCase(tag)) {
if (opening) { // handle <ul>
lists.push(new Ul());
} else { // handle </ul>
lists.pop();
}
} else if (OL_TAG.equalsIgnoreCase(tag)) {
if (opening) { // handle <ol>
lists.push(new Ol()); // use default start index of 1
} else { // handle </ol>
lists.pop();
}
} else if (LI_TAG.equalsIgnoreCase(tag)) {
if (opening) { // handle <li>
lists.peek().openItem(output);
} else { // handle </li>
lists.peek().closeItem(output, lists.size());
}
} else {
Log.d("TagHandler", "Found an unsupported tag " + tag);
}
}

/**
* Abstract super class for {@link Ul} and {@link Ol}.
*/
private abstract static class ListTag {
/**
* Opens a new list item.
*
* @param text
*/
public void openItem(final Editable text) {
if (text.length() > 0 && text.charAt(text.length() - 1) != '\n') {
text.append("\n");
}
final int len = text.length();
text.setSpan(this, len, len, Spanned.SPAN_MARK_MARK);
}

/**
* Closes a list item.
*
* @param text
* @param indentation
*/
public final void closeItem(final Editable text, final int indentation) {
if (text.length() > 0 && text.charAt(text.length() - 1) != '\n') {
text.append("\n");
}
final Object[] replaces = getReplaces(text, indentation);
final int len = text.length();
final ListTag listTag = getLast(text);
final int where = text.getSpanStart(listTag);
text.removeSpan(listTag);
if (where != len) {
for (Object replace : replaces) {
text.setSpan(replace, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}

protected abstract Object[] getReplaces(final Editable text, final int indentation);

/**
* Note: This knows that the last returned object from getSpans() will be the most recently added.
*
* @see Html
*/
private ListTag getLast(final Spanned text) {
final ListTag[] listTags = text.getSpans(0, text.length(), ListTag.class);
if (listTags.length == 0) {
return null;
}
return listTags[listTags.length - 1];
}
}

/**
* Class representing the unordered list ({@code <ul>}) HTML tag.
*/
private static class Ul extends ListTag {

@Override
protected Object[] getReplaces(final Editable text, final int indentation) {
// Nested BulletSpans increases distance between BULLET_SPAN and text, so we must prevent it.
int bulletMargin = INDENT_PX;
if (indentation > 1) {
bulletMargin = INDENT_PX - BULLET_SPAN.getLeadingMargin(true);
if (indentation > 2) {
// This get's more complicated when we add a LeadingMarginSpan into the same line:
// we have also counter it's effect to BulletSpan
bulletMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX;
}
}
return new Object[]{
new LeadingMarginSpan.Standard(LIST_ITEM_INDENT_PX * (indentation - 1)),
new BulletSpan(bulletMargin)
};
}
}

/**
* Class representing the ordered list ({@code <ol>}) HTML tag.
*/
private static class Ol extends ListTag {
private int nextIdx;

/**
* Creates a new {@code <ul>} with start index of 1.
*/
public Ol() {
this(1); // default start index
}

/**
* Creates a new {@code <ul>} with given start index.
*
* @param startIdx
*/
public Ol(final int startIdx) {
this.nextIdx = startIdx;
}

@Override
public void openItem(final Editable text) {
super.openItem(text);
text.append(Integer.toString(nextIdx++)).append(". ");
}

@Override
protected Object[] getReplaces(final Editable text, final int indentation) {
int numberMargin = LIST_ITEM_INDENT_PX * (indentation - 1);
if (indentation > 2) {
// Same as in ordered lists: counter the effect of nested Spans
numberMargin -= (indentation - 2) * LIST_ITEM_INDENT_PX;
}
return new Object[]{new LeadingMarginSpan.Standard(numberMargin)};
}
}
}

然后在您的 string.xml 中添加一个字符串,如下所示:

<string name="change_password_note"><![CDATA[<ol><li>Your password should contain at least one character of a-z, A-Z and 0-9. No special character is allowed.</li> <li>Please do not use any of your last three passwords.</li> <li>Please do not enter your User ID as password.</li> <li>Password minimum of 8 and maximum of 20 characters.</li></ol>]]></string>

最后,将文本设置到您的 TextView 中,如下所示:

txtNotesDescription.setText(Html.fromHtml(getString(R.string.change_password_note),null,new MyTagHandler()));

这对我有用。您可以通过使用 (ul) 标记来使用无序列表。

关于android - Android 中 XML 中的有序列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7153777/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com