diff --git a/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/MountableSpan.kt b/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/MountableSpan.kt new file mode 100644 index 0000000000..b5ae1a0a1d --- /dev/null +++ b/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/MountableSpan.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.facebook.rendercore.text + +import android.view.View + +/** + * A span interface that allows users to receive callbacks when the hosting [View] is mounted and + * unmounted so that it is possible to the component to get access to it.. + */ +interface MountableSpan { + + fun onMount(view: View) + + fun onUnmount(view: View) +} diff --git a/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/RCTextView.java b/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/RCTextView.java index f74447ef67..7759d37ade 100644 --- a/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/RCTextView.java +++ b/litho-rendercore-text/src/main/java/com/facebook/rendercore/text/RCTextView.java @@ -127,7 +127,7 @@ public void draw(Canvas canvas) { shouldRestore = true; } - final OnPrePostDrawSpan[] onPrePostDrawSpans = getOnPrePostDrawableSpans(); + final OnPrePostDrawSpan[] onPrePostDrawSpans = getOnPrePostDrawSpans(); if (onPrePostDrawSpans.length == 0) { drawLayout(canvas); } else { @@ -174,13 +174,20 @@ private void drawLayout(Canvas canvas) { mLayout.draw(canvas, getSelectionPath(), mHighlightPaint, 0); } - private OnPrePostDrawSpan[] getOnPrePostDrawableSpans() { + private OnPrePostDrawSpan[] getOnPrePostDrawSpans() { if (!(mText instanceof Spanned)) { return new OnPrePostDrawSpan[0]; } return ((Spanned) mText).getSpans(0, mText.length(), OnPrePostDrawSpan.class); } + private MountableSpan[] getMountableSpans() { + if (!(mText instanceof Spanned)) { + return new MountableSpan[0]; + } + return ((Spanned) mText).getSpans(0, mText.length(), MountableSpan.class); + } + public void mount(TextLayout textLayout) { final ColorStateList colorStateList = textLayout.textStyle.textColorStateList; mText = textLayout.processedText; @@ -231,6 +238,11 @@ public void mount(TextLayout textLayout) { if (textLayout.textStyle.accessibilityLabel != null) { setContentDescription(textLayout.textStyle.accessibilityLabel); } + + final MountableSpan[] mountableSpans = getMountableSpans(); + for (MountableSpan mountableSpan : mountableSpans) { + mountableSpan.onMount(this); + } invalidate(); } @@ -239,6 +251,10 @@ public boolean isTextTruncated() { } public void unmount() { + final MountableSpan[] mountableSpans = getMountableSpans(); + for (MountableSpan mountableSpan : mountableSpans) { + mountableSpan.onUnmount(this); + } // NULLSAFE_FIXME[Field Not Nullable] mText = null; // NULLSAFE_FIXME[Field Not Nullable]