Intereting Posts
Курсор Edittext невидим в android 4.0 Скрыть клавиатуру, когда пользователь нажимает где-нибудь еще на экране в android Добавьте RawContact, чтобы он заполнил существующий контакт Проблемы с планировкой Android Недостатки использования библиотеки совместимости Android на Honeycomb Неверное завершение строки: найден возврат каретки (\ r) без соответствующей новой строки (\ n) Как установить высоту элемента WearableListView Как избавиться от зависания камеры (SurfaceView)? LocationManager: java.lang.NoSuchMethodError Android, изменение подчеркивания Цвет из EditText динамически Макет размытого / низкого качества, когда jQuery mobile на Android-телефоне с использованием телефонной затычки Невозможно увидеть инструмент sdk manager в Eclipse Juno 4.2.1 Часть элементов фрагмента скрывается в строке действий Как безопасно завершить работу петлителя HandlerThread Как бороться с отсутствующей исходной папкой src / test / java в проекте Android / Maven?

TextView fromHtml ссылки сломаны на Lollipop

В нашем приложении было несколько экземпляров TextViews с его содержимым, установленным myTv.setText(Html.fromHtml()); Которые работают на Android 4.4.0 и ниже.

Начиная с 4.4.2 и Lollypop эти ссылки перестали работать. Текст по-прежнему выглядит подчеркнутым и с гиперссылкой, но нажатие на них не дает никаких результатов.

Следует сказать, что эти поля отмечены как скопированные, которые, как известно, взаимодействуют с этими spannables.

Кто-нибудь смог решить эту проблему?

Проблема в том, что при включении копирования и вставки в TextView, Android будет использовать ArrowKeyMovementMethod, который поддерживает выбор текста, но не щелчок ссылок. Когда вы используете LinkMovementMethod, вы можете щелкнуть ссылки, но не выбирать текст (независимо от того, находитесь ли вы на Lollipop, KitKat или более низкой версии Android).

Чтобы решить эту проблему, я расширил класс ArrayKeyMovementMethod и переопределил onTouchEvent с помощью LinkMovementMethod onTouchEvent. Чтобы разрешить выбор текста, мне пришлось удалить только три строки кода. Поскольку я использую этот класс в текстовом редакторе с большим количеством текстового форматирования, я также добавил логику, чтобы найти щелкнув символ независимо от размера текста, его отступов или выравнивания текста. Если вы хотите, чтобы простое решение прекрасно работало с открытым текстом, используйте его в пользовательском классе ArrowKeyMovementMethod:

 @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); x -= widget.getTotalPaddingLeft(); y -= widget.getTotalPaddingTop(); x += widget.getScrollX(); y += widget.getScrollY(); Layout layout = widget.getLayout(); int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } return true; } /* These are the lines of code you want to remove else { Selection.removeSelection(buffer); }*/ } return super.onTouchEvent(widget, buffer, event); } 

Не забудьте позвонить: myTv.setMovementMethod (новый ClickAndSelectMovementMethod ());

