From c03b166854af21cdb2341a216208a1f3cd46fdef Mon Sep 17 00:00:00 2001 From: Sokovikov Date: Fri, 10 Jun 2016 04:26:45 -0700 Subject: [PATCH] line break mode for ios Summary: What do you think is ```lineBreakMode``` a good name? For android it is called ```ellipsize```. Closes https://github.com/facebook/react-native/pull/7819 Differential Revision: D3417256 fbshipit-source-id: 189441a23ff554bf7f6d67fa8510959351e9e5cc --- Examples/UIExplorer/TextExample.android.js | 11 ++++++++++ Examples/UIExplorer/TextExample.ios.js | 20 +++++++++++++++++++ Libraries/Text/RCTShadowText.h | 1 + Libraries/Text/RCTShadowText.m | 10 +++++++++- Libraries/Text/RCTTextManager.m | 1 + Libraries/Text/Text.js | 7 +++++++ React/Base/RCTConvert.m | 12 +++++------ .../facebook/react/uimanager/ViewProps.java | 1 + .../views/text/ReactTextViewManager.java | 15 ++++++++++++++ 9 files changed, 70 insertions(+), 8 deletions(-) diff --git a/Examples/UIExplorer/TextExample.android.js b/Examples/UIExplorer/TextExample.android.js index 4d1f61b4f..c557162b7 100644 --- a/Examples/UIExplorer/TextExample.android.js +++ b/Examples/UIExplorer/TextExample.android.js @@ -388,6 +388,17 @@ var TextExample = React.createClass({ Demo text shadow + + + This very long text should be truncated with dots in the end. + + + This very long text should be truncated with dots in the middle. + + + This very long text should be truncated with dots in the beginning. + + ); } diff --git a/Examples/UIExplorer/TextExample.ios.js b/Examples/UIExplorer/TextExample.ios.js index 8c7b4ff86..3262aeed0 100644 --- a/Examples/UIExplorer/TextExample.ios.js +++ b/Examples/UIExplorer/TextExample.ios.js @@ -444,6 +444,26 @@ exports.examples = [ ); }, +}, { + title: 'Line break mode', + render: function() { + return ( + + + This very long text should be truncated with dots in the end. + + + This very long text should be truncated with dots in the middle. + + + This very long text should be truncated with dots in the beginning. + + + This very looooooooooooooooooooooooooooong text should be clipped. + + + ); + }, }]; var styles = StyleSheet.create({ diff --git a/Libraries/Text/RCTShadowText.h b/Libraries/Text/RCTShadowText.h index 5d793916b..ed0cc5d6a 100644 --- a/Libraries/Text/RCTShadowText.h +++ b/Libraries/Text/RCTShadowText.h @@ -24,6 +24,7 @@ extern NSString *const RCTReactTagAttributeName; @property (nonatomic, assign) CGFloat letterSpacing; @property (nonatomic, assign) CGFloat lineHeight; @property (nonatomic, assign) NSUInteger numberOfLines; +@property (nonatomic, assign) NSLineBreakMode lineBreakMode; @property (nonatomic, assign) CGSize shadowOffset; @property (nonatomic, assign) NSTextAlignment textAlign; @property (nonatomic, assign) NSWritingDirection writingDirection; diff --git a/Libraries/Text/RCTShadowText.m b/Libraries/Text/RCTShadowText.m index 72461db6e..b1a437668 100644 --- a/Libraries/Text/RCTShadowText.m +++ b/Libraries/Text/RCTShadowText.m @@ -17,6 +17,7 @@ #import "RCTShadowRawText.h" #import "RCTText.h" #import "RCTUtils.h" +#import "RCTConvert.h" NSString *const RCTShadowViewAttributeName = @"RCTShadowViewAttributeName"; NSString *const RCTIsHighlightedAttributeName = @"IsHighlightedAttributeName"; @@ -166,7 +167,13 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width NSTextContainer *textContainer = [NSTextContainer new]; textContainer.lineFragmentPadding = 0.0; - textContainer.lineBreakMode = _numberOfLines > 0 ? NSLineBreakByTruncatingTail : NSLineBreakByClipping; + + if (_numberOfLines > 0) { + textContainer.lineBreakMode = _lineBreakMode; + } else { + textContainer.lineBreakMode = NSLineBreakByClipping; + } + textContainer.maximumNumberOfLines = _numberOfLines; textContainer.size = (CGSize){widthMode == CSS_MEASURE_MODE_UNDEFINED ? CGFLOAT_MAX : width, CGFLOAT_MAX}; @@ -451,6 +458,7 @@ RCT_TEXT_PROPERTY(IsHighlighted, _isHighlighted, BOOL) RCT_TEXT_PROPERTY(LetterSpacing, _letterSpacing, CGFloat) RCT_TEXT_PROPERTY(LineHeight, _lineHeight, CGFloat) RCT_TEXT_PROPERTY(NumberOfLines, _numberOfLines, NSUInteger) +RCT_TEXT_PROPERTY(LineBreakMode, _lineBreakMode, NSLineBreakMode) RCT_TEXT_PROPERTY(TextAlign, _textAlign, NSTextAlignment) RCT_TEXT_PROPERTY(TextDecorationColor, _textDecorationColor, UIColor *); RCT_TEXT_PROPERTY(TextDecorationLine, _textDecorationLine, RCTTextDecorationLineType); diff --git a/Libraries/Text/RCTTextManager.m b/Libraries/Text/RCTTextManager.m index 9104ea72c..cc5149fe7 100644 --- a/Libraries/Text/RCTTextManager.m +++ b/Libraries/Text/RCTTextManager.m @@ -64,6 +64,7 @@ RCT_EXPORT_SHADOW_PROPERTY(isHighlighted, BOOL) RCT_EXPORT_SHADOW_PROPERTY(letterSpacing, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(lineHeight, CGFloat) RCT_EXPORT_SHADOW_PROPERTY(numberOfLines, NSUInteger) +RCT_EXPORT_SHADOW_PROPERTY(lineBreakMode, NSLineBreakMode) RCT_EXPORT_SHADOW_PROPERTY(textAlign, NSTextAlignment) RCT_EXPORT_SHADOW_PROPERTY(textDecorationStyle, NSUnderlineStyle) RCT_EXPORT_SHADOW_PROPERTY(textDecorationColor, UIColor) diff --git a/Libraries/Text/Text.js b/Libraries/Text/Text.js index 4da6d1d52..aab015b6b 100644 --- a/Libraries/Text/Text.js +++ b/Libraries/Text/Text.js @@ -29,6 +29,7 @@ const viewConfig = { validAttributes: merge(ReactNativeViewAttributes.UIView, { isHighlighted: true, numberOfLines: true, + lineBreakMode: true, allowFontScaling: true, }), uiViewClassName: 'RCTText', @@ -69,6 +70,11 @@ const viewConfig = { const Text = React.createClass({ propTypes: { + /** + * Line Break mode. Works only with numberOfLines. + * clip is working only for iOS + */ + lineBreakMode: React.PropTypes.oneOf(['head', 'middle', 'tail', 'clip']), /** * Used to truncate the text with an ellipsis after computing the text * layout, including line wrapping, such that the total number of lines @@ -110,6 +116,7 @@ const Text = React.createClass({ return { accessible: true, allowFontScaling: true, + lineBreakMode: 'tail', }; }, getInitialState: function(): Object { diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 917a5b627..6b3b2a5c5 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -248,13 +248,11 @@ NSNumber *RCTConvertMultiEnumValue(const char *typeName, NSDictionary *mapping, } RCT_ENUM_CONVERTER(NSLineBreakMode, (@{ - @"wordWrapping": @(NSLineBreakByWordWrapping), - @"charWrapping": @(NSLineBreakByCharWrapping), - @"clipping": @(NSLineBreakByClipping), - @"truncatingHead": @(NSLineBreakByTruncatingHead), - @"truncatingTail": @(NSLineBreakByTruncatingTail), - @"truncatingMiddle": @(NSLineBreakByTruncatingMiddle), -}), NSLineBreakByWordWrapping, integerValue) + @"clip": @(NSLineBreakByClipping), + @"head": @(NSLineBreakByTruncatingHead), + @"tail": @(NSLineBreakByTruncatingTail), + @"middle": @(NSLineBreakByTruncatingMiddle), +}), NSLineBreakByTruncatingTail, integerValue) RCT_ENUM_CONVERTER(NSTextAlignment, (@{ @"auto": @(NSTextAlignmentNatural), diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 38160e477..425167111 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -67,6 +67,7 @@ public class ViewProps { public static final String LINE_HEIGHT = "lineHeight"; public static final String NEEDS_OFFSCREEN_ALPHA_COMPOSITING = "needsOffscreenAlphaCompositing"; public static final String NUMBER_OF_LINES = "numberOfLines"; + public static final String LINE_BREAK_MODE = "lineBreakMode"; public static final String ON = "on"; public static final String RESIZE_MODE = "resizeMode"; public static final String TEXT_ALIGN = "textAlign"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java index 00595bb3a..eabbf7b62 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.java @@ -73,6 +73,21 @@ public class ReactTextViewManager extends BaseViewManager