-
Notifications
You must be signed in to change notification settings - Fork 273
TextInput Events
Maciej Jastrzebski edited this page May 4, 2023
·
38 revisions
RN version: 0.71.6
Setup:
<TextInput
style={styles.textInput}
value={value}
onChangeText={handleChangeText}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
onEndEditing={handleEndEditing}
onSubmitEditing={handleSubmitEditing}
onKeyPress={handleKeyPress}
onTextInput={handleTextInput}
onSelectionChange={handleSelectionChange}
onContentSizeChange={handleContentSizeChange}
/>
Steps:
- Press on the text input
- Type "Test" using on screen keyboard
- Press "return" to close the keyboard
Output:
iOS:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 153, "locationY": 10.333328247070312, "pageX": 173, "pageY": 121.33332824707031, "target": 75, "timestamp": 975406399.731625, "touches": [[Circular]]}
LOG Event: focus {"eventCount": 0, "target": 75, "text": ""}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 153, "locationY": 10.333328247070312, "pageX": 173, "pageY": 121.33332824707031, "target": 75, "timestamp": 975406478.905625, "touches": []}
LOG Event: keyPress {"eventCount": 0, "key": "T", "target": 75}
LOG Event: textInput {"eventCount": 0, "previousText": "", "range": {"end": 0, "start": 0}, "target": 75, "text": "T"}
LOG Event: change {"eventCount": 1, "target": 75, "text": "T"}
LOG Event: changeText T
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 11}, "target": 75}
LOG Event: keyPress {"eventCount": 1, "key": "e", "target": 75}
LOG Event: textInput {"eventCount": 1, "previousText": "T", "range": {"end": 1, "start": 1}, "target": 75, "text": "e"}
LOG Event: change {"eventCount": 2, "target": 75, "text": "Te"}
LOG Event: changeText Te
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 19}, "target": 75}
LOG Event: keyPress {"eventCount": 2, "key": "s", "target": 75}
LOG Event: textInput {"eventCount": 2, "previousText": "Te", "range": {"end": 2, "start": 2}, "target": 75, "text": "s"}
LOG Event: change {"eventCount": 3, "target": 75, "text": "Tes"}
LOG Event: changeText Tes
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 28}, "target": 75}
LOG Event: keyPress {"eventCount": 3, "key": "t", "target": 75}
LOG Event: textInput {"eventCount": 3, "previousText": "Tes", "range": {"end": 3, "start": 3}, "target": 75, "text": "t"}
LOG Event: change {"eventCount": 4, "target": 75, "text": "Test"}
LOG Event: changeText Test
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 34}, "target": 75}
LOG Event: submitEditing {"eventCount": 4, "target": 75, "text": "Test"}
LOG Event: endEditing {"eventCount": 4, "target": 75, "text": "Test"}
LOG Event: blur {"eventCount": 4, "target": 75, "text": "Test"}
Android:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 80.36363983154297, "locationY": 29.090909957885742, "pageX": 100.36363983154297, "pageY": 129.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 107060200, "touches": [[Circular]]}
LOG Event: focus {"target": 53}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 80.36363983154297, "locationY": 29.090909957885742, "pageX": 100.36363983154297, "pageY": 129.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 107060255, "touches": []}
LOG Event: textInput {"previousText": "", "range": {"end": 0, "start": 0}, "target": 53, "text": "T"}
LOG Event: change {"eventCount": 2, "target": 53, "text": "T"}
LOG Event: changeText T
LOG Event: textInput {"previousText": "", "range": {"end": 0, "start": 0}, "target": 53, "text": "T"}
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}}
LOG Event: keyPress {"key": "T"}
LOG Event: textInput {"previousText": "T", "range": {"end": 1, "start": 0}, "target": 53, "text": "Te"}
LOG Event: change {"eventCount": 4, "target": 53, "text": "Te"}
LOG Event: changeText Te
LOG Event: textInput {"previousText": "T", "range": {"end": 1, "start": 0}, "target": 53, "text": "Te"}
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}}
LOG Event: keyPress {"key": "e"}
LOG Event: textInput {"previousText": "Te", "range": {"end": 2, "start": 0}, "target": 53, "text": "Tes"}
LOG Event: change {"eventCount": 6, "target": 53, "text": "Tes"}
LOG Event: changeText Tes
LOG Event: textInput {"previousText": "Te", "range": {"end": 2, "start": 0}, "target": 53, "text": "Tes"}
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}}
LOG Event: keyPress {"key": "s"}
LOG Event: textInput {"previousText": "Tes", "range": {"end": 3, "start": 0}, "target": 53, "text": "Test"}
LOG Event: change {"eventCount": 8, "target": 53, "text": "Test"}
LOG Event: changeText Test
LOG Event: textInput {"previousText": "Tes", "range": {"end": 3, "start": 0}, "target": 53, "text": "Test"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: keyPress {"key": "t"}
LOG Event: submitEditing {"target": 53, "text": "Test"}
LOG Event: blur {"target": 53}
LOG Event: endEditing {"target": 53, "text": "Test"}
Notes:
- Sequence of events on focusing both platforms is the same:
pressIn
-focus
-pressOut
- Sequence of events on pressing Enter on both platforms is slightly:
- iOS:
submitEditing
-endEditing
-blur
- Android:
submitEditing
-blur
-endEditing
- iOS:
- Sequence of events of typing is different:
- iOS:
keyPress
-textInput
-change
-changeText
-selectionChange
-contentSizeChange
- Android:
textInput
-change
-changeText
-textInput
-selectionChange
-keyPress
- iOS:
- The
submitEditing
event is only emitted if user presses done/next/etc field, but not in case of tapping on another focusable element - In case of unmanaged
TextInput
(i.e. novalue
prop being passed) the events are the same on Android (TODO: confirm on iOS)
RN version: 0.71.6
Setup:
<TextInput
style={styles.textInput}
value={value}
mutliline={true}
onChangeText={handleChangeText}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
onEndEditing={handleEndEditing}
onSubmitEditing={handleSubmitEditing}
onKeyPress={handleKeyPress}
onTextInput={handleTextInput}
onSelectionChange={handleSelectionChange}
onContentSizeChange={handleContentSizeChange}
/>
Steps:
- Press on the text input
- Type "AB\nCD" using on screen keyboard
- Press "return" to close the keyboard
Output:
iOS:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 244.66665649414062, "locationY": 14.333328247070312, "pageX": 264.6666564941406, "pageY": 125.33332824707031, "target": 75, "timestamp": 1014407822.0294167, "touches": [[Circular]]}
LOG Event: focus {"eventCount": 0, "target": 75, "text": ""}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 244.66665649414062, "locationY": 14.333328247070312, "pageX": 264.6666564941406, "pageY": 125.33332824707031, "target": 75, "timestamp": 1014407901.1994168, "touches": []}
LOG Event: keyPress {"eventCount": 0, "key": "A", "target": 75}
LOG Event: textInput {"eventCount": 0, "previousText": "", "range": {"end": 0, "start": 0}, "target": 75, "text": "A"}
LOG Event: change {"eventCount": 1, "target": 75, "text": "A"}
LOG Event: changeText A
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 11.666666666666666}, "target": 75}
LOG Event: keyPress {"eventCount": 1, "key": "B", "target": 75}
LOG Event: textInput {"eventCount": 1, "previousText": "A", "range": {"end": 1, "start": 1}, "target": 75, "text": "B"}
LOG Event: change {"eventCount": 2, "target": 75, "text": "AB"}
LOG Event: changeText AB
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 23.333333333333332}, "target": 75}
// Enter key
LOG Event: keyPress {"eventCount": 2, "key": "Enter", "target": 75}
LOG Event: textInput {"eventCount": 2, "previousText": "AB", "range": {"end": 2, "start": 2}, "target": 75, "text": "\n"}
LOG Event: change {"eventCount": 3, "target": 75, "text": "AB\n"}
LOG Event: changeText AB
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 43, "width": 23.333333333333332}, "target": 75}
LOG Event: keyPress {"eventCount": 3, "key": "C", "target": 75}
LOG Event: textInput {"eventCount": 3, "previousText": "AB\n", "range": {"end": 3, "start": 3}, "target": 75, "text": "C"}
LOG Event: change {"eventCount": 4, "target": 75, "text": "AB\nC"}
LOG Event: changeText AB\nC
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}, "target": 75}
LOG Event: keyPress {"eventCount": 4, "key": "D", "target": 75}
LOG Event: textInput {"eventCount": 4, "previousText": "AB
C", "range": {"end": 4, "start": 4}, "target": 75, "text": "D"}
LOG Event: change {"eventCount": 5, "target": 75, "text": "AB\nCD"}
LOG Event: changeText AB\nCD
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 43, "width": 25.333333333333332}, "target": 75}
LOG Event: endEditing {"eventCount": 5, "target": 75, "text": "AB\nCD"}
LOG Event: blur {"eventCount": 5, "target": 75, "text": "AB\nCD"}
Android:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 257.4545593261719, "locationY": 33.09090805053711, "pageX": 277.4545593261719, "pageY": 133.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 168170420, "touches": [[Circular]]}
LOG Event: focus {"target": 53}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 257.4545593261719, "locationY": 33.818180084228516, "pageX": 277.4545593261719, "pageY": 133.81817626953125, "target": 53, "targetSurface": -1, "timestamp": 168170514, "touches": []}
LOG Event: textInput {"previousText": "", "range": {"end": 0, "start": 0}, "target": 53, "text": "A"}
LOG Event: change {"eventCount": 2, "target": 53, "text": "A"}
LOG Event: changeText A
LOG Event: textInput {"previousText": "", "range": {"end": 0, "start": 0}, "target": 53, "text": "A"}
LOG Event: selectionChange {"selection": {"end": 1, "start": 1}}
LOG Event: keyPress {"key": "A"}
LOG Event: textInput {"previousText": "A", "range": {"end": 1, "start": 0}, "target": 53, "text": "AB"}
LOG Event: change {"eventCount": 4, "target": 53, "text": "AB"}
LOG Event: changeText AB
LOG Event: textInput {"previousText": "A", "range": {"end": 1, "start": 0}, "target": 53, "text": "AB"}
LOG Event: selectionChange {"selection": {"end": 2, "start": 2}}
LOG Event: keyPress {"key": "B"}
// Enter
LOG Event: textInput {"previousText": "AB", "range": {"end": 2, "start": 0}, "target": 53, "text": "AB\n"}
LOG Event: contentSizeChange {"contentSize": {"height": 61.45454406738281, "width": 352.7272644042969}, "target": 53}
LOG Event: change {"eventCount": 6, "target": 53, "text": "AB\n"}
LOG Event: changeText AB
LOG Event: textInput {"previousText": "AB", "range": {"end": 2, "start": 0}, "target": 53, "text": "AB\n"}
LOG Event: selectionChange {"selection": {"end": 3, "start": 3}}
LOG Event: textInput {"previousText": "", "range": {"end": 3, "start": 3}, "target": 53, "text": "C"}
LOG Event: change {"eventCount": 8, "target": 53, "text": "AB\nC"}
LOG Event: changeText AB\nC
LOG Event: textInput {"previousText": "", "range": {"end": 3, "start": 3}, "target": 53, "text": "C"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: keyPress {"key": "C"}
LOG Event: textInput {"previousText": "C", "range": {"end": 4, "start": 3}, "target": 53, "text": "CD"}
LOG Event: change {"eventCount": 10, "target": 53, "text": "AB\nCD"}
LOG Event: changeText AB\nCD
LOG Event: textInput {"previousText": "C", "range": {"end": 4, "start": 3}, "target": 53, "text": "CD"}
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "D"}
LOG Event: blur {"target": 53}
LOG Event: endEditing {"target": 53, "text": "AB\nCD"}
Notes:
- Sequence of events on focusing both platforms is the same:
pressIn
-focus
-pressOut
- Sequence of events on pressing Enter on both platforms is slightly:
- iOS:
endEditing
-blur
- Android:
blur
-endEditing
- iOS:
- Sequence of events of typing is different:
- iOS:
keyPress
-textInput
-change
-changeText
-selectionChange
-contentSizeChange
(when it actually changes) - Android:
textInput
-contentSizeChange
(only for Enter) -change
-changeText
-textInput
-selectionChange
-keyPress
(not for Enter)
- iOS:
- The
submitEditing
event is only emitted if user presses done/next/etc field, but not in case of tapping on another focusable element
Setup:
<TextInput
style={styles.textInput}
value={value}
onChangeText={handleChangeText}
editable={false}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
/>
Steps:
- Press
TextInput
Output:
iOS:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 57.33332824707031, "locationY": 35, "pageX": 77.33332824707031, "pageY": 146, "target": 117, "timestamp": 707054389.9047917, "touches": [[Circular]]}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 57.33332824707031, "locationY": 35, "pageX": 77.33332824707031, "pageY": 146, "target": 117, "timestamp": 707054477.4037917, "touches": []}
Android:
(No events logged)
RN version: 0.71.6
Setup:
<TextInput
style={styles.textInput}
value="AAAA"
editable={true}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
onChangeText={handleChangeText}
onSubmitEditing={handleSubmitEditing}
onKeyPress={handleKeyPress}
onTextInput={handleTextInput}
onSelectionChange={handleSelectionChange}
onContentSizeChange={handleContentSizeChange}
/>
Steps:
- Press on the text input
- Type "Test" using on screen keyboard
- Press "return" to close the keyboard
Output:
iOS:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 107, "locationY": 12, "pageX": 127, "pageY": 123, "target": 75, "timestamp": 967401529.229625, "touches": [[Circular]]}
LOG Event: focus {"eventCount": 0, "target": 75, "text": "AAAA"}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 107, "locationY": 12, "pageX": 127, "pageY": 123, "target": 75, "timestamp": 967401608.349625, "touches": []}
LOG Event: keyPress {"eventCount": 0, "key": "t", "target": 75}
LOG Event: textInput {"eventCount": 0, "previousText": "AAAA", "range": {"end": 4, "start": 4}, "target": 75, "text": "t"}
LOG Event: change {"eventCount": 1, "target": 75, "text": "AAAAt"}
LOG Event: changeText AAAAt
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 52.333333333333336}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: keyPress {"eventCount": 1, "key": "e", "target": 75}
LOG Event: textInput {"eventCount": 1, "previousText": "AAAA", "range": {"end": 4, "start": 4}, "target": 75, "text": "e"}
LOG Event: change {"eventCount": 2, "target": 75, "text": "AAAAe"}
LOG Event: changeText AAAAe
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 56}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: keyPress {"eventCount": 2, "key": "s", "target": 75}
LOG Event: textInput {"eventCount": 2, "previousText": "AAAA", "range": {"end": 4, "start": 4}, "target": 75, "text": "s"}
LOG Event: change {"eventCount": 3, "target": 75, "text": "AAAAs"}
LOG Event: changeText AAAAs
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 55.666666666666664}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: keyPress {"eventCount": 3, "key": "t", "target": 75}
LOG Event: textInput {"eventCount": 3, "previousText": "AAAA", "range": {"end": 4, "start": 4}, "target": 75, "text": "t"}
LOG Event: change {"eventCount": 4, "target": 75, "text": "AAAAt"}
LOG Event: changeText AAAAt
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 52.333333333333336}, "target": 75}
LOG Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}
LOG Event: submitEditing {"eventCount": 4, "target": 75, "text": "AAAA"}
LOG Event: blur {"eventCount": 4, "target": 75, "text": "AAAA"}
Android:
LOG Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 94.18181610107422, "locationY": 22.18181800842285, "pageX": 114.18181610107422, "pageY": 122.18181610107422, "target": 53, "targetSurface": -1, "timestamp": 91073165, "touches": [[Circular]]}
LOG Event: focus {"target": 53}
// `selectionChange` only happens on first focus. Subsequent focuses skip it.
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 94.18181610107422, "locationY": 22.18181800842285, "pageX": 114.18181610107422, "pageY": 122.18181610107422, "target": 53, "targetSurface": -1, "timestamp": 91073239, "touches": []}
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAT"}
LOG Event: change {"eventCount": 2, "target": 53, "text": "AAAAT"}
LOG Event: changeText AAAAT
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAT"}
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "T"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAe"}
LOG Event: change {"eventCount": 4, "target": 53, "text": "AAAAe"}
LOG Event: changeText AAAAe
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAe"}
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "e"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAs"}
LOG Event: change {"eventCount": 6, "target": 53, "text": "AAAAs"}
LOG Event: changeText AAAAs
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAs"}
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "s"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAt"}
LOG Event: change {"eventCount": 8, "target": 53, "text": "AAAAt"}
LOG Event: changeText AAAAt
LOG Event: textInput {"previousText": "AAAA", "range": {"end": 4, "start": 0}, "target": 53, "text": "AAAAt"}
LOG Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG Event: keyPress {"key": "t"}
LOG Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG Event: submitEditing {"target": 53, "text": "AAAA"}
LOG Event: blur {"target": 53}