mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-03-06 22:37:14 +08:00
Implement data detection for android Text elements (#19216)
Summary: We want the ability to use Linkify on android text elements. This only adds this property to Text and not TextInput since there are some functional differences with how the types could be used between iOS and android - iOS allows one or many types while Linkify restricted us to providing only one option (using the masks). Performance is affected ONLY FOR TEXT ELEMENTS USING THIS FEATURE since Linkify is searching for patterns. Pull Request resolved: https://github.com/facebook/react-native/pull/19216 Differential Revision: D14621883 Pulled By: cpojer fbshipit-source-id: cb692021d314140b9a92b29e23384afd7fd1b09e
This commit is contained in:
committed by
Facebook Github Bot
parent
97c414ec8d
commit
b1251d067a
@@ -66,6 +66,7 @@ const viewConfig = {
|
||||
minimumFontScale: true,
|
||||
textBreakStrategy: true,
|
||||
onTextLayout: true,
|
||||
dataDetectorType: true,
|
||||
},
|
||||
directEventTypes: {
|
||||
topTextLayout: {
|
||||
|
||||
@@ -18,6 +18,8 @@ const TextStylePropTypes = require('TextStylePropTypes');
|
||||
|
||||
const stylePropType = DeprecatedStyleSheetPropType(TextStylePropTypes);
|
||||
|
||||
const DataDetectorTypes = ['phoneNumber', 'link', 'email', 'none', 'all'];
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* When `numberOfLines` is set, this prop defines how text will be
|
||||
@@ -132,4 +134,10 @@ module.exports = {
|
||||
* See https://facebook.github.io/react-native/docs/text.html#disabled
|
||||
*/
|
||||
disabled: PropTypes.bool,
|
||||
/**
|
||||
* Determines the types of data converted to clickable URLs in text.
|
||||
*
|
||||
* See https://facebook.github.io/react-native/docs/text.html#dataDetectorType
|
||||
*/
|
||||
dataDetectorType: PropTypes.oneOf(DataDetectorTypes),
|
||||
};
|
||||
|
||||
@@ -158,6 +158,8 @@ export type TextProps = $ReadOnly<{|
|
||||
*/
|
||||
selectionColor?: ?string,
|
||||
|
||||
dataDetectorType?: ?('phoneNumber' | 'link' | 'email' | 'none' | 'all'),
|
||||
|
||||
/**
|
||||
* Set text break strategy on Android.
|
||||
*
|
||||
|
||||
@@ -623,6 +623,19 @@ class TextExample extends React.Component<{}> {
|
||||
<RNTesterBlock title="Substring Emoji (should only see 'test')">
|
||||
<Text>{'test🙃'.substring(0, 5)}</Text>
|
||||
</RNTesterBlock>
|
||||
<RNTesterBlock title="Text linkify">
|
||||
<Text dataDetectorType="phoneNumber">Phone number: 123-123-1234</Text>
|
||||
<Text dataDetectorType="link">Link: https://www.facebook.com</Text>
|
||||
<Text dataDetectorType="email">Email: employee@facebook.com</Text>
|
||||
<Text dataDetectorType="none">
|
||||
Phone number: 123-123-1234 Link: https://www.facebook.com Email:
|
||||
employee@facebook.com
|
||||
</Text>
|
||||
<Text dataDetectorType="all">
|
||||
Phone number: 123-123-1234 Link: https://www.facebook.com Email:
|
||||
employee@facebook.com
|
||||
</Text>
|
||||
</RNTesterBlock>
|
||||
</RNTesterPage>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ package com.facebook.react.views.text;
|
||||
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
@@ -160,4 +161,26 @@ public abstract class ReactTextAnchorViewManager<T extends View, C extends React
|
||||
public void setDisabled(ReactTextView view, boolean disabled) {
|
||||
view.setEnabled(!disabled);
|
||||
}
|
||||
|
||||
@ReactProp(name = "dataDetectorType")
|
||||
public void setDataDetectorType(ReactTextView view, @Nullable String type) {
|
||||
switch (type) {
|
||||
case "phoneNumber":
|
||||
view.setLinkifyMask(Linkify.PHONE_NUMBERS);
|
||||
break;
|
||||
case "link":
|
||||
view.setLinkifyMask(Linkify.WEB_URLS);
|
||||
break;
|
||||
case "email":
|
||||
view.setLinkifyMask(Linkify.EMAIL_ADDRESSES);
|
||||
break;
|
||||
case "all":
|
||||
view.setLinkifyMask(Linkify.ALL);
|
||||
break;
|
||||
case "none":
|
||||
default:
|
||||
view.setLinkifyMask(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ import androidx.appcompat.widget.AppCompatTextView;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.Spanned;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.util.Linkify;
|
||||
import android.view.Gravity;
|
||||
import android.view.ViewGroup;
|
||||
import com.facebook.common.logging.FLog;
|
||||
@@ -35,6 +38,7 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
private int mTextAlign = Gravity.NO_GRAVITY;
|
||||
private int mNumberOfLines = ViewDefaults.NUMBER_OF_LINES;
|
||||
private TextUtils.TruncateAt mEllipsizeLocation = TextUtils.TruncateAt.END;
|
||||
private int mLinkifyMaskType = 0;
|
||||
|
||||
private ReactViewBackgroundManager mReactBackgroundManager;
|
||||
private Spannable mSpanned;
|
||||
@@ -55,7 +59,12 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
if (getLayoutParams() == null) {
|
||||
setLayoutParams(EMPTY_LAYOUT_PARAMS);
|
||||
}
|
||||
setText(update.getText());
|
||||
Spannable spannable = update.getText();
|
||||
if (mLinkifyMaskType > 0) {
|
||||
Linkify.addLinks(spannable, mLinkifyMaskType);
|
||||
setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
setText(spannable);
|
||||
setPadding(
|
||||
(int) Math.floor(update.getPaddingLeft()),
|
||||
(int) Math.floor(update.getPaddingTop()),
|
||||
@@ -276,4 +285,8 @@ public class ReactTextView extends AppCompatTextView implements ReactCompoundVie
|
||||
public Spannable getSpanned() {
|
||||
return mSpanned;
|
||||
}
|
||||
|
||||
public void setLinkifyMask(int mask) {
|
||||
mLinkifyMaskType = mask;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user