Add <Text> shadow support
Summary: Add three new TextStylePropTypes for \<Text> - textShadowOffset - textShadowRadius - textShadowColor Closes https://github.com/facebook/react-native/pull/4975 Reviewed By: svcscm Differential Revision: D2796278 Pulled By: nicklockwood fb-gh-sync-id: f8c3fa210e664428b029b9fba8eca4a8eb81c08d
This commit is contained in:
parent
718cd7953f
commit
4972cabaa5
|
@ -365,6 +365,11 @@ var TextExample = React.createClass({
|
|||
This text contains an inline image <Image source={require('./flux.png')}/>. Neat, huh?
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Text shadow">
|
||||
<Text style={{fontSize: 20, textShadowOffset: {width: 2, height: 2}, textShadowRadius: 1, textShadowColor: '#00cccc'}}>
|
||||
Demo text shadow
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
</UIExplorerPage>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -424,6 +424,17 @@ exports.examples = [
|
|||
</View>
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Text shadow',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text style={{fontSize: 20, textShadowOffset: {width: 2, height: 2}, textShadowRadius: 1, textShadowColor: '#00cccc'}}>
|
||||
Demo text shadow
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
}];
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
|
|
|
@ -46,5 +46,6 @@ ReactNativeStyleAttributes.color = colorAttributes;
|
|||
ReactNativeStyleAttributes.shadowColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.textDecorationColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.tintColor = colorAttributes;
|
||||
ReactNativeStyleAttributes.textShadowColor = colorAttributes;
|
||||
|
||||
module.exports = ReactNativeStyleAttributes;
|
||||
|
|
|
@ -33,6 +33,9 @@ extern NSString *const RCTReactTagAttributeName;
|
|||
@property (nonatomic, assign) CGFloat fontSizeMultiplier;
|
||||
@property (nonatomic, assign) BOOL allowFontScaling;
|
||||
@property (nonatomic, assign) CGFloat opacity;
|
||||
@property (nonatomic, assign) CGSize textShadowOffset;
|
||||
@property (nonatomic, assign) CGFloat textShadowRadius;
|
||||
@property (nonatomic, strong) UIColor *textShadowColor;
|
||||
|
||||
- (void)recomputeText;
|
||||
|
||||
|
|
|
@ -305,22 +305,31 @@ static css_dim_t RCTMeasure(void *context, float width, float height)
|
|||
}
|
||||
|
||||
// Text decoration
|
||||
if(_textDecorationLine == RCTTextDecorationLineTypeUnderline ||
|
||||
_textDecorationLine == RCTTextDecorationLineTypeUnderlineStrikethrough) {
|
||||
if (_textDecorationLine == RCTTextDecorationLineTypeUnderline ||
|
||||
_textDecorationLine == RCTTextDecorationLineTypeUnderlineStrikethrough) {
|
||||
[self _addAttribute:NSUnderlineStyleAttributeName withValue:@(_textDecorationStyle)
|
||||
toAttributedString:attributedString];
|
||||
}
|
||||
if(_textDecorationLine == RCTTextDecorationLineTypeStrikethrough ||
|
||||
_textDecorationLine == RCTTextDecorationLineTypeUnderlineStrikethrough){
|
||||
if (_textDecorationLine == RCTTextDecorationLineTypeStrikethrough ||
|
||||
_textDecorationLine == RCTTextDecorationLineTypeUnderlineStrikethrough){
|
||||
[self _addAttribute:NSStrikethroughStyleAttributeName withValue:@(_textDecorationStyle)
|
||||
toAttributedString:attributedString];
|
||||
}
|
||||
if(_textDecorationColor) {
|
||||
if (_textDecorationColor) {
|
||||
[self _addAttribute:NSStrikethroughColorAttributeName withValue:_textDecorationColor
|
||||
toAttributedString:attributedString];
|
||||
[self _addAttribute:NSUnderlineColorAttributeName withValue:_textDecorationColor
|
||||
toAttributedString:attributedString];
|
||||
}
|
||||
|
||||
// Text shadow
|
||||
if (!CGSizeEqualToSize(_textShadowOffset, CGSizeZero)) {
|
||||
NSShadow *shadow = [NSShadow new];
|
||||
shadow.shadowOffset = _textShadowOffset;
|
||||
shadow.shadowBlurRadius = _textShadowRadius;
|
||||
shadow.shadowColor = _textShadowColor;
|
||||
[self _addAttribute:NSShadowAttributeName withValue:shadow toAttributedString:attributedString];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)fillCSSNode:(css_node_t *)node
|
||||
|
@ -371,6 +380,9 @@ RCT_TEXT_PROPERTY(TextDecorationLine, _textDecorationLine, RCTTextDecorationLine
|
|||
RCT_TEXT_PROPERTY(TextDecorationStyle, _textDecorationStyle, NSUnderlineStyle);
|
||||
RCT_TEXT_PROPERTY(WritingDirection, _writingDirection, NSWritingDirection)
|
||||
RCT_TEXT_PROPERTY(Opacity, _opacity, CGFloat)
|
||||
RCT_TEXT_PROPERTY(TextShadowOffset, _textShadowOffset, CGSize);
|
||||
RCT_TEXT_PROPERTY(TextShadowRadius, _textShadowRadius, CGFloat);
|
||||
RCT_TEXT_PROPERTY(TextShadowColor, _textShadowColor, UIColor *);
|
||||
|
||||
- (void)setAllowFontScaling:(BOOL)allowFontScaling
|
||||
{
|
||||
|
|
|
@ -59,6 +59,9 @@ RCT_EXPORT_SHADOW_PROPERTY(textDecorationLine, RCTTextDecorationLineType)
|
|||
RCT_EXPORT_SHADOW_PROPERTY(writingDirection, NSWritingDirection)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(allowFontScaling, BOOL)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(opacity, CGFloat)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textShadowOffset, CGSize)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textShadowRadius, CGFloat)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textShadowColor, UIColor)
|
||||
|
||||
- (RCTViewManagerUIBlock)uiBlockToAmendWithShadowViewRegistry:(NSDictionary<NSNumber *, RCTShadowView *> *)shadowViewRegistry
|
||||
{
|
||||
|
|
|
@ -30,6 +30,11 @@ var TextStylePropTypes = Object.assign(Object.create(ViewStylePropTypes), {
|
|||
['normal' /*default*/, 'bold',
|
||||
'100', '200', '300', '400', '500', '600', '700', '800', '900']
|
||||
),
|
||||
textShadowOffset: ReactPropTypes.shape(
|
||||
{width: ReactPropTypes.number, height: ReactPropTypes.number}
|
||||
),
|
||||
textShadowRadius: ReactPropTypes.number,
|
||||
textShadowColor: ColorPropType,
|
||||
/**
|
||||
* @platform ios
|
||||
*/
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.facebook.csslayout.CSSConstants;
|
|||
import com.facebook.csslayout.CSSNode;
|
||||
import com.facebook.csslayout.MeasureOutput;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.uimanager.IllegalViewOperationException;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
|
@ -63,6 +64,11 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
|||
@VisibleForTesting
|
||||
public static final String PROP_TEXT = "text";
|
||||
|
||||
public static final String PROP_SHADOW_OFFSET = "textShadowOffset";
|
||||
public static final String PROP_SHADOW_RADIUS = "textShadowRadius";
|
||||
public static final String PROP_SHADOW_COLOR = "textShadowColor";
|
||||
public static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000;
|
||||
|
||||
private static final TextPaint sTextPaintInstance = new TextPaint();
|
||||
|
||||
static {
|
||||
|
@ -114,8 +120,7 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
|||
ops.add(new SetSpanOperation(start, end, new ForegroundColorSpan(textCSSNode.mColor)));
|
||||
}
|
||||
if (textCSSNode.mIsBackgroundColorSet) {
|
||||
ops.add(
|
||||
new SetSpanOperation(
|
||||
ops.add(new SetSpanOperation(
|
||||
start,
|
||||
end,
|
||||
new BackgroundColorSpan(textCSSNode.mBackgroundColor)));
|
||||
|
@ -135,6 +140,16 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
|||
textCSSNode.mFontFamily,
|
||||
textCSSNode.getThemedContext().getAssets())));
|
||||
}
|
||||
if (textCSSNode.mTextShadowOffsetDx != 0 || textCSSNode.mTextShadowOffsetDy != 0) {
|
||||
ops.add(new SetSpanOperation(
|
||||
start,
|
||||
end,
|
||||
new ShadowStyleSpan(
|
||||
textCSSNode.mTextShadowOffsetDx,
|
||||
textCSSNode.mTextShadowOffsetDy,
|
||||
textCSSNode.mTextShadowRadius,
|
||||
textCSSNode.mTextShadowColor)));
|
||||
}
|
||||
ops.add(new SetSpanOperation(start, end, new ReactTagSpan(textCSSNode.getReactTag())));
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +294,11 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
|||
protected int mNumberOfLines = UNSET;
|
||||
protected int mFontSize = UNSET;
|
||||
|
||||
private float mTextShadowOffsetDx = 0;
|
||||
private float mTextShadowOffsetDy = 0;
|
||||
private float mTextShadowRadius = 1;
|
||||
private int mTextShadowColor = DEFAULT_TEXT_SHADOW_COLOR;
|
||||
|
||||
/**
|
||||
* mFontStyle can be {@link Typeface#NORMAL} or {@link Typeface#ITALIC}.
|
||||
* mFontWeight can be {@link Typeface#NORMAL} or {@link Typeface#BOLD}.
|
||||
|
@ -413,6 +433,34 @@ public class ReactTextShadowNode extends LayoutShadowNode {
|
|||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_SHADOW_OFFSET)
|
||||
public void setTextShadowOffset(ReadableMap offsetMap) {
|
||||
if (offsetMap == null) {
|
||||
mTextShadowOffsetDx = 0;
|
||||
mTextShadowOffsetDy = 0;
|
||||
} else {
|
||||
mTextShadowOffsetDx = PixelUtil.toPixelFromDIP(offsetMap.getDouble("width"));
|
||||
mTextShadowOffsetDy = PixelUtil.toPixelFromDIP(offsetMap.getDouble("height"));
|
||||
}
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_SHADOW_RADIUS, defaultInt = 1)
|
||||
public void setTextShadowRadius(float textShadowRadius) {
|
||||
if (textShadowRadius != mTextShadowRadius) {
|
||||
mTextShadowRadius = textShadowRadius;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_SHADOW_COLOR, defaultInt = DEFAULT_TEXT_SHADOW_COLOR, customType = "Color")
|
||||
public void setTextShadowColor(int textShadowColor) {
|
||||
if (textShadowColor != mTextShadowColor) {
|
||||
mTextShadowColor = textShadowColor;
|
||||
markUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAnchor() {
|
||||
return !mIsVirtual;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.text;
|
||||
|
||||
|
||||
import android.text.TextPaint;
|
||||
import android.text.style.CharacterStyle;
|
||||
|
||||
public class ShadowStyleSpan extends CharacterStyle {
|
||||
private final float mDx, mDy, mRadius;
|
||||
private final int mColor;
|
||||
|
||||
public ShadowStyleSpan(float dx, float dy, float radius, int color) {
|
||||
mDx = dx;
|
||||
mDy = dy;
|
||||
mRadius = radius;
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDrawState(TextPaint textPaint) {
|
||||
textPaint.setShadowLayer(mRadius, mDx, mDy, mColor);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue