Текст с разметкой в android.widget.TextView tutorial
Недавно мне понадобилось сделать довольно хитроумный чат в приложении под Android. Помимо собственно информации требовалось передавать пользователям дополнительную функциональность в контексте определенного сообщения: имя автора сообщения по нажатию на него должно вставляться в текстовое поле ответа, а если это сообщение о только что созданном игровом сеансе, пользователи должны иметь возможность присоединиться к игре по клику и так далее. Одним из главных требований была возможность создавать сообщение, содержащее несколько ссылок, что и задало направление исследований.
WebView, обладая нужной функциональностью, был отвергнут по причине тяжести решения: я даже не стал создавать 100 или сколько-нибудь там экземпляров в тестовых целях, по одному на каждое сообщение, поскольку сразу было понятно, что это расточительство нормально работать не будет.
К счастью, самый обычный TextView обладает неожиданно потрясающей функциональностью по разметке текста и может использоваться как в качестве отдельного элемента, так и служить целой страницей, будучи несравненно легковеснее, чем WebView.
Я реализовал весь, необходимый мне функционал и выяснил ещё несколько довольно интересных вещей, столкнувшись с некоторым количеством подводных камней (впрочем, не очень острых). Можно сказать, всё нижеописанное — руководство по созданию достаточно мощной справочной системы в своём приложении практически даром.
Задачи
В данном примере мы создадим приложение с двумя Activity, одна из которых содержит TextView, исполняющий роль браузера, из которого, в частности, можно вызвать вторую Activity, демонстрирующую работу с параметрами вызова. Мы выясним, каким образом можно создавать страницы текста с разметкой и изображениями и связывать их ссылками.
Содержимое страниц берётся из строк в ресурсах приложения, а изображения являются drawable-ресурсами. Небольшие изменения в коде позволят использовать другие расположения.
Создание приложения
Любым удобным нам способом создаём обычное приложение:
Немного пояснений к манифесту. Если с первой Activity всё понятно, вторая (AnotherActivity) содержит некие дополнительные описатели.
android:exported=«false» необходимо для того, чтобы компилятор не выдавал предупреждения о том, что мы забыли что-то прописать в экспортируемом компоненте. На мой взгляд, чисто декоративный момент, но чем меньше жёлтых треугольничков — тем спокойнее.
Раздел intent-filter содержит описатели того, каким образом и при каких обстоятельствах будет происходить запуск Activity.
означает, что можно запустить Activity ссылкой вида activity-run://AnotherActivityHost?params.
Значения action и category необходимы системе для того чтобы обнаружить и запустить Activity.
Подготовка ресурсов
Строки, содержащие разметку, должны иметь аттрибут formatted со значением false, а содержимое должно передаваться в блоке CDATA, чтобы у компилятора не было претензий к разметке и специальным символам. В данном примере признаком статьи будет префикс article_ в названии строки.
Также замечен странный глюк, проявляющийся в том, что если текст начинается с тега, то заканчивается он этим же тегом. Если у вас в начале статьи ссылка, советую ставить перед ней либо пробел, либо
.
Изображения могут быть формата jpg, png или gif без анимации. Анимированный gif отображается статичной картинкой. Расположение стандартное для ресурсов, для дисплеев разной плотности можно подготовить свой вариант картинки. В данном примере все изображения находятся в drawable-nodpi
Как всё работает
Рассмотрим некоторые части кода подробно.
TextView используемый нами в качестве браузера, требует особой инициализации:
tvContent.setLinksClickable(true); указывает на то, что ссылки в данном элементе реагируют на нажатие.
tvContent.setMovementMethod(new LinkMovementMethod()); назначает способ навигации по элементу. Использованный нами LinkMovementMethod интересен сам по себе и, возможно, заслуживает отдельной статьи. Я лишь скажу, что при необходимости более полного контроля можно создать его наследника, переопределенные методы которого позволят отслеживать все действия со ссылками в элементе.
В данном методе происходит получение строки по идентификатору из строковых ресурсов, её преобразование из HTML в специальный объект Spanned, затем ещё одно преобразование в Spannable и установка в TextView в качестве содержимого. Всё это кажется довольно громоздким, но тому есть причины.
В TextView, на мой взгляд, странный порядок обработки спанов — с конца списка. При естественном расположении спанов после преобразования строки из HTML, изменения внешнего вида вложенных спанов перекрываются свойствами спанов, их содержащих. Для нормального отображения приходится буквально выворачивать маркировку наизнанку с помощью метода revertSpanned:
Определение обработчика ссылок на изображения минималистично и призвано загружать только картинки из ресурсов. Поскольку мы рассматриваем вариант справочной системы, я посчитал, что этого будет достаточно. С вашего позволения, я не буду цитировать его. Если вы хотите большего, можно обратиться, например, к данной статье.
Более интересен нам будет Html.TagHadler:
Здесь у нас происходит несколько интересных вещей.
При преобразовании из HTML в Spanned методом Html.fromHtml, обрабатываются тэги br , p , div , em , b , strong , cite , dfn , i , big , small , font , blockquote , tt , a , u , sup , sub , h1. h6 и img . В случае, если тэг не опознан, вызывается Html.TagHandler (если, конечно, он передан в вызов).
Мы проверяем, не является ли переданный тэг «нашим» и если это так, создаём соответствующий Span — элемент разметки, а затем накладываем его на текст. Я создал несколько собственных Span-ов, они будут рассмотрены далее. Как правило, Span-ы наследуются от android.text.style.CharacterStyle.
К сожалению, у меня не получилось малой кровью добиться центрования отдельных строк или абзацев, а встроенной возможности для этого не существует. Также, нельзя прочесть атрибуты тэга из xmlReader, поскольку он реализован не полностью. По этой причине пришлось изобретать свой способ передачи параметров: значение является частью тега. В нашем примере таким образом передаётся значение цвета в тэге color, преобразовываемом в ParameterizedSpan. Получается что-то вроде красный . Это достаточно ограниченный и не очень удобный способ, но иногда лучше такой, чем никакого.
Этот код делает следующее: В случае, если передан открывающий Span, он добавляется к концу строки в текущем её виде. В случае, если Span закрывающий, мы находим в строке его открывающий аналог, запоминаем его положение, затем удаляем и добавляем новый, но уже с информацией о начальном положении и длине.
Мы завершили рассмотрение класса Activity, являющегося основным модулем нашего приложения. Теперь рассмотрим вспомогательные классы.
Это Span общего назначения и с его помощью можно задать большинство параметров стиля текста. Его можно использовать как базу для создания стилей текста из собственных тэгов.
Этот класс описывает элемент, который по нажатию на него обеспечивает переход к статье, чей идентификатор является его параметром. Здесь я применил производное от способа, описанного мной ранее: сам тэг является собственным параметром, а его класс определяется префиксом article_. Поднимемся выше, к описанию Html.TagHandler:
Обработчик тэгов, увидев тэг, начинающийся на article_, создаёт ArticleSpan, задавая ему в качестве параметра название тэга. Элемент, при нажатии на него, вызывает метод MainActivity.setArticle, после чего в TextView устанавливается новый текст.
Здесь реализован элемент, получающий параметр явно и отдельно от своего имени. Претензия на своего рода стандарт именования тэгов, раз уж нельзя передавать атрибуты.
Конечно, всё описанное является вариациями одного принципа, каждый выберёт то, что ему удобнее.
Вызов Activity
В HTML мы видим следующее:
При нажатии на ссылку, происходит вызов AnotherActivity с передачей параметров в Intent. Эти параметры можно получить и использовать:
Использованные материалы
Следующие материалы очень ускорили создание данной статьи, да и, чего уж там, сделали его вообще возможным:
Источник
Android: как использовать Html.TagHandler?
Я пытаюсь создать приложение android для доски объявлений. Чтобы отобразить форматированный html для содержимого поста, я выбрал метод TextView и Html.fromHtml(). Это, к сожалению, охватывает только несколько тегов html. Неизвестные теги обрабатываются классом, который реализует TagHandler и должен быть сгенерирован мной самим.
Теперь я много гуглил и не могу найти пример того, как должен работать этот класс. Давайте рассмотрим, что у меня есть тег u для подчеркивания некоторого текста (я знаю, что это устарело, но все равно). Как выглядит мой TagHandler?
Он называется следующим образом:
Первые два аргумента хороши. Я думаю, что мне нужно изменить вывод с помощью output.append(). Но как я могу прикрепить туда что-то подчеркнутое?
5 ответов
Ладно, я схожу с ума из-за этого. У меня есть метод в моей программе, который анализирует HTML. Я хочу включить встроенные изображения, и у меня сложилось впечатление, что использование Html.fromHtml(string, Html.ImageGetter, Html.TagHandler) позволит этому произойти. Поскольку Html.ImageGetter не.
Я хочу установить TextView с SpannableString , который находится в приведенном ниже методе: Html.fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler) Но ImageGetter здесь нужно переопределить метод ниже: public abstract Drawable getDrawable(String source) Поскольку мне.
Итак, я, наконец, понял это сам.
И для вашего TextView вы можете назвать это так:
если кому-то это понадобится.
Это решение находится в Android sdk
В android.text.html . Строки 596 — 626. Копирование/вставка
Чтобы использовать, переопределите TagHandler следующим образом:
Я хочу использовать hplip для печати с устройства android. Пожалуйста, скажите мне, как я могу построить hplip и использовать в android. Есть ли какая-нибудь обертка для android? См . документация пакет
Я хочу использовать LTR (слева направо) и RTL (справа налево) в своем приложении. Я прочитал этот пост http://android-developers.blogspot.co.uk/2013/03/native-rtl-support-in-android-42.html Я много ищу, чтобы узнать, как использовать эту функцию в android 2.2.
Я взял ответ джаноливера и придумал свою версию, которая пытается поддержать больше вариантов
Похоже, что это действительно дает маркеры, цвет переднего плана и цвет фона. Это может сработать для лица шрифта, но вам может потребоваться указать шрифты, так как кажется, что Android не поддерживает шрифты, отличные от Droid/Roboto.
Это больше похоже на proof-of-concept, вы, вероятно, захотите преобразовать regex в обработку String , так как regex никоим образом не поддерживает объединение предварительной обработки, что означает, что для этого требуется много проходов по String . Это также, похоже, не приводит к изменению размера шрифта, я попытался определить его как «16sp», «medium» или «4», не видя изменений. Если кто-то получил размеры для работы, поделитесь мыслями?
В настоящее время я хотел бы иметь возможность добавить поддержку нумерованного/упорядоченного списка к этому, т. е.
NOTE: Людям, начинающим с чего-либо из этого, кажется, что «tag», который дается handleTag(. ) , является просто именем тега (например, «span») и не содержит никаких атрибутов, назначенных в теге (например, если у вас есть»), вы можете увидеть мою лазейку вокруг этого для цвета фона.
Мы уже некоторое время разрабатываем эту библиотеку https://github.com/square1-io/rich-text-android и используем ее в ряде новостных приложений с интенсивным контентом.
Библиотека может анализировать наиболее распространенные теги html, включая видео и img, с удаленной загрузкой изображений. Пользовательское представление, RichTextView затем можно использовать в качестве замены TextView для отображения проанализированного содержимого.
Мы опубликовали его публично совсем недавно, так что документ все еще неполон, однако приведенный пример должен быть легко следовать, чтобы увидеть, соответствует ли он вашим потребностям.
Хотя я вижу это в Html.java API , что стиль и выравнивание текста должны использоваться с тегами
и многими другими вариантами. Не имея возможности выполнить выравнивание текста по центру и другие стили, такие как размер шрифта, несколько граней шрифта из моих файлов ttf, цвет фона, я создал свой собственный htmlTextView на основе TextView, но с моим собственным классом tagHandler. Учитывая одно или два незначительных раздражения, большинство тегов в порядке, но мои пользовательские теги выравнивания , левый , центральный, правый работают только в особых условиях (которые я не понимаю), в противном случае. они не работают и не выводят приложение из строя! Это мой маркер выравнивания. Он имеет ту же структуру, что и все другие обработчики пользовательских тегов, но действительно ведет себя странно! Основная форма моих обработчиков тегов одинакова и не задумана мной ! Я нашел шаблон taghandler после многих часов поиска в Интернете. Я благодарен тому, кто его опубликовал, но моя память и организаторские способности таковы, что я не могу вспомнить, кто или где, поэтому, если вы признаете этот код своим, пожалуйста, дайте мне знать. Единственная ссылка (которая находится здесь) У меня есть в моем коде: stackoverflow : Android: Как использовать Html.TagHandler?
Я думаю, что проблема в том, что конечный тег не подключается к правильному стартовому тегу.
Это общий класс, и что-то не так. Самый большой компонент-это мое понимание! Возможно, кто-нибудь поможет мне лучше понять.
htmlTextView создается из действия с:
и htmljumblies определяется в strings.xml, как показано ниже. Эта конкретная версия приведет к сбою приложения , но если первые теги , будут удалены из строк 7 и 9, беспорядок появится централизованным? Сбивает с толку и расстраивает! Сохраните их и удалите теги , , охватывающие беспорядок , и ничего не произойдет. Строка в заголовке не выровнена по центру!
Похожие вопросы:
Я разрабатываю приложение Android, и мне нужно отобразить HTLM (также теги) в textView. Для этого я нашел этот TagHandler , но он поднимает java.lang.RuntimeException: PARAGRAPH span должен.
Я пытаюсь сделать приложение, использование списка в android леденец через UsageStatsManager, на что я пошел через android разработчик документа.
Внутри TagHandler , который я передал в Html.fromHtml() , я хотел бы добавить некоторый форматированный текст к данному объекту Editable output , который затем передается в TextView . Добавление.
Ладно, я схожу с ума из-за этого. У меня есть метод в моей программе, который анализирует HTML. Я хочу включить встроенные изображения, и у меня сложилось впечатление, что использование.
Я хочу установить TextView с SpannableString , который находится в приведенном ниже методе: Html.fromHtml(String source, Html.ImageGetter imageGetter, Html.TagHandler tagHandler) Но ImageGetter.
Я хочу использовать hplip для печати с устройства android. Пожалуйста, скажите мне, как я могу построить hplip и использовать в android. Есть ли какая-нибудь обертка для android? См . документация.
Я хочу использовать LTR (слева направо) и RTL (справа налево) в своем приложении. Я прочитал этот пост http://android-developers.blogspot.co.uk/2013/03/native-rtl-support-in-android-42.html Я много.
Я пытаюсь использовать TextView для отображения строкового текста с пользовательскими тегами: строка: text1 paddingtext2 .
Я использую TextView для отображения строки HTML, такой как: Тест HTML link1 link2 Как вы видите, есть два разных типа.
Я хотел показать пули в тексте android. Я успешно добавил их. Я поискал в интернете и обнаружил, что вы можете добавлять пули. но если текст идет более чем на одну строку, он не следует правильному.
Источник