Fix text input spans

Differential Revision: D2626072

fb-gh-sync-id: 35087d65b8f4a52e44fedc229058c3f88827e539
This commit is contained in:
Andrei Coman 2015-11-06 08:22:22 -08:00 committed by facebook-github-bot-9
parent 7b2cd03d6a
commit de586bfa18
4 changed files with 82 additions and 2 deletions

View File

@ -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({
multiline: {
height: 60,
@ -109,6 +163,10 @@ var styles = StyleSheet.create({
singleLineWithHeightTextInput: {
height: 30,
},
hashtag: {
color: 'blue',
fontWeight: 'bold',
},
});
exports.title = '<TextInput>';
@ -322,4 +380,10 @@ exports.examples = [
);
}
},
{
title: 'Attributed text',
render: function() {
return <TokenizedTextExample />;
}
},
];

View File

@ -20,12 +20,17 @@ import android.text.InputType;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
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.KeyEvent;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
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
@ -204,6 +209,15 @@ public class ReactEditText extends EditText {
private void manageSpans(SpannableStringBuilder spannableStringBuilder) {
Object[] spans = getText().getSpans(0, length(), Object.class);
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) !=
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
continue;

View File

@ -16,8 +16,9 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
/**
* 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";

View File

@ -16,8 +16,9 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
/**
* 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";