kotlin 撤消/重做,如何处理Jetpack编写的文本字段中的doOnTextChanged和doBeforeTextChanged?

5jvtdoz2  于 2022-11-25  发布在  Kotlin
关注(0)|答案(1)|浏览(192)

我需要在Jetpack Compose中为TextField实现redo/undo。对于EditText,我使用了这个one,它运行得很好。但是,对于Jetpack Compose,没有这样的侦听器。我将基于EditText的侦听器实现一个自己的侦听器,但是我缺少这两个侦听器方法,它们对TextField不可用:

doOnTextChanged { text, start, before, count -> }
doBeforeTextChanged { text, start, count, after -> }

在TextField中只能使用一个侦听器

onValuesChange = { }

仅返回没有startcount****字符串**
我找了找,什么也没找到。
如何在Jetpack Compose中为TextField实现重做/撤消?

  • 谢谢-谢谢
    编辑:
    顺便说一句,这就是我到目前为止所做的。如果能让它发挥作用就太好了。
class EditTextDo {

    private var mIsUndoOrRedo = false
    private val editHistory: EditHistory? = null

    fun redo() {
        val edit = editHistory?.getNext() ?: return

        // Do Redo
    }

    fun undo() {
        val edit = editHistory?.getPrevious() ?: return

        // Do Undo
    }

    fun canUndo(): Boolean {
        editHistory?.let {
            return it.position > 0
        }
        return false
    }

    fun canRedo(): Boolean {
        editHistory?.let {
            return it.position < it.history.size
        }
        return false
    }

}

class EditHistory {

    var position = 0

    private var maxHistorySize = -1

    val history = LinkedList<EditItem>()

    private fun clear() {
        position = 0
        history.clear()
    }

    fun add(item: EditItem) {
        while (history.size > position) {
            history.removeLast()
        }
        history.add(item)
        position++
        if (maxHistorySize >= 0)
            trimHistory()
    }

    fun getNext(): EditItem? {
        if (position >= history.size) {
            return null
        }
        val item = history[position]
        position++
        return item
    }

    fun getPrevious(): EditItem? {
        if (position == 0) {
            return null
        }
        position--
        return history[position]
    }

    private fun setMaxHistorySize(maxHistorySize: Int) {
        this.maxHistorySize = maxHistorySize
        if (maxHistorySize >= 0)
            trimHistory()
    }

    private fun trimHistory() {
        while (history.size > maxHistorySize) {
            history.removeFirst()
            position--
        }
        if (position < 0)
            position = 0
    }
}

data class EditItem(val start: Int, val before: CharSequence, val after: CharSequence)
sqxo8psd

sqxo8psd1#

这可能不完全解决你的帖子,但希望它能有所帮助。我在我的项目上有一个简单的undo/redoTextfield,使用Queue结构来跟踪输入历史,但我没有指定历史大小。

@Composable
fun TextFieldWithHistory() {

    val undoRedoState = remember { UndoRedoState() }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .wrapContentHeight()
    ) {
        TextField(
            value = undoRedoState.input,
            onValueChange = {
                undoRedoState.onInput(it)
            }
        )

        Button(
            onClick = {
                undoRedoState.undo()
            }) {
            Text(text = "Undo")
        }

        Button(
            onClick = {
                undoRedoState.redo()
            }) {
            Text(text = "Redo")
        }
    }
}

class UndoRedoState {

    var input by mutableStateOf(TextFieldValue(""))
    var undoHistory = ArrayDeque<TextFieldValue?>()
    var redoHistory = ArrayDeque<TextFieldValue?>()

    init {
        undoHistory.add(input)
    }

    fun onInput(value: TextFieldValue) {
        // always set the cursor at the end (selection = text length)
        val updatedValue =  value.copy(value.text, selection = TextRange(value.text.length))
        undoHistory.add(updatedValue)
        input = updatedValue
    }

    fun undo() {

        if (undoHistory.size > 1) {

            // pop the last
            val pop = undoHistory.removeLastOrNull()
            pop?.let {
                if (it.text.isNotEmpty()) {
                    redoHistory.add(it)
                }
            }

            // peek the last
            val peek = undoHistory.lastOrNull()
            peek?.let{
                input = it
            }
        }
    }

    fun redo() {
        val pop = redoHistory.removeLastOrNull()
        pop?.let {
            if (it.text.isNotEmpty()) {
                undoHistory.add(it)
                input = it
            }
        }
    }
}

相关问题