mirror of
https://github.com/status-im/react-native.git
synced 2025-01-28 18:25:06 +00:00
Fix text input spans
Differential Revision: D2626072 fb-gh-sync-id: 35087d65b8f4a52e44fedc229058c3f88827e539
This commit is contained in:
parent
7b2cd03d6a
commit
de586bfa18
@ -91,6 +91,60 @@ class RewriteExample extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TokenizedTextExample extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {text: 'Hello #World'};
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
|
||||||
|
//define delimiter
|
||||||
|
let delimiter = /\s+/;
|
||||||
|
|
||||||
|
//split string
|
||||||
|
let _text = this.state.text;
|
||||||
|
let token, index, parts = [];
|
||||||
|
while (_text) {
|
||||||
|
delimiter.lastIndex = 0;
|
||||||
|
token = delimiter.exec(_text);
|
||||||
|
if (token === null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index = token.index;
|
||||||
|
if (token[0].length === 0) {
|
||||||
|
index = 1;
|
||||||
|
}
|
||||||
|
parts.push(_text.substr(0, index));
|
||||||
|
parts.push(token[0]);
|
||||||
|
index = index + token[0].length;
|
||||||
|
_text = _text.slice(index);
|
||||||
|
}
|
||||||
|
parts.push(_text);
|
||||||
|
|
||||||
|
//highlight hashtags
|
||||||
|
parts = parts.map((text) => {
|
||||||
|
if (/^#/.test(text)) {
|
||||||
|
return <Text key={text} style={styles.hashtag}>{text}</Text>;
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<TextInput
|
||||||
|
multiline={true}
|
||||||
|
style={styles.multiline}
|
||||||
|
onChangeText={(text) => {
|
||||||
|
this.setState({text});
|
||||||
|
}}>
|
||||||
|
<Text>{parts}</Text>
|
||||||
|
</TextInput>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var styles = StyleSheet.create({
|
var styles = StyleSheet.create({
|
||||||
multiline: {
|
multiline: {
|
||||||
height: 60,
|
height: 60,
|
||||||
@ -109,6 +163,10 @@ var styles = StyleSheet.create({
|
|||||||
singleLineWithHeightTextInput: {
|
singleLineWithHeightTextInput: {
|
||||||
height: 30,
|
height: 30,
|
||||||
},
|
},
|
||||||
|
hashtag: {
|
||||||
|
color: 'blue',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.title = '<TextInput>';
|
exports.title = '<TextInput>';
|
||||||
@ -322,4 +380,10 @@ exports.examples = [
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Attributed text',
|
||||||
|
render: function() {
|
||||||
|
return <TokenizedTextExample />;
|
||||||
|
}
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -20,12 +20,17 @@ import android.text.InputType;
|
|||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.text.style.AbsoluteSizeSpan;
|
||||||
|
import android.text.style.BackgroundColorSpan;
|
||||||
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import com.facebook.infer.annotation.Assertions;
|
import com.facebook.infer.annotation.Assertions;
|
||||||
|
import com.facebook.react.views.text.CustomStyleSpan;
|
||||||
|
import com.facebook.react.views.text.ReactTagSpan;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper around the EditText that lets us better control what happens when an EditText gets
|
* A wrapper around the EditText that lets us better control what happens when an EditText gets
|
||||||
@ -204,6 +209,15 @@ public class ReactEditText extends EditText {
|
|||||||
private void manageSpans(SpannableStringBuilder spannableStringBuilder) {
|
private void manageSpans(SpannableStringBuilder spannableStringBuilder) {
|
||||||
Object[] spans = getText().getSpans(0, length(), Object.class);
|
Object[] spans = getText().getSpans(0, length(), Object.class);
|
||||||
for (int spanIdx = 0; spanIdx < spans.length; spanIdx++) {
|
for (int spanIdx = 0; spanIdx < spans.length; spanIdx++) {
|
||||||
|
// Remove all styling spans we might have previously set
|
||||||
|
if (ForegroundColorSpan.class.isInstance(spans[spanIdx]) ||
|
||||||
|
BackgroundColorSpan.class.isInstance(spans[spanIdx]) ||
|
||||||
|
AbsoluteSizeSpan.class.isInstance(spans[spanIdx]) ||
|
||||||
|
CustomStyleSpan.class.isInstance(spans[spanIdx]) ||
|
||||||
|
ReactTagSpan.class.isInstance(spans[spanIdx])) {
|
||||||
|
getText().removeSpan(spans[spanIdx]);
|
||||||
|
}
|
||||||
|
|
||||||
if ((getText().getSpanFlags(spans[spanIdx]) & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) !=
|
if ((getText().getSpanFlags(spans[spanIdx]) & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) !=
|
||||||
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -16,8 +16,9 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Event emitted by EditText native view when text changes.
|
* Event emitted by EditText native view when text changes.
|
||||||
|
* VisibleForTesting from {@link TextInputEventsTestCase}.
|
||||||
*/
|
*/
|
||||||
/* package */ class ReactTextChangedEvent extends Event<ReactTextChangedEvent> {
|
public class ReactTextChangedEvent extends Event<ReactTextChangedEvent> {
|
||||||
|
|
||||||
public static final String EVENT_NAME = "topChange";
|
public static final String EVENT_NAME = "topChange";
|
||||||
|
|
||||||
|
@ -16,8 +16,9 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Event emitted by EditText native view when text changes.
|
* Event emitted by EditText native view when text changes.
|
||||||
|
* VisibleForTesting from {@link TextInputEventsTestCase}.
|
||||||
*/
|
*/
|
||||||
/* package */ class ReactTextInputEvent extends Event<ReactTextInputEvent> {
|
public class ReactTextInputEvent extends Event<ReactTextInputEvent> {
|
||||||
|
|
||||||
public static final String EVENT_NAME = "topTextInput";
|
public static final String EVENT_NAME = "topTextInput";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user