mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-18 16:03:12 +00:00
address some more warnings
This commit is contained in:
parent
af1eb551cf
commit
e543788920
10 changed files with 77 additions and 52 deletions
|
@ -2,6 +2,7 @@ package org.dslul.openboard.inputmethod.accessibility
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
@ -12,7 +13,6 @@ import android.view.ViewGroup
|
||||||
import android.view.accessibility.AccessibilityEvent
|
import android.view.accessibility.AccessibilityEvent
|
||||||
import android.view.accessibility.AccessibilityManager
|
import android.view.accessibility.AccessibilityManager
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import androidx.core.view.accessibility.AccessibilityEventCompat
|
|
||||||
import org.dslul.openboard.inputmethod.latin.R
|
import org.dslul.openboard.inputmethod.latin.R
|
||||||
import org.dslul.openboard.inputmethod.latin.SuggestedWords
|
import org.dslul.openboard.inputmethod.latin.SuggestedWords
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils
|
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils
|
||||||
|
@ -127,17 +127,17 @@ class AccessibilityUtils private constructor() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// The following is a hack to avoid using the heavy-weight TextToSpeech
|
// The following is a hack to avoid using the heavy-weight TextToSpeech
|
||||||
// class. Instead, we're just forcing a fake AccessibilityEvent into
|
// class. Instead, we're just forcing a fake AccessibilityEvent into
|
||||||
// the screen reader to make it speak.
|
// the screen reader to make it speak.
|
||||||
val event = AccessibilityEvent.obtain()
|
val event = obtainEvent()
|
||||||
event.packageName = PACKAGE
|
event.packageName = PACKAGE
|
||||||
event.className = CLASS
|
event.className = CLASS
|
||||||
event.eventTime = SystemClock.uptimeMillis()
|
event.eventTime = SystemClock.uptimeMillis()
|
||||||
event.isEnabled = true
|
event.isEnabled = true
|
||||||
event.text.add(text)
|
event.text.add(text)
|
||||||
// Platforms starting at SDK version 16 (Build.VERSION_CODES.JELLY_BEAN) should use
|
// Platforms starting at SDK version 16 (Build.VERSION_CODES.JELLY_BEAN) should use
|
||||||
// announce events.
|
// announce events.
|
||||||
event.eventType = AccessibilityEventCompat.TYPE_ANNOUNCEMENT
|
event.eventType = AccessibilityEvent.TYPE_ANNOUNCEMENT
|
||||||
val viewParent = view.parent
|
val viewParent = view.parent
|
||||||
if (viewParent == null || viewParent !is ViewGroup) {
|
if (viewParent == null || viewParent !is ViewGroup) {
|
||||||
Log.e(TAG, "Failed to obtain ViewParent in announceForAccessibility")
|
Log.e(TAG, "Failed to obtain ViewParent in announceForAccessibility")
|
||||||
|
@ -205,5 +205,21 @@ class AccessibilityUtils private constructor() {
|
||||||
val action = event.action
|
val action = event.action
|
||||||
return action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_HOVER_MOVE
|
return action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_EXIT || action == MotionEvent.ACTION_HOVER_MOVE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun obtainEvent(eventType: Int): AccessibilityEvent =
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
AccessibilityEvent(eventType)
|
||||||
|
} else {
|
||||||
|
@Suppress("deprecation")
|
||||||
|
AccessibilityEvent.obtain(eventType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun obtainEvent(): AccessibilityEvent =
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
AccessibilityEvent()
|
||||||
|
} else {
|
||||||
|
@Suppress("deprecation")
|
||||||
|
AccessibilityEvent.obtain()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -73,8 +73,7 @@ open class KeyboardAccessibilityDelegate<KV : KeyboardView?>(protected val mKeyb
|
||||||
* @param text The text to send with the event.
|
* @param text The text to send with the event.
|
||||||
*/
|
*/
|
||||||
protected fun sendWindowStateChanged(text: String?) {
|
protected fun sendWindowStateChanged(text: String?) {
|
||||||
val stateChange = AccessibilityEvent.obtain(
|
val stateChange = AccessibilityUtils.obtainEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
|
||||||
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)
|
|
||||||
mKeyboardView!!.onInitializeAccessibilityEvent(stateChange)
|
mKeyboardView!!.onInitializeAccessibilityEvent(stateChange)
|
||||||
stateChange.text.add(text)
|
stateChange.text.add(text)
|
||||||
stateChange.contentDescription = null
|
stateChange.contentDescription = null
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package org.dslul.openboard.inputmethod.accessibility
|
package org.dslul.openboard.inputmethod.accessibility
|
||||||
|
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.accessibility.AccessibilityEvent
|
import android.view.accessibility.AccessibilityEvent
|
||||||
|
import android.view.accessibility.AccessibilityRecord
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.accessibility.AccessibilityEventCompat
|
import androidx.core.view.accessibility.AccessibilityEventCompat
|
||||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
|
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
|
||||||
|
@ -91,12 +93,12 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
|
||||||
fun createAccessibilityEvent(key: Key, eventType: Int): AccessibilityEvent {
|
fun createAccessibilityEvent(key: Key, eventType: Int): AccessibilityEvent {
|
||||||
val virtualViewId = getVirtualViewIdOf(key)
|
val virtualViewId = getVirtualViewIdOf(key)
|
||||||
val keyDescription = getKeyDescription(key)
|
val keyDescription = getKeyDescription(key)
|
||||||
val event = AccessibilityEvent.obtain(eventType)
|
val event = AccessibilityUtils.obtainEvent(eventType)
|
||||||
event.packageName = mKeyboardView!!.context.packageName
|
event.packageName = mKeyboardView!!.context.packageName
|
||||||
event.className = key.javaClass.name
|
event.className = key.javaClass.name
|
||||||
event.contentDescription = keyDescription
|
event.contentDescription = keyDescription
|
||||||
event.isEnabled = true
|
event.isEnabled = true
|
||||||
val record = AccessibilityEventCompat.asRecord(event)
|
val record: AccessibilityRecord = event
|
||||||
record.setSource(mKeyboardView, virtualViewId)
|
record.setSource(mKeyboardView, virtualViewId)
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
@ -111,16 +113,16 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
|
||||||
// announcements.
|
// announcements.
|
||||||
mHoveringNodeId = id
|
mHoveringNodeId = id
|
||||||
// Invalidate the node info of the key.
|
// Invalidate the node info of the key.
|
||||||
sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED)
|
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
|
||||||
sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER)
|
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onHoverExitFrom(key: Key) {
|
fun onHoverExitFrom(key: Key) {
|
||||||
mHoveringNodeId = UNDEFINED
|
mHoveringNodeId = UNDEFINED
|
||||||
// Invalidate the node info of the key to be able to revert the change we have done
|
// Invalidate the node info of the key to be able to revert the change we have done
|
||||||
// in {@link #onHoverEnterTo(Key)}.
|
// in {@link #onHoverEnterTo(Key)}.
|
||||||
sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED)
|
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)
|
||||||
sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT)
|
sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,8 +294,8 @@ class KeyboardAccessibilityNodeProvider<KV : KeyboardView?>(keyboardView: KV,
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.Companion.instance
|
mKeyCodeDescriptionMapper = KeyCodeDescriptionMapper.instance
|
||||||
mAccessibilityUtils = AccessibilityUtils.Companion.instance
|
mAccessibilityUtils = AccessibilityUtils.instance
|
||||||
mKeyboardView = keyboardView
|
mKeyboardView = keyboardView
|
||||||
mDelegate = delegate
|
mDelegate = delegate
|
||||||
// Since this class is constructed lazily, we might not get a subsequent
|
// Since this class is constructed lazily, we might not get a subsequent
|
||||||
|
|
|
@ -24,8 +24,8 @@ object CompatUtils {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return targetClass.getMethod(name!!, *parameterTypes)
|
return targetClass.getMethod(name!!, *parameterTypes)
|
||||||
} catch (e: SecurityException) { // ignore
|
} catch (_: SecurityException) { // ignore
|
||||||
} catch (e: NoSuchMethodException) {
|
} catch (_: NoSuchMethodException) {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ object CompatUtils {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return targetClass.getField(name!!)
|
return targetClass.getField(name!!)
|
||||||
} catch (e: SecurityException) { // ignore
|
} catch (_: SecurityException) { // ignore
|
||||||
} catch (e: NoSuchFieldException) {
|
} catch (_: NoSuchFieldException) {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,8 @@ object CompatUtils {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return targetClass.getConstructor(*types)
|
return targetClass.getConstructor(*types)
|
||||||
} catch (e: SecurityException) { // ignore
|
} catch (_: SecurityException) { // ignore
|
||||||
} catch (e: NoSuchMethodException) {
|
} catch (_: NoSuchMethodException) {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -153,9 +153,10 @@ object CompatUtils {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unchecked_cast")
|
||||||
class ToObjectMethodWrapper<T>(private val mMethod: Method?, private val mDefaultValue: T) {
|
class ToObjectMethodWrapper<T>(private val mMethod: Method?, private val mDefaultValue: T) {
|
||||||
operator fun invoke(receiver: Any?, vararg args: Any?): T {
|
operator fun invoke(receiver: Any?, vararg args: Any?): T {
|
||||||
return CompatUtils.invoke(receiver, mDefaultValue!!, mMethod, *args) as T
|
return CompatUtils.invoke(receiver, mDefaultValue, mMethod, *args) as T
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,28 +2,24 @@ package org.dslul.openboard.inputmethod.compat
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Build.VERSION_CODES
|
import android.os.Build.VERSION_CODES
|
||||||
import android.text.TextUtils
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.inputmethod.InputMethodSubtype
|
import android.view.inputmethod.InputMethodSubtype
|
||||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting
|
|
||||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype
|
|
||||||
import org.dslul.openboard.inputmethod.latin.common.Constants
|
|
||||||
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
|
import org.dslul.openboard.inputmethod.latin.common.LocaleUtils
|
||||||
|
import org.dslul.openboard.inputmethod.latin.settings.locale
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object InputMethodSubtypeCompatUtils {
|
object InputMethodSubtypeCompatUtils {
|
||||||
// Note that InputMethodSubtype.getLanguageTag() is expected to be available in Android N+.
|
// Note that InputMethodSubtype.getLanguageTag() is expected to be available in Android N+.
|
||||||
private val GET_LANGUAGE_TAG = CompatUtils.getMethod(InputMethodSubtype::class.java, "getLanguageTag")
|
private val GET_LANGUAGE_TAG = CompatUtils.getMethod(InputMethodSubtype::class.java, "getLanguageTag")
|
||||||
|
|
||||||
@kotlin.jvm.JvmStatic
|
@JvmStatic
|
||||||
fun getLocaleObject(subtype: InputMethodSubtype): Locale { // Locale.forLanguageTag() is available only in Android L and later.
|
fun getLocaleObject(subtype: InputMethodSubtype): Locale { // Locale.forLanguageTag() is available only in Android L and later.
|
||||||
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
val languageTag = CompatUtils.invoke(subtype, null, GET_LANGUAGE_TAG) as String?
|
val languageTag = CompatUtils.invoke(subtype, null, GET_LANGUAGE_TAG) as String?
|
||||||
if (!TextUtils.isEmpty(languageTag)) {
|
if (!languageTag.isNullOrEmpty()) {
|
||||||
return Locale.forLanguageTag(languageTag)
|
return Locale.forLanguageTag(languageTag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LocaleUtils.constructLocaleFromString(subtype.locale)
|
return LocaleUtils.constructLocaleFromString(subtype.locale())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -87,6 +87,7 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
||||||
layoutManager = StaggeredGridLayoutManager(colCount, StaggeredGridLayoutManager.VERTICAL)
|
layoutManager = StaggeredGridLayoutManager(colCount, StaggeredGridLayoutManager.VERTICAL)
|
||||||
val dividerHeight = resources.getDimensionPixelSize(R.dimen.config_clipboard_divider_height)
|
val dividerHeight = resources.getDimensionPixelSize(R.dimen.config_clipboard_divider_height)
|
||||||
addItemDecoration(ClipboardHistoryRecyclerView.BottomDividerItemDecoration(dividerHeight, dividerColor))
|
addItemDecoration(ClipboardHistoryRecyclerView.BottomDividerItemDecoration(dividerHeight, dividerColor))
|
||||||
|
@Suppress("deprecation") // no cache should be fine according to warning in https://developer.android.com/reference/android/view/ViewGroup#setPersistentDrawingCache(int)
|
||||||
persistentDrawingCache = PERSISTENT_NO_CACHE
|
persistentDrawingCache = PERSISTENT_NO_CACHE
|
||||||
clipboardLayoutParams.setListProperties(this)
|
clipboardLayoutParams.setListProperties(this)
|
||||||
placeholderView = this@ClipboardHistoryView.placeholderView
|
placeholderView = this@ClipboardHistoryView.placeholderView
|
||||||
|
@ -222,8 +223,8 @@ class ClipboardHistoryView @JvmOverloads constructor(
|
||||||
clipboardRecyclerView.smoothScrollToPosition(at)
|
clipboardRecyclerView.smoothScrollToPosition(at)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClipboardHistoryEntriesRemoved(position: Int, count: Int) {
|
override fun onClipboardHistoryEntriesRemoved(pos: Int, count: Int) {
|
||||||
clipboardAdapter.notifyItemRangeRemoved(position, count)
|
clipboardAdapter.notifyItemRangeRemoved(pos, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClipboardHistoryEntryMoved(from: Int, to: Int) {
|
override fun onClipboardHistoryEntryMoved(from: Int, to: Int) {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.dslul.openboard.inputmethod.latin.settings
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.text.Html
|
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -179,7 +178,7 @@ class LanguageSettingsDialog(
|
||||||
private fun fillDictionariesView(dictionariesView: LinearLayout) {
|
private fun fillDictionariesView(dictionariesView: LinearLayout) {
|
||||||
dictionariesView.findViewById<ImageView>(R.id.add_dictionary).setOnClickListener {
|
dictionariesView.findViewById<ImageView>(R.id.add_dictionary).setOnClickListener {
|
||||||
val link = "<a href='$DICTIONARY_URL'>" + context.getString(R.string.dictionary_link_text) + "</a>"
|
val link = "<a href='$DICTIONARY_URL'>" + context.getString(R.string.dictionary_link_text) + "</a>"
|
||||||
val message = Html.fromHtml(context.getString(R.string.add_dictionary, link))
|
val message = SpannableStringUtils.fromHtml(context.getString(R.string.add_dictionary, link))
|
||||||
val dialog = Builder(context)
|
val dialog = Builder(context)
|
||||||
.setTitle(R.string.add_new_dictionary_title)
|
.setTitle(R.string.add_new_dictionary_title)
|
||||||
.setMessage(message)
|
.setMessage(message)
|
||||||
|
|
|
@ -259,4 +259,8 @@ private val systemSubtypes = mutableListOf<InputMethodSubtype>()
|
||||||
private const val SUBTYPE_SEPARATOR = ";"
|
private const val SUBTYPE_SEPARATOR = ";"
|
||||||
private const val LOCALE_LAYOUT_SEPARATOR = ":"
|
private const val LOCALE_LAYOUT_SEPARATOR = ":"
|
||||||
|
|
||||||
|
@Suppress("deprecation") // it's deprecated, but no replacement for API < 24
|
||||||
|
// todo: add language tags in method.xml, and adjust this method to use locale only if necessary
|
||||||
|
// but then language tag should be converted to locale, or other way!
|
||||||
|
// see also InputMethodSubtypeCompatUtils
|
||||||
fun InputMethodSubtype.locale() = locale
|
fun InputMethodSubtype.locale() = locale
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.dslul.openboard.inputmethod.latin.utils
|
package org.dslul.openboard.inputmethod.latin.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.Html
|
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
@ -49,7 +48,7 @@ fun showMissingDictionaryDialog(context: Context, locale: Locale) {
|
||||||
val dictionaryLink = "<a href='$DICTIONARY_URL/src/branch/main/dictionaries/main_$locale.dict'>" + context.getString(
|
val dictionaryLink = "<a href='$DICTIONARY_URL/src/branch/main/dictionaries/main_$locale.dict'>" + context.getString(
|
||||||
R.string.dictionary_link_text) + "</a>"
|
R.string.dictionary_link_text) + "</a>"
|
||||||
|
|
||||||
val message = Html.fromHtml(context.getString(
|
val message = SpannableStringUtils.fromHtml(context.getString(
|
||||||
R.string.no_dictionary_message,
|
R.string.no_dictionary_message,
|
||||||
repositoryLink,
|
repositoryLink,
|
||||||
locale.toString(),
|
locale.toString(),
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.latin.utils;
|
package org.dslul.openboard.inputmethod.latin.utils;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.text.Html;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -50,8 +52,8 @@ public final class SpannableStringUtils {
|
||||||
Spannable dest, int destoff) {
|
Spannable dest, int destoff) {
|
||||||
Object[] spans = source.getSpans(start, end, SuggestionSpan.class);
|
Object[] spans = source.getSpans(start, end, SuggestionSpan.class);
|
||||||
|
|
||||||
for (int i = 0; i < spans.length; i++) {
|
for (Object span : spans) {
|
||||||
int fl = source.getSpanFlags(spans[i]);
|
int fl = source.getSpanFlags(span);
|
||||||
// We don't care about the PARAGRAPH flag in LatinIME code. However, if this flag
|
// We don't care about the PARAGRAPH flag in LatinIME code. However, if this flag
|
||||||
// is set, Spannable#setSpan will throw an exception unless the span is on the edge
|
// is set, Spannable#setSpan will throw an exception unless the span is on the edge
|
||||||
// of a word. But the spans have been split into two by the getText{Before,After}Cursor
|
// of a word. But the spans have been split into two by the getText{Before,After}Cursor
|
||||||
|
@ -59,16 +61,15 @@ public final class SpannableStringUtils {
|
||||||
// Since we don't use them, we can just remove them and avoid crashing.
|
// Since we don't use them, we can just remove them and avoid crashing.
|
||||||
fl &= ~Spanned.SPAN_PARAGRAPH;
|
fl &= ~Spanned.SPAN_PARAGRAPH;
|
||||||
|
|
||||||
int st = source.getSpanStart(spans[i]);
|
int st = source.getSpanStart(span);
|
||||||
int en = source.getSpanEnd(spans[i]);
|
int en = source.getSpanEnd(span);
|
||||||
|
|
||||||
if (st < start)
|
if (st < start)
|
||||||
st = start;
|
st = start;
|
||||||
if (en > end)
|
if (en > end)
|
||||||
en = end;
|
en = end;
|
||||||
|
|
||||||
dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
|
dest.setSpan(span, st - start + destoff, en - start + destoff, fl);
|
||||||
fl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,16 +90,16 @@ public final class SpannableStringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean spanned = false;
|
boolean spanned = false;
|
||||||
for (int i = 0; i < text.length; i++) {
|
for (CharSequence value : text) {
|
||||||
if (text[i] instanceof Spanned) {
|
if (value instanceof Spanned) {
|
||||||
spanned = true;
|
spanned = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (int i = 0; i < text.length; i++) {
|
for (CharSequence sequence : text) {
|
||||||
sb.append(text[i]);
|
sb.append(sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!spanned) {
|
if (!spanned) {
|
||||||
|
@ -107,11 +108,11 @@ public final class SpannableStringUtils {
|
||||||
|
|
||||||
SpannableString ss = new SpannableString(sb);
|
SpannableString ss = new SpannableString(sb);
|
||||||
int off = 0;
|
int off = 0;
|
||||||
for (int i = 0; i < text.length; i++) {
|
for (CharSequence charSequence : text) {
|
||||||
int len = text[i].length();
|
int len = charSequence.length();
|
||||||
|
|
||||||
if (text[i] instanceof Spanned) {
|
if (charSequence instanceof Spanned) {
|
||||||
copyNonParagraphSuggestionSpansFrom((Spanned) text[i], 0, len, ss, off);
|
copyNonParagraphSuggestionSpansFrom((Spanned) charSequence, 0, len, ss, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
off += len;
|
off += len;
|
||||||
|
@ -120,6 +121,13 @@ public final class SpannableStringUtils {
|
||||||
return new SpannedString(ss);
|
return new SpannedString(ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public static Spanned fromHtml(final String text) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||||
|
return Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY);
|
||||||
|
return Html.fromHtml(text);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean hasUrlSpans(final CharSequence text,
|
public static boolean hasUrlSpans(final CharSequence text,
|
||||||
final int startIndex, final int endIndex) {
|
final int startIndex, final int endIndex) {
|
||||||
if (!(text instanceof Spanned)) {
|
if (!(text instanceof Spanned)) {
|
||||||
|
@ -178,6 +186,6 @@ public final class SpannableStringUtils {
|
||||||
sequences.remove(i);
|
sequences.remove(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sequences.toArray(new CharSequence[sequences.size()]);
|
return sequences.toArray(new CharSequence[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue