Как получить BackgroundColorSpan для выбранного текста в android
Я пытаюсь установить BackgroundColorSpan на выделенный текст в Правке-тексте. Поэтому, когда я выбираю любой текст и нажимаю кнопку, он устанавливает цвет фона для этого конкретного текста, а затем я сохраняю эту заметку на SDCard с форматом .html, а затем снова получаю эту заметку для редактирования снова в том же формате.
Проблема, с которой я столкнулся сейчас, - это когда я применяю BackgroundColorSpan к выбранному тексту, он показывает эту строку с цветом фона, который я применил, но как только я сохраню эту заметку на SDCard и снова открою ее не отображает цвет фона для этой конкретной строки, а не показывает мне нормальную строку без цвета фона.
Ниже мой код, который я использовал для установки цвета фона в выделенную область редактирования текста
mSpannable.setSpan(new BackgroundColorSpan(color),startSelection, endSelection, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
и ниже - код для сохранения моих заметок на SD-карте.
Spanned spannedText = edtNoteDescription.getText();
StringBuilder output = new StringBuilder();
AppHtml.withinHtml(output, spannedText);
File mFile = new File(Environment.getExternalStorageDirectory()
+ File.separator + "MyNote/");
}
File myFile = new File(mFile, "/" + strNoteTitle + ".html/");
myFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(myFile);
OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
myOutWriter.append(output);
myOutWriter.close();
fOut.close();
С помощью этого выше кода я успешно могу сохранить файл в формате HTML, но я не получаю строку с цветом фона.
Я попытался напечатать эту строку в журнале, а затем вставить эту строку в w3School, тогда я получаю точный результат, чего я ожидаю, но в андроиде я не знаю, почему он не работает.
Строка, которую я получаю в Logcat, находится ниже
<p><font color ="#7dff00">This</font> <font color ="#ff5100">Is</font>  a  <font color ="#04ff00"><b><font style = "background-color:#2929dd">String</font></b></font>... </p>
Вы можете попробовать эту строку здесь, которая дает прекрасный результат с цветом фона для строки, но при настройке на android Edit-ext я не знаю что происходит, и оно не устанавливается, как я ожидаю.
Edit
Ниже приведен код, который я использовал для извлечения текста из файла SDcard
Bundle bundle = getIntent().getExtras();
strGetPath = bundle.getString(GlobalClass.notesPath);
filePath = new File(strGetPath);
fileInputStream = new FileInputStream(filePath);
int size = fileInputStream.available();
bytbuffer = new byte[size];
fileInputStream.read(bytbuffer);
fileInputStream.close();
String strGetData = new String(bytbuffer);
Spanned spanHTMLData = AppHtml.fromHtml(strGetData);
LogM.e("===== Getting Data =====" + strGetData);
edtNoteDescription.setText(spanHTMLData);
Ответы
Ответ 1
Та же самая проблема, с которой я столкнулся при создании проекта сохранения заметок HTML.
Как вы сказали, что вы создали свой собственный класс HTML.java, я также настроил тот же класс для своей цели.
По умолчанию класс Html.java не содержит функциональные возможности для фона, размера шрифта, пули и т.д.
Итак, я разделяю содержимое этого класса, чтобы вы могли получить от него идею установить Backround Color в HTML-примечание.
Предположим ваш настроенный Html.java = AppHtml.java, чтобы другие могли лучше понять его.
1) Сначала добавьте тег цвета фона в свой класс AppHtml.java. Добавьте этот ниже код в свой внутри параметра.
if (style[j] instanceof BackgroundColorSpan) {
out.append("<font style = \"background-color:#");
String color = Integer
.toHexString(((BackgroundColorSpan) style[j])
.getBackgroundColor() + 0x01000000);
while (color.length() < 6) {
color = "0" + color;
}
out.append(color);
out.append("\">");
}
затем заполните стиль шрифта, который вы запустили
if (style[j] instanceof BackgroundColorSpan) {
out.append("</font>");
}
2) Вот мой Шрифт класс
private static class Font {
public String mColor;
public String mFace;
public String mbgColor;
public String mSize;
public Font(String color, String face, String bgColor, String size) {
mColor = color;
mFace = face;
mbgColor = bgColor;
mSize = size;
}
}
3) Вот мой метод startFont.
private static void startFont(SpannableStringBuilder text,
Attributes attributes) {
String color = attributes.getValue("", "color");
String face = attributes.getValue("", "face");
String bgColor = attributes.getValue("", "style");
String size = attributes.getValue("", "size");
int len = text.length();
text.setSpan(new Font(color, face, bgColor, size), len, len,
Spannable.SPAN_MARK_MARK);
}
4) Вот мой метод endFont.
private static void endFont(SpannableStringBuilder text) {
int len = text.length();
Object obj = getLast(text, Font.class);
int where = text.getSpanStart(obj);
text.removeSpan(obj);
if (where != len) {
Font f = (Font) obj;
if (f.mColor != null) {
if (!TextUtils.isEmpty(f.mColor)) {
if (f.mColor.startsWith("@")) {
Resources res = Resources.getSystem();
String name = f.mColor.substring(1);
int colorRes = res.getIdentifier(name, "color",
"android");
if (colorRes != 0) {
ColorStateList colors = res
.getColorStateList(colorRes);
text.setSpan(new TextAppearanceSpan(null, 0, 0,
colors, null), where, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
int c = getHtmlColor(f.mColor);
if (c != -1) {
text.setSpan(
new ForegroundColorSpan(c | 0xFF000000),
where, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
}
if (f.mFace != null) {
text.setSpan(new TypefaceSpan(f.mFace), where, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (f.mbgColor != null) {
String bg_COLOR = f.mbgColor.substring(
f.mbgColor.lastIndexOf("#"), f.mbgColor.length());
if (!TextUtils.isEmpty(bg_COLOR)) {
if (bg_COLOR.startsWith("@")) {
Resources res = Resources.getSystem();
String name = bg_COLOR.substring(1);
int colorRes = res.getIdentifier(name, "color",
"android");
if (colorRes != 0) {
ColorStateList colors = res
.getColorStateList(colorRes);
text.setSpan(new TextAppearanceSpan(null, 0, 0,
colors, null), where, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
} else {
int c = getHtmlColor(bg_COLOR);
if (c != -1) {
text.setSpan(
new BackgroundColorSpan(c | 0xFF000000),
where, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
}
if (f.mSize != null) {
if (!TextUtils.isEmpty(f.mSize)) {
int size = Integer.parseInt(f.mSize);
text.setSpan((new AbsoluteSizeSpan(size)), where, len,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
}
}
Ответ 2
Я не знаю, что есть AppHtml
в исходном коде, но для Html ↔ Spannable parsing в Android мы используем класс android.text.Html
. По какой-то причине этот класс, хотя не поддерживает BackgroundColorSpan
.
Я бы предложил экспериментировать с методом Html.fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler)
и передать TagHandler
для поддержки того, что вам нужно. Документы здесь.
Ответ 3
- Создайте свой собственный формат и сохраните его в файле
Я не знаю, это именно то, что вы ищете, но я не вижу смысла использовать HTML здесь. Как указывалось в других ответах, fromHtml()
довольно ограничен, и использование пользовательского формата файла решит вашу проблему сохранения/восстановления в кратчайшие сроки.
Вам необходимо сохранить в файле следующие данные:
-
Сколько пролетов у вас есть
-
начало, конец, цвет для каждого диапазона
-
ваш текст
В следующем фрагменте кода показано, как реализовать методы хранения и загрузки. Он использует текст Spanned
в TextView
. полный проект Eclipse занял у меня около получаса и здесь можно найти здесь.
public void store(View v)
{
Spanned s = (Spanned) mTextView.getText();
BackgroundColorSpan[] spans = s.getSpans(0, s.length(), BackgroundColorSpan.class);
BufferedWriter bw = null;
try
{
int len = spans.length;
bw = new BufferedWriter(new FileWriter(mFile));
bw.write(String.valueOf(len));
bw.newLine();
for (BackgroundColorSpan span : spans)
{
int start = s.getSpanStart(span);
int end = s.getSpanEnd(span);
int color = span.getBackgroundColor();
bw.write("" + start + "," + end + "," + color);
bw.newLine();
}
bw.write(mText);
clear(v);
}
catch (IOException e)
{
Log.e(TAG, "IO error", e);
}
finally
{
closeQuietly(bw);
}
}
public void load(View v)
{
BufferedReader br = null;
try
{
br = new BufferedReader(new FileReader(mFile));
int len = Integer.parseInt(br.readLine());
BackgroundColorSpan[] spans = new BackgroundColorSpan[len];
int[] starts = new int[len];
int[] ends = new int[len];
for (int i = 0; i < len; i++)
{
String[] tokens = br.readLine().split(",");
starts[i] = Integer.parseInt(tokens[0]);
ends[i] = Integer.parseInt(tokens[1]);
int color = Integer.parseInt(tokens[2]);
spans[i] = new BackgroundColorSpan(color);
}
mText = br.readLine();
SpannableString s = new SpannableString(mText);
for (int i = 0; i < len; i++)
{
s.setSpan(spans[i], starts[i], ends[i], Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mTextView.setText(s);
}
catch (IOException e)
{
Log.e(TAG, "IO error", e);
}
finally
{
closeQuietly(br);
}
}
Ответ 4
Текущая реализация Html.fromHtml
поддерживает только атрибуты Font
color
и typeface
. Вы можете проверить здесь здесь.
Как вы сказали, вы используете модифицированную версию Html
, гораздо проще поддерживать дополнительные атрибуты самостоятельно.
При анализе XML, когда обнаружен тег открытого шрифта, все значения атрибута шрифта хранятся в Font
частном классе. Когда встречается тег закрытия шрифта, для каждого из этих атрибутов применяйте соответствующие стили span.
Шаг 1: В Font
private class добавьте элемент данных для хранения фона и измените конструктор, чтобы принять дополнительный параметр.
private static class Font {
...
public String mBackgroundColor; // Data member to hold background color
public Font(String color, String face, String backgroundColor) {
...
mBackgroundColor = backgroundColor;
}
...
}
Шаг 2. В методе startFont
обрабатывайте атрибут background-color
.
private static void startFont(SpannableStringBuilder text,
Attributes attributes) {
...
String backgroundColor = null;
// In this specific example, background-color attribute is present in style attribute.
String style = attributes.getValue("", "style");
if(style != null && style.contains("background-color")) {
String[] array = style.split(":");
if(array.length == 2)
backgroundColor = array[1];
} else {
// If background-color is specified as an attribute itself use this
backgroundColor = attributes.getValue("", "background-color");
}
// Pass the background-color to the Font constructor
text.setSpan(new Font(color, face, backgroundColor), len, len, Spannable.SPAN_MARK_MARK);
}
Шаг 3: В endFont
добавьте текст BackgroundColorSpan
в текст.
private static void endFont(SpannableStringBuilder text) {
...
if(f.mBackgroundColor != null) {
text.setSpan(new BackgroundColorSpan(Color.parseColor(f.mBackgroundColor)), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
P.S.: Поскольку конструктор Html
является закрытым, специализация Html
невозможна.
Ответ 5
К сожалению, fromHtml()
довольно ограничен, и не может проанализировать атрибут стиля шрифта.
Скорее старый пост в блоге Commonware содержит список рабочих атрибутов.
У вас есть несколько вариантов:
- Установите промежутки фона вручную.
- Создайте свой собственный синтаксический анализатор, который поддерживает это, и передайте его публике (yay)
- Использовать WebView
Теперь использование WebView похоже на самое сложное решение, поэтому вот пример:
WebView webView = (WebView) findViewById(R.id.webView);
String strGetData = "<p><font color =\"#7dff00\">This</font> <font color =\"#ff5100\">Is</font>  a  <font color =\"#04ff00\"><b><font style = \"background-color:#2929dd\">String</font></b></font>... </p>\n";
webView.loadData(strGetData, "text/html", "utf-8");