Skip to content
Permalink
Browse files

line break mode for ios

Summary:
What do you think is ```lineBreakMode``` a good name? For android it is called ```ellipsize```.

<img src="https://cloud.githubusercontent.com/assets/1488195/15628555/7372f8d0-250c-11e6-8919-722f28a38d60.png"" width="300" />
Closes #7819

Differential Revision: D3417256

fbshipit-source-id: 189441a23ff554bf7f6d67fa8510959351e9e5cc
  • Loading branch information...
skv-headless authored and Facebook Github Bot 3 committed Jun 10, 2016
1 parent 33dfc9d commit c03b166854af21cdb2341a216208a1f3cd46fdef
@@ -388,6 +388,17 @@ var TextExample = React.createClass({
Demo text shadow
</Text>
</UIExplorerBlock>
<UIExplorerBlock title="Line break mode">
<Text numberOfLines={1}>
This very long text should be truncated with dots in the end.
</Text>
<Text lineBreakMode="middle" numberOfLines={1}>
This very long text should be truncated with dots in the middle.
</Text>
<Text lineBreakMode="head" numberOfLines={1}>
This very long text should be truncated with dots in the beginning.
</Text>
</UIExplorerBlock>
</UIExplorerPage>
);
}
@@ -444,6 +444,26 @@ exports.examples = [
</View>
);
},
}, {
title: 'Line break mode',
render: function() {
return (
<View>
<Text numberOfLines={1}>
This very long text should be truncated with dots in the end.
</Text>
<Text lineBreakMode="middle" numberOfLines={1}>
This very long text should be truncated with dots in the middle.
</Text>
<Text lineBreakMode="head" numberOfLines={1}>
This very long text should be truncated with dots in the beginning.
</Text>
<Text lineBreakMode="clip" numberOfLines={1}>
This very looooooooooooooooooooooooooooong text should be clipped.
</Text>
</View>
);
},
}];

var styles = StyleSheet.create({
@@ -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;
@@ -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 @@ - (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(css_measur

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 @@ - (void)set##setProp:(type)value; \
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);
@@ -64,6 +64,7 @@ - (RCTShadowView *)shadowView
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)
@@ -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 {
@@ -248,13 +248,11 @@ + (NSDate *)NSDate:(id)json
}

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),
@@ -67,6 +67,7 @@
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";
@@ -73,6 +73,21 @@ public void setTextAlign(ReactTextView view, @Nullable String textAlign) {
}
}

@ReactProp(name = ViewProps.LINE_BREAK_MODE)
public void setLineBreakMode(ReactTextView view, @Nullable String lineBreakMode) {
if(lineBreakMode == null) {
return;
}

if (lineBreakMode.equals("head")) {
view.setEllipsize(TextUtils.TruncateAt.START);
} else if (lineBreakMode.equals("middle")) {
view.setEllipsize(TextUtils.TruncateAt.MIDDLE);
} else if (lineBreakMode.equals("tail")) {
view.setEllipsize(TextUtils.TruncateAt.END);
}
}

@ReactProp(name = ViewProps.TEXT_ALIGN_VERTICAL)
public void setTextAlignVertical(ReactTextView view, @Nullable String textAlignVertical) {
if (textAlignVertical == null || "auto".equals(textAlignVertical)) {

4 comments on commit c03b166

@satya164

This comment has been minimized.

Copy link
Collaborator

replied Jun 21, 2016

IMO it should be called ellipsizeMode as it decides where the ellipsis is placed. It doesn't really deal with where the line is broken.

@kolking

This comment has been minimized.

Copy link

replied Jul 22, 2016

lineBreakMode is a bad name for this prop, that's for sure.

@satya164

This comment has been minimized.

Copy link
Collaborator

replied Jul 22, 2016

@kolking wanna send a PR with the new name? We could show a warning for old prop, and eventually deprecate it.

@kolking

This comment has been minimized.

Copy link

replied Jul 22, 2016

@satya164 no, I would leave it to the author since he have initially asked for the community opinion. As for me, I think that your ellipsizeMode is a good name, but maybe ellipsisMode is a better one ;)

Please sign in to comment.
You can’t perform that action at this time.