Android - выделить слово в TextView?
У меня есть database search query
который ищет в базе данных слово, введенное пользователем, и возвращает Cursor
,
В моем ListActivity
, У меня есть ListView
который будет содержать предметы (предметы Cursor). ListView
расположение элементов в основном TextView
, Я имею в виду, ListView
будет список TextView
"S.
То, что я хочу, это выделить search term
где бы он ни появлялся в TextView
, Я имею в виду выделение: другой цвет или другой цвет фона или что-то делает его отличным от остального текста.
Это возможно? и как?
Обновить:
cursor = myDbHelper.search(term); //term: a word entered by the user.
cursor.moveToFirst();
String[] columns = {cursor.getColumnName(1)};
int[] columnsLayouts = {R.id.item_title}; //item_title: the TextView holding the one raw
ca = new SimpleCursorAdapter(this.getBaseContext(), R.layout.items_layout, cursor,columns , columnsLayouts);
lv = getListView();
lv.setAdapter(ca);
Для @Shailendra: search()
Метод вернет несколько заголовков. Я хочу выделить слова в тех заголовках, которые соответствуют term
слово. Надеюсь, теперь это понятно.
7 ответов
Вставьте HTML-код для цвета вокруг слова и установите его для вашего textView .
лайк
String newString = oldString.replaceAll(textToHighlight, "<font color='red'>"+textToHighlight+"</font>");
textView.setText(Html.fromHtml(newString));
TextView textView = (TextView)findViewById(R.id.mytextview01);
//use a loop to change text color
Spannable WordtoSpan = new SpannableString("partial colored text");
WordtoSpan.setSpan(new ForegroundColorSpan(Color.BLUE), 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(WordtoSpan);
Числа 2 и 4 являются индексами начала / остановки для окраски текста, в этом примере "rti" будет окрашен.
Таким образом, вы просто нашли бы начальный индекс вашего поискового слова в заголовке:
int startIndex = titleText.indexOf(term);
int stopIndex = startIndex + term.length();
а затем замените цифры 2 и 4 на индексы, а "частичный цветной текст" - на строку заголовка.
Более легкий путь
Вы можете использовать Spannable класс для выделения / форматирования части текста.
textView.setText("Hello, I am Awesome, Most Awesome"); // set text first
setHighLightedText(textView, "a"); // highlight all `a` in TextView
Вот метод.
/**
* use this method to highlight a text in TextView
*
* @param tv TextView or Edittext or Button (or derived from TextView)
* @param textToHighlight Text to highlight
*/
public void setHighLightedText(TextView tv, String textToHighlight) {
String tvt = tv.getText().toString();
int ofe = tvt.indexOf(textToHighlight, 0);
Spannable wordToSpan = new SpannableString(tv.getText());
for (int ofs = 0; ofs < tvt.length() && ofe != -1; ofs = ofe + 1) {
ofe = tvt.indexOf(textToHighlight, ofs);
if (ofe == -1)
break;
else {
// set color here
wordToSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + textToHighlight.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(wordToSpan, TextView.BufferType.SPANNABLE);
}
}
}
Вы можете проверить этот ответ на кликабельный выделенный текст.
Я знаю, что это старый вопрос, но я создал метод для выделения повторяющегося слова в строке \ абзаце.
private Spannable highlight(int color, Spannable original, String word) {
String normalized = Normalizer.normalize(original, Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
int start = normalized.indexOf(word);
if (start < 0) {
return original;
} else {
Spannable highlighted = new SpannableString(original);
while (start >= 0) {
int spanStart = Math.min(start, original.length());
int spanEnd = Math.min(start+word.length(), original.length());
highlighted.setSpan(new ForegroundColorSpan(color), spanStart,
spanEnd, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
start = normalizedText.indexOf(word, spanEnd);
}
return highlighted;
}
}
использование:
textView.setText(highlight(primaryColor, textAll, wordToHighlight));
Основываясь на предыдущих ответах, я разработал следующую функцию, вы можете скопировать / вставить ее
private void highlightMask(TextView textView, String text, String mask) {
boolean highlightenabled = true;
boolean isHighlighted = false;
if (highlightenabled) {
if (!TextUtils.isEmpty(text) && !TextUtils.isEmpty(mask)) {
String textLC = text.toLowerCase();
mask = mask.toLowerCase();
if (textLC.contains(mask)) {
int ofe = textLC.indexOf(mask, 0);
Spannable wordToSpan = new SpannableString(text);
for (int ofs = 0; ofs < textLC.length() && ofe != -1; ofs = ofe + 1) {
ofe = textLC.indexOf(mask, ofs);
if (ofe == -1) {
break;
} else {
// set color here
wordToSpan.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + mask.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(wordToSpan, TextView.BufferType.SPANNABLE);
isHighlighted = true;
}
}
}
}
}
if (!isHighlighted) {
textView.setText(text);
}
}
Я не сделал этого, но это выглядит многообещающе:
http://developer.android.com/reference/android/text/SpannableString.html
http://developer.android.com/guide/topics/resources/string-resource.html
публичный финал void setText (текст CharSequence)
Since: API Level 1 Устанавливает строковое значение TextView. TextView не поддерживает HTML-подобное форматирование, что можно делать с текстовыми строками в файлах ресурсов XML. Чтобы стилизовать ваши строки, присоедините объекты android.text.style.* К SpannableString или посмотрите документацию "Доступные типы ресурсов" для примера установки форматированного текста в файле ресурсов XML.
http://developer.android.com/reference/android/widget/TextView.html
Попробуйте эту библиотеку Android TextHighlighter.
Реализации
TextView.setText()
получает параметр как Spannable
не только CharacterSequence
, SpannableString имеет метод setSpan()
что позволяет применять стили.
См. Список форм прямого подкласса CharacterStyle https://developer.android.com/reference/android/text/style/CharacterStyle.html
- Пример задания цвета фона и цвета переднего плана для слова "Hello" в "Hello, World"
Spannable spannable = new SpannableString("Hello, World");
// setting red foreground color
ForegroundSpan fgSpan = new ForegroundColorSpan(Color.red);
// setting blue background color
BackgroundSpan bgSpan = new BackgroundColorSPan(Color.blue);
// setSpan requires start and end index
// in our case, it's 0 and 5
// You can directly set fgSpan or bgSpan, however,
// to reuse defined CharacterStyle, use CharacterStyle.wrap()
spannable.setSpan(CharacterStyle.wrap(fgSpan), 0, 5, 0);
spannable.setSpan(CharacterStyle.wrap(bgSpan), 0, 5, 0);
// apply spannableString on textview
textView.setText(spannable);
Я знаю, что эта ветка старая, но на всякий случай, если кто-то хочет выделить строки в текстовом представлении, я создал библиотеку, которая делает именно это. Это мой первый ответ на вопрос о переполнении стека, поскольку я только что присоединился, надеюсь, он отформатирован правильно и актуально. Он использует SpannableString и найдет все вхождения указанной вами строки. Кроме того, встроенный пользовательский ClickableSpan дает вам возможность при желании настроить прослушиватели для текста, по которому щелкают.
Linker
Облегченная библиотека Android для выделения строк внутри текстового представления (без учета регистра) с необязательными обратными вызовами.
Язык: Java
MinSDK: 17
Изображение его функциональности и весь код можно найти здесь.
Чтобы привнести в ваш проект android реализацию артефакта:
На уровне проекта build.gradle
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
На уровне приложения build.gradle
dependencies {
implementation 'com.github.Gaineyj0349:Linker:1.2'
}
Как пользоваться:
1 - Построить объект Linker с помощью textview:
Linker linker = new Linker(textView);
2 - Добавить массив или список строк, которые будут выделены в тексте textview:
ArrayList<String> list = new ArrayList<>();
list.add("hello");
list.add("world");
linker.addStrings(list);
И / ИЛИ
String[] words = new String[]{"One", "Two", "Three"};
linker.addStrings(words);
3 - Добавить обратный вызов: (это необязательно):
linker.setListener(new LinkerListener() {
@Override
public void onLinkClick(String charSequenceClicked) {
// charSequenceClicked is the word that was clicked
Toast.makeText(MainActivity.this, charSequenceClicked, Toast.LENGTH_SHORT).show();
}
});
4 - Вызвать метод обновления компоновщика, чтобы зафиксировать настройку и развернуть настройку.:
linker.update();
У вас всегда есть возможность добавить Strings в объект компоновщика, просто убедитесь, что вы вызываете метод update после обновления промежутков.
linker.addStrings("yoda");
linker.update();
Если вам нужен новый планшет с тем же объектом компоновщика, просто позвоните
linker.clearLinksList()
Вы также можете настроить ссылки:
1 - настроить все цвета ссылки:
linker.setAllLinkColors(Color.BLUE);
2 - настроить ссылку подчеркивает:
linker.setAllLinkUnderline(false);
3 - Если вы хотите настроить цвет или подчеркивание для определенной строки (обратите внимание, что строка должна быть уже добавлена в компоновщик):
linker.setLinkColorForCharSequence("world", Color.MAGENTA);
linker.setUnderlineModeForCharSequence("world", true);
4 - Если вы хотите использовать разные настройки для каждого слова, вы также можете предоставить объекту компоновщика список или массив LinkProfiles:
ArrayList<LinkProfile> profiles = new ArrayList<>();
profiles.add(new LinkProfile("hello world",
Color.GREEN, false));
profiles.add(new LinkProfile("goodbye cruel world",
Color.RED, false));
profiles.add(new LinkProfile("Whoa awesome!",
Color.CYAN, true));
linker.addProfiles(profiles);
Просто не забудьте вызвать.update() после любых дополнений к объекту компоновщика.
Обратите внимание, что библиотека позаботится о таких тонкостях, как добавление двух одинаковых слов или одинаковых частей слова. Например, если "helloworld" и "hello" - это два слова, добавленные в компоновщик, "helloworld" будет отдаваться предпочтение перед "hello", когда они находятся в одном и том же диапазоне символов. Линкер будет сначала сортировать по более крупным словам и отслеживать все промежутки по мере их связывания, избегая проблемы дублирования и пересекающихся интервалов.
Лицензировано по лицензии MIT.
Вы делаете это в xml strings
если ваши строки статичны
<string name="my_text">This text is <font color='red'>red here</font></string>