Как показать HTML-текст в Android при обнаружении кликов по определенным фразам и прокручиванию позиции?

Я получаю стену простого текста HTML с сервера и должен отображать ее в своем приложении, но это не все.

Мне также необходимо обнаружить клики по определенным фразам в тексте. Фразы определяются двумя цифрами: количество слов, в котором начинается фраза, и количество слов, где оно заканчивается (например, от слова 10 до слова 15).

Моя интуиция говорит, что я мог бы, вероятно, использовать HTML со ссылками или некоторым JavaScript в соответствии со спецификацией фраз, а затем прослушивать клики по этим ссылкам. Однако я не уверен, как добиться такой функциональности в Android.

Кроме того, я также должен иметь возможность программно наблюдать и манипулировать положением прокрутки в показанном HTML-тексте. Например, мне нужно понять, когда определенная фраза прокручивается с экрана.

Наверное, у меня три тесно связанных вопроса:

  1. Какой вид следует использовать для достижения вышеуказанной функциональности (TextView, WebView, другие)?
  2. Как я могу прослушивать клики по определенным частям HTML?
  3. Как я могу наблюдать и манипулировать прокруткой?

Спасибо

Ответ 1

  1. WebView - это быстрый способ сделать это.
  2. Вы можете сопоставить функцию java/kotlin с функцией javascript на веб-странице для отслеживания кликов.
  3. Опять используя простой jquery, вы можете это достичь.

См. Веб-представление slymax.

Ответ 2

Я думаю, вы можете сделать это, используя этот метод: 1.) Вам нужно получить все ссылки из html-текста, который у вас есть. Поэтому для этого используйте этот метод:

 public static ArrayList<String> extractUrls(String text) {
    ArrayList<String> containedUrls = new ArrayList<>();
    String urlRegex = "((https?|ftp|gopher|telnet|file):((//)|(\\\\))+[\\w\\d:#@%/;$()~_?\\+-=\\\\\\.&]*)";
    Pattern pattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE);
    Matcher urlMatcher = pattern.matcher(text);

    while (urlMatcher.find()) {
        containedUrls.add(text.substring(urlMatcher.start(0),
                urlMatcher.end(0)));
    }
    return containedUrls;
}

Он вернет ArrayList URL-адресов. Теперь вам нужно преобразовать данные HTML в текст, читаемый человеком: для этого используйте:

public void HtmlToString(final String data) {
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            final String s = String.valueOf(Html.fromHtml(data));
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    processData(s);
                }
            });
        }
    });
    thread.start();
}
void processData(String s){
// Do whatever you want to do
}

Мы делаем эту работу в другом потоке. Теперь у вас есть текст, а также ссылки, делайте все, что хотите. Теперь, если вы хотите больше работать над этим, вы можете сделать это, заменив все ссылки, которые вы получаете в списке массивов, специальным кодом, который вы можете использовать в качестве заполнителя, например:

for(int i = 0; i < urlArray.size();i++){
    yourData.replace(urlArray.get(i),"<<<YOURSPECIALCODE>>>");       
}

Теперь вы можете разбить свои данные, используя специальный код, чтобы получить перерывы в месте URL. Для этого:

ArrayList<String> dataArray = new ArrayList<>(yourData.split("<<<YOURSPECIALCODE>>>"));

Теперь вы можете использовать эти два массива для отображения в соответствии с вашими требованиями

Поскольку теперь вы можете легко назначать разные текстовые представления для разных данных и устанавливать ListOnClick Listeners.

Надеюсь, это поможет!

Спасибо

Ответ 3

Если вы планируете использовать TextView (я бы предпочел, чтобы контент не отображался как полный HTML, используйте WebView иначе) и используйте Clickable span в текстовом контенте, чтобы сделать определенные области доступными для кликов. Вы можете обрабатывать щелчок по отдельным областям диапазона и выполнять необходимые действия в обработчике кликов. Вам нужно написать несколько классов CustomClickableSpan, основанных на количестве различных областей, которые вы хотите обработать.

Ответ 4

Думаю, для вас идеальным вариантом будет WebView.

Легче обрабатывать HTML в webview, а не TextView.

TextView требует, чтобы вы использовали промежутки для обработки содержимого HTML, что несколько сложно по сравнению с обработкой HTML в WebView.

А также для контроля поведения прокрутки мы можем использовать событие прокрутки элемента в веб-просмотре, что упрощает обработку поведения прокрутки отдельных элементов.

Поэтому, чтобы сделать определенные фрагменты текстового текста, используйте приведенный ниже фрагмент кода (Kotlin),

val htmlString = "<div>Handling the click near the specified indices</div>"
        val document = Jsoup.parse(htmlString)
        document.outputSettings().prettyPrint(false)
        var plaintext = document.body().text()
        plaintext = plaintext.replaceRange(13,18, "<a href='https://www.google.com'>${plaintext.substring(13, 18)}</a>")
        document.body().html(plaintext)

Используйте библиотеку Jsoup для синтаксического анализа содержимого HTML. Вышеприведенный фрагмент кода сделает индексированную подстроку кликабельной и укажет на www.google.com. Вы также можете добавить к нему другие события.

Затем, чтобы проверить, является ли элемент видимым на экране, вы можете иметь функцию javascript, например,

function isElementVisible(element)
{
  var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();
    
  var elemTop = $(element).offset().top;
  var elemBottom = elemTop + $(element).height();
    
  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Ответ 5

Вы можете сделать это с помощью SpannableString - найти все теги ссылок в тексте html и установить spannable везде, где вам нужно (например, для каждого из тегов: SPANNABLE STRING).

Следуйте этой теме, создайте свои интерактивные строки и покажите их в TextView. Это не так сложно :)

Android: ClickableSpan в интерактивном TextView