Если вы хотите, чтобы версия, поддерживающая все виды форматирования текста, использовала это:

 import android.graphics.Rect; import android.text.Layout; import android.text.Selection; import android.text.Spannable; import android.text.Spanned; import android.text.TextPaint; import android.text.method.ArrowKeyMovementMethod; import android.text.method.MovementMethod; import android.text.style.AbsoluteSizeSpan; import android.text.style.ClickableSpan; import android.text.style.LeadingMarginSpan; import android.view.MotionEvent; import android.widget.TextView; /** * ArrowKeyMovementMethod does support selection of text but not the clicking of * links. LinkMovementMethod does support clicking of links but not the * selection of text. This class adds the link clicking to the * ArrowKeyMovementMethod. We basically take the LinkMovementMethod onTouchEvent * code and remove the line Selection.removeSelection(buffer); which de-selects * all text when no link was found. */ public class ClickAndSelectMovementMethod extends ArrowKeyMovementMethod { private static Rect sLineBounds = new Rect(); @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { int action = event.getAction(); if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) { int index = getCharIndexAt(widget, event); if (index != -1) { ClickableSpan[] link = buffer.getSpans(index, index, ClickableSpan.class); if (link.length != 0) { if (action == MotionEvent.ACTION_UP) { link[0].onClick(widget); } else if (action == MotionEvent.ACTION_DOWN) { Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0])); } return true; } } /* * else { Selection.removeSelection(buffer); } */ } return super.onTouchEvent(widget, buffer, event); } private int getCharIndexAt(TextView textView, MotionEvent event) { // get coordinates int x = (int) event.getX(); int y = (int) event.getY(); x -= textView.getTotalPaddingLeft(); y -= textView.getTotalPaddingTop(); x += textView.getScrollX(); y += textView.getScrollY(); /* * Fail-fast check of the line bound. If we're not within the line bound * no character was touched */ Layout layout = textView.getLayout(); int line = layout.getLineForVertical(y); synchronized (sLineBounds) { layout.getLineBounds(line, sLineBounds); if (!sLineBounds.contains(x, y)) { return -1; } } // retrieve line text Spanned text = (Spanned) textView.getText(); int lineStart = layout.getLineStart(line); int lineEnd = layout.getLineEnd(line); int lineLength = lineEnd - lineStart; if (lineLength == 0) { return -1; } Spanned lineText = (Spanned) text.subSequence(lineStart, lineEnd); // compute leading margin and subtract it from the x coordinate int margin = 0; LeadingMarginSpan[] marginSpans = lineText.getSpans(0, lineLength, LeadingMarginSpan.class); if (marginSpans != null) { for (LeadingMarginSpan span : marginSpans) { margin += span.getLeadingMargin(true); } } x -= margin; // retrieve text widths float[] widths = new float[lineLength]; TextPaint paint = textView.getPaint(); paint.getTextWidths(lineText, 0, lineLength, widths); // scale text widths by relative font size (absolute size / default size) final float defaultSize = textView.getTextSize(); float scaleFactor = 1f; AbsoluteSizeSpan[] absSpans = lineText.getSpans(0, lineLength, AbsoluteSizeSpan.class); if (absSpans != null) { for (AbsoluteSizeSpan span : absSpans) { int spanStart = lineText.getSpanStart(span); int spanEnd = lineText.getSpanEnd(span); scaleFactor = span.getSize() / defaultSize; int start = Math.max(lineStart, spanStart); int end = Math.min(lineEnd, spanEnd); for (int i = start; i < end; i++) { widths[i] *= scaleFactor; } } } // find index of touched character float startChar = 0; float endChar = 0; for (int i = 0; i < lineLength; i++) { startChar = endChar; endChar += widths[i]; if (endChar >= x) { // which "end" is closer to x, the start or the end of the character? int index = lineStart + (x - startChar < endChar - x ? i : i + 1); return index; } } return -1; } } 

По умолчанию, Material Buttons и Textviews стилизованы для отображения текста во всех шапках. Однако в AllCapsTransformationMethod есть ошибка, которая приводит к отбрасыванию другого форматирования текста, например. Spannable . Поэтому, когда вы пытаетесь изменить размер шрифта для Button на Lollipop, как показано ниже:

 SpannableString span = new SpannableString(text); span.setSpan(new AbsoluteSizeSpan(8, true), 5, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); testButton.setText(span); 

Он также не будет работать (только для Lollipop).

Решение :

Обходной путь для вашего случая и описанный случай textAllCaps устанавливается textAllCaps на false :

 <TextView ... android:textAllCaps="false" /> 

Решение

 final Spanned spanned = Html.fromHtml("<a href='http://google.com'>My link</a>"); textView.setText(spanned); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ClickableSpan[] links = spanned.getSpans(0, spanned.length(), ClickableSpan.class); if (links.length > 0) { links[0].onClick(v); } } }); 

При этом ваш текст можно выбрать с помощью длинного щелчка, и ссылку можно открыть одним щелчком мыши. Вы можете сделать более реалистичную реализацию, чтобы разрешить выбор текста с двойным щелчком.

проблема

Проблема, похоже, заключается в следующем коде. Это часть стандартного TextView onTouchEvent :

 if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) { // The LinkMovementMethod which should handle taps on links has not been installed // on non editable text that support text selection. // We reproduce its behavior here to open links for these. ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(), getSelectionEnd(), ClickableSpan.class); if (links.length > 0) { links[0].onClick(this); handled = true; } } 

Мы видим, что одним из условий для запуска if блока является mAutoLinkMask != 0 .

Если вы измените android:autoLink будет чем-то отличным от значения по умолчанию 0 или none если блок if работает, но не имеет ссылок.

Я предполагаю, что это было упущено разработчиками и должно быть представлено как ошибка на мой взгляд.

Примечание

Если вам нужны простые ссылки, такие как http://google.com, не изменяя их внешний вид, вы можете установить android:autoLink="web" в своем TextView и сделать. Ссылки будут найдены автоматически и сделаны интерактивными. Однако это не будет работать с <a href="..."></a> типом ссылок.

Попытайтесь, это сработало для меня. Я загружаю html-файл из папки моих ресурсов для моего требования, но вам просто нужно установить все связующие свойства textview, вот и все .. он будет работать …

 <TextView android:id="@+id/txt_terms_and_conditions" android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/hello_world" android:linksClickable="true" android:autoLink="phone|email|web" /> 

И в коде попробуйте установить html как это

 mTxtTearmsAndConditions.setText(Html.fromHtml(total.toString()));