Объясните значение флагов Span, таких как SPAN_EXCLUSIVE_EXCLUSIVE
Может кто-то четко объяснить с примерами, что нравится каждый из флагов span SPAN_EXCLUSIVE_EXCLUSIVE
а также SPAN_MARK_MARK
значит и когда использовать какие флаги?
Я не понимаю официальную документацию, когда говорится:
Пролеты типа
SPAN_EXCLUSIVE_EXCLUSIVE
не расширяйте, чтобы включить текст, вставленный в их начальной или конечной точке.
Относится ли "развернуть, чтобы включить" к правкам, внесенным после вставки пролетов?
Означает ли это, что эти флаги НЕ влияют на Spannables с неизменным текстом?
3 ответа
Относится ли "развернуть, чтобы включить" к правкам, внесенным после вставки пролетов?
Да. Например, предположим, у нас есть следующее:
Быстрая лиса прыгнула.
Если бы мы использовали SPAN_EXCLUSIVE_EXCLUSIVE
на полужирном промежутке, и мы вставляем текст в середину промежутка, он все еще полужирный:
Быстрая коричневая лиса подпрыгнула.
Однако если мы вставим текст в начале или в конце полужирного интервала, вставленный текст не будет выделен жирным шрифтом:
Действительно быстрый лис прыгнул.
Если, однако, мы использовали SPAN_INCLUSIVE_EXCLUSIVE
затем вставка текста в начале будет включена как часть диапазона, и мы получим:
Действительно быстрый лис прыгнул.
Означает ли это, что эти флаги НЕ влияют на Spannables с неизменным текстом?
Я бы сказал, что они имеют ограниченное использование для неизменного текста. В основном, они будут использоваться с SpannableStringBuilder
или вещи, которые используют один под одеялом (например, EditText
).
Что не значат флаги
Когда я впервые увидел INCLUSIVE
а также EXCLUSIVE
части Spannable
флаги, я думал, что они только сказали, включал ли промежуток начальную и конечную позиции индекса промежутка. Это неправда. Позвольте мне проиллюстрировать это на следующем примере.
String myString = "01234";
int start = 1;
int end = 3;
int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; // this is what is changing
SpannableString spannableString = new SpannableString(myString);
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(foregroundSpan, start, end, spanFlag);
textView.setText(spannableString);
Вот результаты:
SPAN_INCLUSIVE_INCLUSIVE
SPAN_INCLUSIVE_EXCLUSIVE
SPAN_EXCLUSIVE_INCLUSIVE
SPAN_EXCLUSIVE_EXCLUSIVE
Они все одинаковы! Флаги не влияют на промежуток. Интервал всегда включает символ в своем начальном индексе и исключает символ в конечном индексе.
Что на самом деле означают флаги
INCLUSIVE
а также EXCLUSIVE
части флагов Spannable фактически указывают, должен ли диапазон включать текст, который вставляется в начальную или конечную позиции.
Вот модифицированный пример, чтобы проиллюстрировать это.
String myString = "01234";
int start = 1;
int end = 3;
int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; // this is what is changing
// set the span
SpannableStringBuilder spannableString = new SpannableStringBuilder(myString);
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(foregroundSpan, start, end, spanFlag);
// insert the text after the span has already been set
// (inserting at start index second so that end index doesn't get messed up)
spannableString.insert(end, "x");
spannableString.insert(start, "x");
textView.setText(spannableString);
Вот результаты после вставки x
в конце и в начале индексы:
SPAN_INCLUSIVE_INCLUSIVE
SPAN_INCLUSIVE_EXCLUSIVE
SPAN_EXCLUSIVE_INCLUSIVE
SPAN_EXCLUSIVE_EXCLUSIVE
Заметки
- Большая часть этого ответа описывает вещи, которые ОП уже знал. Я просто добавляю это для будущих посетителей как я, которые не знали этих вещей.
- Во втором примере я должен был использовать
SpannableStringBuilder
потому что текст вSpannableString
является неизменным, поэтому вы не можете вставить текст в него. Таким образом, флаги, как правило, не имеют смысла дляSpannableString
, Однако можно представить себе ситуацию, когдаSpannableString
скопировать вSpannableStringBuilder
или жеEditable
и оттуда флаги будут иметь значение. - Смотрите этот ответ для разницы между
SpannableString
,SpannableStringBuilder
,Editable
, и больше.
Значения String, которые мы храним как ресурс в XML-файле в каталоге res/values, можно стилизовать с помощью методов, определенных в интерфейсе android.text.Spannable, а поля, определенные в интерфейсе android.text.Spanned (Spannable - это подинтерфейс Spanned), с классом android.text.SpannableStringBuilder (SpannableStringBuilder является подклассом Spannable) и с классами, определенными в пакете android.text.style, особенно для android.text.style.ForegroundColorSpan android.text.style.StyleSpan классы. Поскольку SpannableStringBuilder является подклассом Spannable, а Spannable является подынтерфейсом Spanned. Все поля интерфейса Spanned и полная реализация методов интерфейса Spannable существуют в классе SpannableStringBuilder.
1. Теперь, чтобы стилизовать текстовый ресурс, мы должны сначала получить его с идентификатором ресурса с помощью метода метода getString(int resource_id) из объекта Resources, чтобы получить объект Resources, связанный с подклассом Context, который мы вызываем методом getResources(). пример-
String title = getResources(). GetString (R.string.string_title);
2. Теперь нам нужно создать объект SpannableStringBuilder с его открытым конструктором без параметров или любым другим открытым конструктором.
3.SpannableStringBuilder работает немного сложным образом. Мы можем добавить текст в SpannableStringBuilder с помощью одного из методов добавления. Некоторая часть текста, которую содержит SpannableStringBuilder, может быть помечена как составная, и только эта часть будет стилизована (с цветом, шрифтом и т. Д.).), когда новый текст добавляется в объект SpannableStringBuilder с любым индексом, если новый текст также будет помечен как расширенный или нет, что определяется полями интерфейса Spanned. Мы вызываем метод setSpan(Object what, int start, int end, int flags), объявленный интерфейсом Spannable и реализованный классом SpannableStringBuilder. Вот что является объектом класса пакета android.text.style.StyleSpan. Этот объект определяет тип стиля, который мы хотим применить. Флаги - это одно из полей, определенных в интерфейсе Spanned, этот параметр flags указывает, когда новый текст добавляется в этот объект SpannableStringBuilder по любому индексу, если новый текст также будет помечен как составной или нет.
4. Различные классы пакета android.text.style.StyleSpan определяют разные стили, но на данный момент я знаю только одно использование класса android.text.style.StyleSpan и одно использование android.text.style.ForegroundColorSpan учебный класс. Один открытый конструктор класса StyleSpan принимает значение int, которое может быть значением одного из полей, определенных в классе android.graphics.Typeface ( BOLD,BOLD_ITALIC,ITALIC,NORMAL). Поскольку эти имена полей предполагают, что они будут стилизовать текст жирным шрифтом или полужирным шрифтом или курсивом или нормальным. Например-
StyleSpan style_span = новый StyleSpan(Typeface.ITALIC);
Один открытый конструктор класса ForegroundColorSpan принимает значение типа int, которое может быть любым шестнадцатеричным значением цвета argb или значением одного из полей, определенных в классе android.graphics.Color ( BLACK,BLUE,CYAN,DKGRAY,GREY,GREEN,LTGRAY,MAGENTA,RED,TRANSPARENT,WHITE,YELLOW). Поскольку имена этих полей предполагают, что они окрашивают текст. Чтобы дать шестнадцатеричное значение цвета argb в качестве int для конструктора, мы начинаем шестнадцатеричное значение с 0X или 0x, Java затем автоматически преобразует шестнадцатеричное значение в его int-эквивалент. Например-
ForegroundColorSpan fore_ground_color_Span = new ForegroundColorSpan (Color.RED);
5. В методе setSpan(Object what, int start, int end, int flags) начало и конец определяют начальный диапазон текста, который должен быть помечен как составной, начало определяет индекс начальных символов, а конец указывает Индекс символа переданного конечного символа, например, для строки "01234"
новый SpannableStringBuilder("01234").setSpan(foreground_color_span, 1, 3, span_flag);
приведет к тому, что только 12 будут помечены как натянутые изначально, поэтому начальный символ - это "1", как указано в начальном индексе, а конечный символ - это 2, как указано в индексе (конец-1). Таким образом, если мы дадим одинаковое значение для начала и конца, то текст не будет покрыт изначально, а диапазон будет равен нулю, для приведенного выше примера, если оба начала и конца равны 1, тогда начальный символ равен 1, но конечный символ равен 0. это не имеет смысла, в этом случае не будет текста, помеченного как натянутый изначально.
6. Теперь некоторые поля интерфейса Spanned работают, как описано ниже. Когда добавляется новый текст.......... SPAN_EXCLUSIVE_EXCLUSIVE не помечает любой текст, добавляемый перед начальным символом и после конечного символа, как составной, но помечает любой текст, добавляемый после начального символа или перед конечным символом как SPAN_EXCLUSIVE_EXCLUSIVE является синонимом SPAN_POINT_MARK, если диапазон равен нулю, что означает, что текст не помечен как составной изначально, то любой текст, добавляемый по любому индексу, не помечается как объединенный с этим флагом,
SPAN_EXCLUSIVE_INCLUSIVE не помечает любой текст, добавляемый перед начальным символом как составной, но помечает любой текст, добавляемый после начального символа или любой текст, добавляемый до или после конечного символа, как составной, согласно моим тестам, SPAN_EXCLUSIVE_INCLUSIVE является синонимом для SPAN_POINT_POINT, если диапазон равен нулю, что означает, что текст не был помечен как составной изначально, тогда любой текст, добавленный к любому индексу, не помечается как составной с этим флагом
SPAN_INCLUSIVE_EXCLUSIVE не помечает любой текст, добавляемый перед конечным символом как составной, но помечает любой текст, добавленный после или перед начальным символом, или любой текст, добавляемый после конечного символа, как составной, согласно моим тестам, SPAN_INCLUSIVE_EXCLUSIVE является синонимом для SPAN_MARK_MARK, если диапазон равен нулю, что означает, что текст не был помечен как составной изначально, тогда любой текст, добавленный к любому индексу, не помечается как составной с этим флагом
SPAN_INCLUSIVE_INCLUSIVE помечает любой текст, добавляемый после или перед начальным и конечным символом как составной,SPAN_INCLUSIVE_INCLUSIVE является синонимом SPAN_MARK_POINT, если диапазон равен нулю, что означает, что текст не помечен как составной изначально, затем любой текст, добавленный в любом индексе после или до начальный или конечный символ всегда помечается как охватываемый этим флагом,
Я не смог правильно понять другие константы флагов, определенные в интерфейсе Spanned.
7. Теперь мы можем добавить любой текст в наш объект SpannableStringBuilder с помощью одного из методов добавления или одного из методов вставки, например:
SpannableStringBuilder text = new SpannableStringBuilder(); ...... text.append(string_value); //append(CharSequence text) добавляет данную строку в конец //insert(int where, CharSequence tb) вставляет данную строку после символа, индекс которого равен (where-1)
Новый текст, вставленный в этот SpannableStringBuilder, будет помечен как "составной и стилизованный" или нет, будет зависеть от флага, который мы указали при предыдущем вызове метода setSpan(Object what, int start, int end, int flags).
8. Если мы хотим применить более одного стиля к тексту в объекте SpannableStringBuilder, то мы можем снова вызвать метод setSpan(Object what, int start, int end, int flags) и указать стиль для параметра what, и начало и конец должны быть стилизованы изначально, затем параметр flag, чтобы указать, как стиль должен вести себя при вставке любого нового текста. Здесь важно то, что когда мы вызываем метод span, указанный нами стиль соединяется с началом, концом и флагом, который не зависит от любого предыдущего вызова метода span, что означает, что каждый вызов метода span применяет стиль, который работает независимо от любого другого стиля, который также применяется к тому же тексту. Даже если мы снова применяем тот же стиль, но с новым объектом к параметру "what", этот стиль также работает независимо от ранее примененного того же стиля, только для изменить уже примененный стиль, чтобы указать тот же объект для параметра "что". Например-
TextView txv=(TextView)findViewById(R.id.textView9);
String myString = "01234";
Object ob;
int start = 1;
int end = 4;
int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE;
SpannableStringBuilder spannableString = new SpannableStringBuilder(myString);
ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED);
ob=foregroundSpan;
spannableString.setSpan(foregroundSpan, start, end, spanFlag);
txv.setText(spannableString);
Это приведет к тому, что txv имеет "01234", где часть "123" имеет красный цвет.
end=3;
spanFlag = Spannable.SPAN_EXCLUSIVE_INCLUSIVE;
spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, spanFlag);
txv.setText(spannableString);
Это приведет к тому, что txv имеет "01234", где часть "123" имеет красный цвет, а часть "12" выделена жирным шрифтом (жирный) и красный, но "3" только красный, а не жирный из-за "конца" значение.
spannableString.insert(end, "x");
spannableString.insert(start, "x");
txv.setText(spannableString);
Это приведет к тому, что txv будет иметь "0x12x34", где часть "x12x3" выделена красным, а только "12x3" выделена жирным шрифтом, это произошло потому, что красный стиль был изначально применен к тексту "123" с флагом SPAN_INCLUSIVE_INCLUSIVE, что означает любой текст после или до 1 и 3 всегда включаются в красную область стилей, следовательно, "x12x3" красного цвета, жирный стиль был первоначально применен к тексту "12" с флагом SPAN_EXCLUSIVE_INCLUSIVE, что означает, что любой текст, добавленный до 1, не включен в область стиля, но любой текст, добавляемый после 1 и после или до 2, всегда включается в режим жирного шрифта, поэтому только жирный шрифт "12x3".
int end=3;
spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
foregroundSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(foregroundSpan, start, end, spanFlag);
txv.setText(spannableString);
Это вызовет еще один независимый красный стиль для текста "x1", но, поскольку уже другой красный стиль применяется к тексту "x12x3", мы не увидим никакой разницы в txv. Чтобы фактически изменить ранее примененный красный стиль, нам нужно передать тот же объект ForegroundColorSpan, который мы делали, когда мы вызывали метод setSpan в первый раз, мы должны использовать следующий код вместо приведенного выше:
int end=3;
spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE;
spannableString.setSpan(ob, start, end, spanFlag); //ob refers to the same the styling object as we specified on the first occasion
txv.setText(spannableString);
Это приведет к тому, что только "x1" будет красным, а также, если мы добавим какой-либо текст после "1" или перед "x", то этот текст не будет включен в красную область стиля, но любой текст после "x" и до " 1 "всегда включен в красную область стилей из-за флага SPAN_EXCLUSIVE_EXCLUSIVE, который мы указали на этот раз.
9.Последнее, если мы хотим полностью удалить стиль и его флаг-флаг span, то мы можем вызвать метод removeSpan(Object what), определенный интерфейсом Spannable, реализованным классом SpannableStringBuilder, нам нужно передать тот же объект стиля в метод removeSpan как мы дали методу setSpan.
Благодаря приведенным выше ответам, особенно пример цвета помог мне понять эти флаги должным образом.