mirror of
https://github.com/divkit/divkit.git
synced 2026-05-07 20:02:32 +00:00
[Android] Support enter_key_actions for multiline input
commit_hash:3a2f3c0300831299a61c31a09c381bca237c796f
This commit is contained in:
@@ -21845,6 +21845,7 @@
|
||||
"test_data/ui_test_data/input/div_input_highlight.json":"divkit/public/test_data/ui_test_data/input/div_input_highlight.json",
|
||||
"test_data/ui_test_data/input/div_input_is_enabled.json":"divkit/public/test_data/ui_test_data/input/div_input_is_enabled.json",
|
||||
"test_data/ui_test_data/input/div_input_multi_line_text.json":"divkit/public/test_data/ui_test_data/input/div_input_multi_line_text.json",
|
||||
"test_data/ui_test_data/input/div_input_multi_line_text_enter_key_actions.json":"divkit/public/test_data/ui_test_data/input/div_input_multi_line_text_enter_key_actions.json",
|
||||
"test_data/ui_test_data/input/div_input_number.json":"divkit/public/test_data/ui_test_data/input/div_input_number.json",
|
||||
"test_data/ui_test_data/input/div_input_phone.json":"divkit/public/test_data/ui_test_data/input/div_input_phone.json",
|
||||
"test_data/ui_test_data/input/div_input_single_line_text.json":"divkit/public/test_data/ui_test_data/input/div_input_single_line_text.json",
|
||||
|
||||
+54
@@ -4,9 +4,14 @@ import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Rect
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyEvent
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputConnection
|
||||
import android.view.inputmethod.InputConnectionWrapper
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
@@ -46,6 +51,8 @@ internal class DivInputView @JvmOverloads constructor(
|
||||
|
||||
private var _isFocusable = true
|
||||
|
||||
private var editorActionListener: OnEditorActionListener? = null
|
||||
|
||||
var enabled = true
|
||||
internal set(value) {
|
||||
field = value
|
||||
@@ -95,6 +102,10 @@ internal class DivInputView @JvmOverloads constructor(
|
||||
isFocusableInTouchMode = isFocusable
|
||||
}
|
||||
|
||||
override fun setOnEditorActionListener(l: OnEditorActionListener?) {
|
||||
editorActionListener = l
|
||||
}
|
||||
|
||||
fun addAfterTextChangeAction(action: (Editable?) -> Unit) {
|
||||
if (textChangeWatcher == null) {
|
||||
textChangeWatcher = doAfterTextChanged { editable ->
|
||||
@@ -110,4 +121,47 @@ internal class DivInputView @JvmOverloads constructor(
|
||||
onTextChangedActions.clear()
|
||||
textChangeWatcher = null
|
||||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
if ((inputType and InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0 &&
|
||||
(keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER)
|
||||
) {
|
||||
val imeAction = imeOptions and EditorInfo.IME_MASK_ACTION
|
||||
editorActionListener?.onEditorAction(this, imeAction, event)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event)
|
||||
}
|
||||
|
||||
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
|
||||
val baseInputConnection = super.onCreateInputConnection(outAttrs) ?: return null
|
||||
if ((inputType and InputType.TYPE_TEXT_FLAG_MULTI_LINE) == 0) return baseInputConnection
|
||||
return object : InputConnectionWrapper(baseInputConnection, true) {
|
||||
override fun sendKeyEvent(event: KeyEvent): Boolean {
|
||||
if ((event.keyCode == KeyEvent.KEYCODE_ENTER ||
|
||||
event.keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER) &&
|
||||
event.action == KeyEvent.ACTION_DOWN
|
||||
) {
|
||||
val imeAction = imeOptions and EditorInfo.IME_MASK_ACTION
|
||||
editorActionListener?.onEditorAction(this@DivInputView, imeAction, event)?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
return super.sendKeyEvent(event)
|
||||
}
|
||||
|
||||
//Enter key from soft keyboard
|
||||
override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean {
|
||||
if (text == "\n") {
|
||||
val imeAction = imeOptions and EditorInfo.IME_MASK_ACTION
|
||||
editorActionListener?.onEditorAction(this@DivInputView, imeAction, null)?.let{
|
||||
return it
|
||||
}
|
||||
}
|
||||
return super.commitText(text, newCursorPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -9,6 +9,7 @@ import org.junit.Test
|
||||
|
||||
private const val TEXT_BEFORE_BREAK = "https://Text_with different+symbols(123)@site.ru"
|
||||
internal const val TEXT_WITH_DIFFERENT_SYMBOLS = "$TEXT_BEFORE_BREAK\nsecond_line"
|
||||
internal const val SEARCH_KEY_TAPPED = "Search key tapped!"
|
||||
|
||||
class DivInputKeyboardTypeTest {
|
||||
|
||||
@@ -83,6 +84,15 @@ class DivInputKeyboardTypeTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun checkMultiLineTextEnterKeyActions() {
|
||||
checkType(
|
||||
type = "multi_line_text_enter_key_actions",
|
||||
expectedText = SEARCH_KEY_TAPPED,
|
||||
typedText = "\n"
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkType(
|
||||
type: String,
|
||||
expectedText: String,
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"card": {
|
||||
"log_id": "ui_test_card",
|
||||
"variables": [
|
||||
{
|
||||
"name": "input_value",
|
||||
"type": "string",
|
||||
"value": "Initial text"
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
{
|
||||
"state_id": 0,
|
||||
"div": {
|
||||
"type": "container",
|
||||
"width": {
|
||||
"type": "match_parent"
|
||||
},
|
||||
"height": {
|
||||
"type": "wrap_content"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"type": "input",
|
||||
"width": {
|
||||
"type": "match_parent"
|
||||
},
|
||||
"height": {
|
||||
"type": "wrap_content"
|
||||
},
|
||||
"margins": {
|
||||
"left": 16,
|
||||
"top": 20,
|
||||
"right": 16,
|
||||
"bottom": 16
|
||||
},
|
||||
"paddings": {
|
||||
"left": 16,
|
||||
"top": 10,
|
||||
"right": 16,
|
||||
"bottom": 10
|
||||
},
|
||||
"alpha": 1.0,
|
||||
"alignment_horizontal": "center",
|
||||
"alignment_vertical": "center",
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#0e000000"
|
||||
}
|
||||
],
|
||||
"border": {
|
||||
"corner_radius": 8
|
||||
},
|
||||
"font_size": 16,
|
||||
"font_weight": "medium",
|
||||
"text_color": "#000000",
|
||||
"text_variable": "input_value",
|
||||
"hint_text": "Hint",
|
||||
"hint_color": "#888888",
|
||||
"highlight_color": "#e0bae3",
|
||||
"line_height": 22,
|
||||
"keyboard_type": "multi_line_text",
|
||||
"enter_key_type": "search",
|
||||
"enter_key_actions": [
|
||||
{
|
||||
"log_id": "enter_key_tapped",
|
||||
"url": "div-action://set_variable?name=input_value&value=Search key tapped!"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"width": {
|
||||
"type": "match_parent"
|
||||
},
|
||||
"height": {
|
||||
"type": "wrap_content"
|
||||
},
|
||||
"paddings": {
|
||||
"left": 18,
|
||||
"right": 16,
|
||||
"bottom": 16
|
||||
},
|
||||
"alpha": 1.0,
|
||||
"alignment_horizontal": "center",
|
||||
"alignment_vertical": "center",
|
||||
"font_size": 16,
|
||||
"font_weight": "medium",
|
||||
"text_alignment_horizontal": "left",
|
||||
"text_alignment_vertical": "center",
|
||||
"text_color": "#000000",
|
||||
"text": "Text: @{input_value}",
|
||||
"ranges": [
|
||||
{
|
||||
"start": 0,
|
||||
"end": 5,
|
||||
"text_color": "#777777"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user