Skip to content

Commit

Permalink
feat(android): support opacity for rich text (#3615)
Browse files Browse the repository at this point in the history
  • Loading branch information
iPel authored Nov 24, 2023
1 parent bb9b7db commit fe9feda
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
String ARRAY = "array";
String MAP = "map";

String name() default "name";
String name();

/*
* defaultType Number boolean string else default is do not check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,27 @@ private static void initComponentPropsMap() {
HippyControllerProps controllerProps = method
.getAnnotation(HippyControllerProps.class);
if (controllerProps != null) {
if (!sComponentPropsMethodMap.containsKey(controllerProps.name())) {
sTextPropsSet.add(controllerProps.name());
String name = controllerProps.name();
if (!isComponentProps(name)) {
sTextPropsSet.add(name);
}
sRenderPropsList.add(controllerProps.name());
sRenderPropsList.add(name);
}
}
Collections.addAll(sRenderPropsList, sLayoutStyleList);
}

private static boolean isComponentProps(String name) {
if (sComponentPropsMethodMap.containsKey(name)) {
return true;
}
// Special case: property "opacity" in TextVirtualNode also need to process in HippyViewController
if (NodeProps.OPACITY.equals(name)) {
return true;
}
return false;
}

void findViewPropsMethod(Class<?> cls,
@NonNull Map<String, PropertyMethodHolder> methodHolderMap) {
if (cls != HippyViewController.class) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public class TextImageSpan extends ImageSpan {
@Nullable
private Paint mBackgroundPaint = null;
private int mTintColor;
private final int mAlpha;

public TextImageSpan(Drawable drawable, String source, @NonNull ImageVirtualNode node,
@NonNull NativeRender nativeRenderer) {
Expand All @@ -123,6 +124,8 @@ public TextImageSpan(Drawable drawable, String source, @NonNull ImageVirtualNode
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(node.getBackgroundColor());
}
// multiple alpha bits (0xFF) to convert opacity into alpha
mAlpha = Math.round(node.getFinalOpacity() * 255);
setUrl(source);
}

Expand Down Expand Up @@ -177,7 +180,7 @@ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end,
if (mMeasuredWidth == 0 || mMeasuredHeight == 0) {
return;
}
canvas.save();
int count = canvas.save();
int transY;
assert mVerticalAlign != null;
switch (mVerticalAlign) {
Expand All @@ -197,6 +200,9 @@ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end,
}

canvas.translate(x + mMarginLeft, transY);
if (mAlpha < 255) {
canvas.saveLayerAlpha(0, 0, mMeasuredWidth, mMeasuredHeight, mAlpha);
}
if (mBackgroundPaint != null) {
canvas.drawRect(0, 0, mMeasuredWidth, mMeasuredHeight, mBackgroundPaint);
}
Expand All @@ -215,7 +221,7 @@ public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end,
canvas.scale(scaleX, scaleY, 0, 0);
drawable.draw(canvas);
}
canvas.restore();
canvas.restoreToCount(count);
}

private void legacyDraw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ public void setVerticalAlign(String align) {
markDirty();
}

@HippyControllerProps(name = NodeProps.OPACITY, defaultType = HippyControllerProps.NUMBER, defaultNumber = 1f)
public void setOpacity(float opacity) {
super.setOpacity(opacity);
}

@SuppressWarnings("unused")
@HippyControllerProps(name = "defaultSource", defaultType = HippyControllerProps.STRING)
public void setDefaultSource(String defaultSource) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ protected void createChildrenSpanOperation(@NonNull List<SpanOperation> ops,
}
}

protected TextForegroundColorSpan createForegroundColorSpan() {
return new TextForegroundColorSpan(mColor);
protected TextForegroundColorSpan createForegroundColorSpan(float opacity) {
return new TextForegroundColorSpan(colorWithOpacity(mColor, opacity));
}

protected void createSpanOperationImpl(@NonNull List<SpanOperation> ops,
Expand All @@ -416,9 +416,13 @@ protected void createSpanOperationImpl(@NonNull List<SpanOperation> ops,
TextVerticalAlignSpan span = new TextVerticalAlignSpan(verticalAlign);
ops.add(new SpanOperation(start, end, span, SpanOperation.PRIORITY_LOWEST));
}
ops.add(new SpanOperation(start, end, createForegroundColorSpan()));
float opacity = getFinalOpacity();
ops.add(new SpanOperation(start, end, createForegroundColorSpan(opacity)));
if (mBackgroundColor != Color.TRANSPARENT && mParent != null) {
ops.add(new SpanOperation(start, end, new BackgroundColorSpan(mBackgroundColor)));
int color = colorWithOpacity(mBackgroundColor, opacity);
if (color != Color.TRANSPARENT) {
ops.add(new SpanOperation(start, end, new BackgroundColorSpan(color)));
}
}
if (mLetterSpacing != 0) {
ops.add(new SpanOperation(start, end,
Expand All @@ -437,9 +441,11 @@ protected void createSpanOperationImpl(@NonNull List<SpanOperation> ops,
ops.add(new SpanOperation(start, end, new StrikethroughSpan()));
}
if (mShadowOffsetDx != 0 || mShadowOffsetDy != 0) {
ops.add(new SpanOperation(start, end,
new TextShadowSpan(mShadowOffsetDx, mShadowOffsetDy, mShadowRadius,
mShadowColor)));
int color = colorWithOpacity(mShadowColor, opacity);
if (color != Color.TRANSPARENT) {
ops.add(new SpanOperation(start, end,
new TextShadowSpan(mShadowOffsetDx, mShadowOffsetDy, mShadowRadius, color)));
}
}
if (mEventTypes != null && mEventTypes.size() > 0) {
TextGestureSpan span = new TextGestureSpan(mId);
Expand All @@ -463,6 +469,16 @@ protected void createSpanOperationImpl(@NonNull List<SpanOperation> ops,
}
}

public static int colorWithOpacity(int color, float opacity) {
if (opacity >= 1) {
return color;
} else if (opacity > 0) {
int alpha = (color >> 24) & 0xFF;
return (Math.round(alpha * opacity) << 24) | (color & 0xFFFFFF);
}
return Color.TRANSPARENT;
}

protected float getLineSpacingMultiplier() {
return mLineSpacingMultiplier <= 0 ? 1.0f : mLineSpacingMultiplier;
}
Expand Down Expand Up @@ -781,4 +797,13 @@ public String getVerticalAlign() {
}
return null;
}

@HippyControllerProps(name = NodeProps.OPACITY, defaultType = HippyControllerProps.NUMBER, defaultNumber = 1f)
public void setOpacity(float opacity) {
// top-level opacity will be handled by HippyViewController, so only sub-level opacity needs to be considered
if (mParent != null) {
super.setOpacity(opacity);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public abstract class VirtualNode {
protected VirtualNode mParent;
@Nullable
protected List<String> mEventTypes;
protected float mOpacity = 1f;

public VirtualNode(int rootId, int id, int pid, int index) {
mRootId = rootId;
Expand Down Expand Up @@ -137,6 +138,18 @@ public int getChildCount() {
return mChildren.size();
}

public void setOpacity(float opacity) {
opacity = Math.min(Math.max(0, opacity), 1);
if (opacity != mOpacity) {
mOpacity = opacity;
markDirty();
}
}

public float getFinalOpacity() {
return mParent == null ? mOpacity : mParent.getFinalOpacity() * mOpacity;
}

protected static class SpanOperation {

public static final int PRIORITY_DEFAULT = 1;
Expand Down

0 comments on commit fe9feda

Please sign in to comment.