mirror of
https://github.com/BetterAndroid/PanguText.git
synced 2025-09-04 09:45:37 +08:00
refactor: decoupling mListeners in PanguTextWatcher to TextViewDelegate
This commit is contained in:
@@ -26,9 +26,9 @@ import android.text.TextWatcher
|
|||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import com.highcapable.betterandroid.system.extension.tool.AndroidVersion
|
import com.highcapable.betterandroid.system.extension.tool.AndroidVersion
|
||||||
import com.highcapable.kavaref.KavaRef.Companion.asResolver
|
|
||||||
import com.highcapable.pangutext.android.PanguText
|
import com.highcapable.pangutext.android.PanguText
|
||||||
import com.highcapable.pangutext.android.PanguTextConfig
|
import com.highcapable.pangutext.android.PanguTextConfig
|
||||||
|
import com.highcapable.pangutext.android.core.TextViewDelegate.Companion.delegate
|
||||||
import com.highcapable.pangutext.android.extension.injectRealTimePanguText
|
import com.highcapable.pangutext.android.extension.injectRealTimePanguText
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,15 +40,7 @@ import com.highcapable.pangutext.android.extension.injectRealTimePanguText
|
|||||||
*/
|
*/
|
||||||
class PanguTextWatcher internal constructor(private val base: TextView, private val config: PanguTextConfig) : TextWatcher {
|
class PanguTextWatcher internal constructor(private val base: TextView, private val config: PanguTextConfig) : TextWatcher {
|
||||||
|
|
||||||
/**
|
private val delegate = base.delegate
|
||||||
* The text watchers of the base [TextView].
|
|
||||||
* @return [ArrayList]<[TextWatcher]>.
|
|
||||||
*/
|
|
||||||
private val textWatchers
|
|
||||||
get() = base.asResolver().optional(silent = true).firstFieldOrNull {
|
|
||||||
name = "mListeners"
|
|
||||||
superclass()
|
|
||||||
}?.getQuietly<ArrayList<TextWatcher>>()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to automatically re-measure the text width after processing.
|
* Whether to automatically re-measure the text width after processing.
|
||||||
@@ -62,20 +54,12 @@ class PanguTextWatcher internal constructor(private val base: TextView, private
|
|||||||
editable?.let { PanguText.format(base.resources, base.textSize, it, config) }
|
editable?.let { PanguText.format(base.resources, base.textSize, it, config) }
|
||||||
if (!isAutoRemeasureText) return
|
if (!isAutoRemeasureText) return
|
||||||
|
|
||||||
val currentWatchers = mutableListOf<TextWatcher>()
|
delegate.withoutTextWatchers {
|
||||||
textWatchers?.also {
|
// Reset the text to trigger remeasurement.
|
||||||
currentWatchers.addAll(it)
|
base.text = editable
|
||||||
// Avoid triggering events again during processing.
|
|
||||||
it.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the text to trigger remeasurement.
|
|
||||||
base.text = editable
|
|
||||||
// Re-add to continue listening to text changes.
|
|
||||||
textWatchers?.addAll(currentWatchers)
|
|
||||||
|
|
||||||
currentWatchers.clear()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||||
}
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* PanguText - A typographic solution for the optimal alignment of CJK characters, English words, and half-width digits.
|
||||||
|
* Copyright (C) 2019 HighCapable
|
||||||
|
* https://github.com/BetterAndroid/PanguText
|
||||||
|
*
|
||||||
|
* Apache License Version 2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is created by fankes on 2025/8/15.
|
||||||
|
*/
|
||||||
|
package com.highcapable.pangutext.android.core
|
||||||
|
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.widget.TextView
|
||||||
|
import com.highcapable.kavaref.KavaRef.Companion.resolve
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A delegate for [TextView] to manage its text watchers.
|
||||||
|
* @param instance the [TextView] instance.
|
||||||
|
*/
|
||||||
|
internal class TextViewDelegate private constructor(private val instance: TextView) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val mListeners by lazy {
|
||||||
|
TextView::class.resolve()
|
||||||
|
.optional(silent = true)
|
||||||
|
.firstFieldOrNull { name = "mListeners" }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the [TextViewDelegate] for the given [TextView] instance.
|
||||||
|
* @return [TextViewDelegate]
|
||||||
|
*/
|
||||||
|
val TextView.delegate get() = TextViewDelegate(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The text watchers of the [TextView].
|
||||||
|
* @return [ArrayList]<[TextWatcher]>.
|
||||||
|
*/
|
||||||
|
private val textWatchers
|
||||||
|
get() = mListeners?.copy()?.of(instance)?.getQuietly<ArrayList<TextWatcher>>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the given action without triggering text watchers.
|
||||||
|
* @param action the action to execute without triggering text watchers.
|
||||||
|
*/
|
||||||
|
inline fun withoutTextWatchers(action: () -> Unit) {
|
||||||
|
val currentWatchers = mutableListOf<TextWatcher>()
|
||||||
|
textWatchers?.also {
|
||||||
|
currentWatchers.addAll(it)
|
||||||
|
// Avoid triggering events again during processing.
|
||||||
|
it.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run action.
|
||||||
|
action()
|
||||||
|
// Re-add to continue listening to text changes.
|
||||||
|
textWatchers?.addAll(currentWatchers)
|
||||||
|
|
||||||
|
currentWatchers.clear()
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user