mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Kotlinify ReactScrollViewManager
Summary: ## Changelog: [Android] [Internal] - As in the title Reviewed By: cortinico Differential Revision: D72971263 fbshipit-source-id: 8bd0c4e29e48f7e3d47a97f1a4e988e7b0282646
This commit is contained in:
committed by
Facebook GitHub Bot
parent
e0a506fac3
commit
44c274ae6e
@@ -6218,10 +6218,11 @@ public abstract interface class com/facebook/react/views/scroll/ReactScrollViewH
|
||||
}
|
||||
|
||||
public class com/facebook/react/views/scroll/ReactScrollViewManager : com/facebook/react/uimanager/ViewGroupManager, com/facebook/react/views/scroll/ReactScrollViewCommandHelper$ScrollCommandHandler {
|
||||
public static final field Companion Lcom/facebook/react/views/scroll/ReactScrollViewManager$Companion;
|
||||
public static final field REACT_CLASS Ljava/lang/String;
|
||||
public fun <init> ()V
|
||||
public fun <init> (Lcom/facebook/react/views/scroll/FpsListener;)V
|
||||
public static fun createExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
|
||||
public synthetic fun <init> (Lcom/facebook/react/views/scroll/FpsListener;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public synthetic fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Landroid/view/View;
|
||||
public fun createViewInstance (Lcom/facebook/react/uimanager/ThemedReactContext;)Lcom/facebook/react/views/scroll/ReactScrollView;
|
||||
public fun flashScrollIndicators (Lcom/facebook/react/views/scroll/ReactScrollView;)V
|
||||
@@ -6237,39 +6238,43 @@ public class com/facebook/react/views/scroll/ReactScrollViewManager : com/facebo
|
||||
public synthetic fun scrollTo (Ljava/lang/Object;Lcom/facebook/react/views/scroll/ReactScrollViewCommandHelper$ScrollToCommandData;)V
|
||||
public fun scrollToEnd (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/views/scroll/ReactScrollViewCommandHelper$ScrollToEndCommandData;)V
|
||||
public synthetic fun scrollToEnd (Ljava/lang/Object;Lcom/facebook/react/views/scroll/ReactScrollViewCommandHelper$ScrollToEndCommandData;)V
|
||||
public fun setBorderColor (Lcom/facebook/react/views/scroll/ReactScrollView;ILjava/lang/Integer;)V
|
||||
public fun setBorderRadius (Lcom/facebook/react/views/scroll/ReactScrollView;IF)V
|
||||
public fun setBorderStyle (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public fun setBorderWidth (Lcom/facebook/react/views/scroll/ReactScrollView;IF)V
|
||||
public fun setBottomFillColor (Lcom/facebook/react/views/scroll/ReactScrollView;I)V
|
||||
public fun setContentOffset (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/bridge/ReadableMap;)V
|
||||
public fun setDecelerationRate (Lcom/facebook/react/views/scroll/ReactScrollView;F)V
|
||||
public fun setDisableIntervalMomentum (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setFadingEdgeLength (Lcom/facebook/react/views/scroll/ReactScrollView;I)V
|
||||
public fun setHorizontal (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setIsInvertedVirtualizedList (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setMaintainVisibleContentPosition (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/bridge/ReadableMap;)V
|
||||
public fun setNestedScrollEnabled (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setBorderColor (Lcom/facebook/react/views/scroll/ReactScrollView;ILjava/lang/Integer;)V
|
||||
public final fun setBorderRadius (Lcom/facebook/react/views/scroll/ReactScrollView;IF)V
|
||||
public final fun setBorderStyle (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public final fun setBorderWidth (Lcom/facebook/react/views/scroll/ReactScrollView;IF)V
|
||||
public final fun setBottomFillColor (Lcom/facebook/react/views/scroll/ReactScrollView;I)V
|
||||
public final fun setContentOffset (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/bridge/ReadableMap;)V
|
||||
public final fun setDecelerationRate (Lcom/facebook/react/views/scroll/ReactScrollView;F)V
|
||||
public final fun setDisableIntervalMomentum (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setFadingEdgeLength (Lcom/facebook/react/views/scroll/ReactScrollView;I)V
|
||||
public final fun setHorizontal (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setIsInvertedVirtualizedList (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setMaintainVisibleContentPosition (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/bridge/ReadableMap;)V
|
||||
public final fun setNestedScrollEnabled (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setOverScrollMode (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public fun setOverflow (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public fun setPagingEnabled (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setPersistentScrollbar (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setPointerEvents (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public fun setRemoveClippedSubviews (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setScrollEnabled (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setScrollEventThrottle (Lcom/facebook/react/views/scroll/ReactScrollView;I)V
|
||||
public fun setScrollPerfTag (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public fun setSendMomentumEvents (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setShowsVerticalScrollIndicator (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setSnapToAlignment (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public fun setSnapToEnd (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public fun setSnapToInterval (Lcom/facebook/react/views/scroll/ReactScrollView;F)V
|
||||
public fun setSnapToOffsets (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public fun setSnapToStart (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setOverflow (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public final fun setPagingEnabled (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setPersistentScrollbar (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setPointerEvents (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public final fun setRemoveClippedSubviews (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setScrollEnabled (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setScrollEventThrottle (Lcom/facebook/react/views/scroll/ReactScrollView;I)V
|
||||
public final fun setScrollPerfTag (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public final fun setSendMomentumEvents (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setShowsVerticalScrollIndicator (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setSnapToAlignment (Lcom/facebook/react/views/scroll/ReactScrollView;Ljava/lang/String;)V
|
||||
public final fun setSnapToEnd (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public final fun setSnapToInterval (Lcom/facebook/react/views/scroll/ReactScrollView;F)V
|
||||
public final fun setSnapToOffsets (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/bridge/ReadableArray;)V
|
||||
public final fun setSnapToStart (Lcom/facebook/react/views/scroll/ReactScrollView;Z)V
|
||||
public synthetic fun updateState (Landroid/view/View;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Ljava/lang/Object;
|
||||
public fun updateState (Lcom/facebook/react/views/scroll/ReactScrollView;Lcom/facebook/react/uimanager/ReactStylesDiffMap;Lcom/facebook/react/uimanager/StateWrapper;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/views/scroll/ReactScrollViewManager$Companion {
|
||||
public final fun createExportedCustomDirectEventTypeConstants ()Ljava/util/Map;
|
||||
}
|
||||
|
||||
public final class com/facebook/react/views/scroll/ScrollEvent : com/facebook/react/uimanager/events/Event {
|
||||
public static final field Companion Lcom/facebook/react/views/scroll/ScrollEvent$Companion;
|
||||
public fun canCoalesce ()Z
|
||||
@@ -6996,4 +7001,3 @@ public class com/facebook/react/views/view/ReactViewManager : com/facebook/react
|
||||
|
||||
public final class com/facebook/react/views/view/ReactViewManager$Companion {
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1111,7 +1111,7 @@ public class ReactScrollView extends ScrollView
|
||||
}
|
||||
}
|
||||
|
||||
public void setContentOffset(ReadableMap value) {
|
||||
public void setContentOffset(@Nullable ReadableMap value) {
|
||||
// When contentOffset={{x:0,y:0}} with lazy load items, setContentOffset
|
||||
// is repeatedly called, causing an unexpected scroll to top behavior.
|
||||
// Avoid updating contentOffset if the value has not changed.
|
||||
|
||||
-409
@@ -1,409 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.scroll;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import com.facebook.infer.annotation.Nullsafe;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.RetryableMountingLayerException;
|
||||
import com.facebook.react.common.MapBuilder;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator;
|
||||
import com.facebook.react.uimanager.LengthPercentage;
|
||||
import com.facebook.react.uimanager.LengthPercentageType;
|
||||
import com.facebook.react.uimanager.PixelUtil;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.Spacing;
|
||||
import com.facebook.react.uimanager.StateWrapper;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
import com.facebook.react.uimanager.ViewProps;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.annotations.ReactPropGroup;
|
||||
import com.facebook.react.uimanager.style.BorderRadiusProp;
|
||||
import com.facebook.react.uimanager.style.BorderStyle;
|
||||
import com.facebook.react.uimanager.style.LogicalEdge;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* View manager for {@link ReactScrollView} components.
|
||||
*
|
||||
* <p>Note that {@link ReactScrollView} and {@link ReactHorizontalScrollView} are exposed to JS as a
|
||||
* single ScrollView component, configured via the {@code horizontal} boolean property.
|
||||
*/
|
||||
@Nullsafe(Nullsafe.Mode.LOCAL)
|
||||
@ReactModule(name = ReactScrollViewManager.REACT_CLASS)
|
||||
public class ReactScrollViewManager extends ViewGroupManager<ReactScrollView>
|
||||
implements ReactScrollViewCommandHelper.ScrollCommandHandler<ReactScrollView> {
|
||||
|
||||
public static final String REACT_CLASS = "RCTScrollView";
|
||||
|
||||
private static final int[] SPACING_TYPES = {
|
||||
Spacing.ALL, Spacing.LEFT, Spacing.RIGHT, Spacing.TOP, Spacing.BOTTOM,
|
||||
};
|
||||
|
||||
private @Nullable FpsListener mFpsListener = null;
|
||||
|
||||
public ReactScrollViewManager() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public ReactScrollViewManager(@Nullable FpsListener fpsListener) {
|
||||
mFpsListener = fpsListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return REACT_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactScrollView createViewInstance(ThemedReactContext context) {
|
||||
return new ReactScrollView(context, mFpsListener);
|
||||
}
|
||||
|
||||
@ReactProp(name = "scrollEnabled", defaultBoolean = true)
|
||||
public void setScrollEnabled(ReactScrollView view, boolean value) {
|
||||
view.setScrollEnabled(value);
|
||||
|
||||
// Set focusable to match whether scroll is enabled. This improves keyboarding
|
||||
// experience by not making scrollview a tab stop when you cannot interact with it.
|
||||
view.setFocusable(value);
|
||||
}
|
||||
|
||||
@ReactProp(name = "showsVerticalScrollIndicator", defaultBoolean = true)
|
||||
public void setShowsVerticalScrollIndicator(ReactScrollView view, boolean value) {
|
||||
view.setVerticalScrollBarEnabled(value);
|
||||
}
|
||||
|
||||
@ReactProp(name = "decelerationRate")
|
||||
public void setDecelerationRate(ReactScrollView view, float decelerationRate) {
|
||||
view.setDecelerationRate(decelerationRate);
|
||||
}
|
||||
|
||||
@ReactProp(name = "disableIntervalMomentum")
|
||||
public void setDisableIntervalMomentum(ReactScrollView view, boolean disableIntervalMomentum) {
|
||||
view.setDisableIntervalMomentum(disableIntervalMomentum);
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToInterval")
|
||||
public void setSnapToInterval(ReactScrollView view, float snapToInterval) {
|
||||
// snapToInterval needs to be exposed as a float because of the Javascript interface.
|
||||
float density = PixelUtil.getDisplayMetricDensity();
|
||||
view.setSnapInterval((int) (snapToInterval * density));
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToOffsets")
|
||||
public void setSnapToOffsets(ReactScrollView view, @Nullable ReadableArray snapToOffsets) {
|
||||
if (snapToOffsets == null || snapToOffsets.size() == 0) {
|
||||
view.setSnapOffsets(null);
|
||||
return;
|
||||
}
|
||||
|
||||
float density = PixelUtil.getDisplayMetricDensity();
|
||||
List<Integer> offsets = new ArrayList<Integer>();
|
||||
for (int i = 0; i < snapToOffsets.size(); i++) {
|
||||
offsets.add((int) (snapToOffsets.getDouble(i) * density));
|
||||
}
|
||||
view.setSnapOffsets(offsets);
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToAlignment")
|
||||
public void setSnapToAlignment(ReactScrollView view, @Nullable String alignment) {
|
||||
view.setSnapToAlignment(ReactScrollViewHelper.parseSnapToAlignment(alignment));
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToStart")
|
||||
public void setSnapToStart(ReactScrollView view, boolean snapToStart) {
|
||||
view.setSnapToStart(snapToStart);
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToEnd")
|
||||
public void setSnapToEnd(ReactScrollView view, boolean snapToEnd) {
|
||||
view.setSnapToEnd(snapToEnd);
|
||||
}
|
||||
|
||||
@ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
|
||||
public void setRemoveClippedSubviews(ReactScrollView view, boolean removeClippedSubviews) {
|
||||
view.setRemoveClippedSubviews(removeClippedSubviews);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computing momentum events is potentially expensive since we post a runnable on the UI thread to
|
||||
* see when it is done. We only do that if {@param sendMomentumEvents} is set to true. This is
|
||||
* handled automatically in js by checking if there is a listener on the momentum events.
|
||||
*
|
||||
* @param view
|
||||
* @param sendMomentumEvents
|
||||
*/
|
||||
@ReactProp(name = "sendMomentumEvents")
|
||||
public void setSendMomentumEvents(ReactScrollView view, boolean sendMomentumEvents) {
|
||||
view.setSendMomentumEvents(sendMomentumEvents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag used for logging scroll performance on this scroll view. Will force momentum events to be
|
||||
* turned on (see setSendMomentumEvents).
|
||||
*
|
||||
* @param view
|
||||
* @param scrollPerfTag
|
||||
*/
|
||||
@ReactProp(name = "scrollPerfTag")
|
||||
public void setScrollPerfTag(ReactScrollView view, @Nullable String scrollPerfTag) {
|
||||
view.setScrollPerfTag(scrollPerfTag);
|
||||
}
|
||||
|
||||
@ReactProp(name = "pagingEnabled")
|
||||
public void setPagingEnabled(ReactScrollView view, boolean pagingEnabled) {
|
||||
view.setPagingEnabled(pagingEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* When set, fills the rest of the scrollview with a color to avoid setting a background and
|
||||
* creating unnecessary overdraw.
|
||||
*
|
||||
* @param view
|
||||
* @param color
|
||||
*/
|
||||
@ReactProp(name = "endFillColor", defaultInt = Color.TRANSPARENT, customType = "Color")
|
||||
public void setBottomFillColor(ReactScrollView view, int color) {
|
||||
view.setEndFillColor(color);
|
||||
}
|
||||
|
||||
/** Controls overScroll behaviour */
|
||||
@ReactProp(name = "overScrollMode")
|
||||
public void setOverScrollMode(ReactScrollView view, @Nullable String value) {
|
||||
view.setOverScrollMode(ReactScrollViewHelper.parseOverScrollMode(value));
|
||||
}
|
||||
|
||||
@ReactProp(name = "nestedScrollEnabled")
|
||||
public void setNestedScrollEnabled(ReactScrollView view, boolean value) {
|
||||
ViewCompat.setNestedScrollingEnabled(view, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Integer> getCommandsMap() {
|
||||
return ReactScrollViewCommandHelper.getCommandsMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveCommand(
|
||||
ReactScrollView scrollView, int commandId, @Nullable ReadableArray args) {
|
||||
ReactScrollViewCommandHelper.receiveCommand(this, scrollView, commandId, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveCommand(
|
||||
ReactScrollView scrollView, String commandId, @Nullable ReadableArray args) {
|
||||
ReactScrollViewCommandHelper.receiveCommand(this, scrollView, commandId, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flashScrollIndicators(ReactScrollView scrollView) {
|
||||
scrollView.flashScrollIndicators();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollTo(
|
||||
ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToCommandData data) {
|
||||
scrollView.abortAnimation();
|
||||
if (data.mAnimated) {
|
||||
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY);
|
||||
} else {
|
||||
scrollView.scrollTo(data.mDestX, data.mDestY);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactPropGroup(
|
||||
names = {
|
||||
ViewProps.BORDER_RADIUS,
|
||||
ViewProps.BORDER_TOP_LEFT_RADIUS,
|
||||
ViewProps.BORDER_TOP_RIGHT_RADIUS,
|
||||
ViewProps.BORDER_BOTTOM_RIGHT_RADIUS,
|
||||
ViewProps.BORDER_BOTTOM_LEFT_RADIUS
|
||||
},
|
||||
defaultFloat = Float.NaN)
|
||||
public void setBorderRadius(ReactScrollView view, int index, float borderRadius) {
|
||||
@Nullable
|
||||
LengthPercentage radius =
|
||||
Float.isNaN(borderRadius)
|
||||
? null
|
||||
: new LengthPercentage(borderRadius, LengthPercentageType.POINT);
|
||||
BackgroundStyleApplicator.setBorderRadius(view, BorderRadiusProp.values()[index], radius);
|
||||
}
|
||||
|
||||
@ReactProp(name = "borderStyle")
|
||||
public void setBorderStyle(ReactScrollView view, @Nullable String borderStyle) {
|
||||
@Nullable
|
||||
BorderStyle parsedBorderStyle =
|
||||
borderStyle == null ? null : BorderStyle.fromString(borderStyle);
|
||||
BackgroundStyleApplicator.setBorderStyle(view, parsedBorderStyle);
|
||||
}
|
||||
|
||||
@ReactPropGroup(
|
||||
names = {
|
||||
ViewProps.BORDER_WIDTH,
|
||||
ViewProps.BORDER_LEFT_WIDTH,
|
||||
ViewProps.BORDER_RIGHT_WIDTH,
|
||||
ViewProps.BORDER_TOP_WIDTH,
|
||||
ViewProps.BORDER_BOTTOM_WIDTH,
|
||||
},
|
||||
defaultFloat = Float.NaN)
|
||||
public void setBorderWidth(ReactScrollView view, int index, float width) {
|
||||
BackgroundStyleApplicator.setBorderWidth(view, LogicalEdge.values()[index], width);
|
||||
}
|
||||
|
||||
@ReactPropGroup(
|
||||
names = {
|
||||
"borderColor",
|
||||
"borderLeftColor",
|
||||
"borderRightColor",
|
||||
"borderTopColor",
|
||||
"borderBottomColor"
|
||||
},
|
||||
customType = "Color")
|
||||
public void setBorderColor(ReactScrollView view, int index, @Nullable Integer color) {
|
||||
BackgroundStyleApplicator.setBorderColor(view, LogicalEdge.ALL, color);
|
||||
}
|
||||
|
||||
@ReactProp(name = "overflow")
|
||||
public void setOverflow(ReactScrollView view, @Nullable String overflow) {
|
||||
view.setOverflow(overflow);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollToEnd(
|
||||
ReactScrollView scrollView, ReactScrollViewCommandHelper.ScrollToEndCommandData data) {
|
||||
// ScrollView always has one child - the scrollable area. However, it's possible today that we
|
||||
// execute this method as view command before the child view is mounted. Here we will retry the
|
||||
// view commands as a workaround.
|
||||
View child = scrollView.getChildAt(0);
|
||||
if (child == null) {
|
||||
throw new RetryableMountingLayerException("scrollToEnd called on ScrollView without child");
|
||||
}
|
||||
|
||||
// ScrollView always has one child - the scrollable area
|
||||
int bottom = child.getHeight() + scrollView.getPaddingBottom();
|
||||
scrollView.abortAnimation();
|
||||
if (data.mAnimated) {
|
||||
scrollView.reactSmoothScrollTo(scrollView.getScrollX(), bottom);
|
||||
} else {
|
||||
scrollView.scrollTo(scrollView.getScrollX(), bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "persistentScrollbar")
|
||||
public void setPersistentScrollbar(ReactScrollView view, boolean value) {
|
||||
view.setScrollbarFadingEnabled(!value);
|
||||
}
|
||||
|
||||
@ReactProp(name = "fadingEdgeLength")
|
||||
public void setFadingEdgeLength(ReactScrollView view, int value) {
|
||||
if (value > 0) {
|
||||
view.setVerticalFadingEdgeEnabled(true);
|
||||
view.setFadingEdgeLength(value);
|
||||
} else {
|
||||
view.setVerticalFadingEdgeEnabled(false);
|
||||
view.setFadingEdgeLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "contentOffset", customType = "Point")
|
||||
public void setContentOffset(ReactScrollView view, ReadableMap value) {
|
||||
view.setContentOffset(value);
|
||||
}
|
||||
|
||||
@ReactProp(name = "maintainVisibleContentPosition")
|
||||
public void setMaintainVisibleContentPosition(ReactScrollView view, ReadableMap value) {
|
||||
if (value != null) {
|
||||
view.setMaintainVisibleContentPosition(
|
||||
MaintainVisibleScrollPositionHelper.Config.fromReadableMap(value));
|
||||
} else {
|
||||
view.setMaintainVisibleContentPosition(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object updateState(
|
||||
ReactScrollView view, ReactStylesDiffMap props, StateWrapper stateWrapper) {
|
||||
view.setStateWrapper(stateWrapper);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> getExportedCustomDirectEventTypeConstants() {
|
||||
@Nullable
|
||||
Map<String, Object> baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants();
|
||||
Map<String, Object> eventTypeConstants =
|
||||
baseEventTypeConstants == null ? new HashMap<String, Object>() : baseEventTypeConstants;
|
||||
eventTypeConstants.putAll(createExportedCustomDirectEventTypeConstants());
|
||||
return eventTypeConstants;
|
||||
}
|
||||
|
||||
public static Map<String, Object> createExportedCustomDirectEventTypeConstants() {
|
||||
return MapBuilder.<String, Object>builder()
|
||||
.put(
|
||||
ScrollEventType.getJSEventName(ScrollEventType.SCROLL),
|
||||
MapBuilder.of("registrationName", "onScroll"))
|
||||
.put(
|
||||
ScrollEventType.getJSEventName(ScrollEventType.BEGIN_DRAG),
|
||||
MapBuilder.of("registrationName", "onScrollBeginDrag"))
|
||||
.put(
|
||||
ScrollEventType.getJSEventName(ScrollEventType.END_DRAG),
|
||||
MapBuilder.of("registrationName", "onScrollEndDrag"))
|
||||
.put(
|
||||
ScrollEventType.getJSEventName(ScrollEventType.MOMENTUM_BEGIN),
|
||||
MapBuilder.of("registrationName", "onMomentumScrollBegin"))
|
||||
.put(
|
||||
ScrollEventType.getJSEventName(ScrollEventType.MOMENTUM_END),
|
||||
MapBuilder.of("registrationName", "onMomentumScrollEnd"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.POINTER_EVENTS)
|
||||
public void setPointerEvents(ReactScrollView view, @Nullable String pointerEventsStr) {
|
||||
view.setPointerEvents(PointerEvents.parsePointerEvents(pointerEventsStr));
|
||||
}
|
||||
|
||||
@ReactProp(name = "scrollEventThrottle")
|
||||
public void setScrollEventThrottle(ReactScrollView view, int scrollEventThrottle) {
|
||||
view.setScrollEventThrottle(scrollEventThrottle);
|
||||
}
|
||||
|
||||
@ReactProp(name = "horizontal")
|
||||
public void setHorizontal(ReactScrollView view, boolean horizontal) {
|
||||
// Do Nothing: Align with static ViewConfigs
|
||||
}
|
||||
|
||||
@ReactProp(name = "isInvertedVirtualizedList")
|
||||
public void setIsInvertedVirtualizedList(ReactScrollView view, boolean applyFix) {
|
||||
// Usually when inverting the scroll view we are using scaleY: -1 on the list
|
||||
// and on the parent container. HOWEVER, starting from android API 33 there is
|
||||
// a bug that can cause an ANR due to that. Thus we are using different transform
|
||||
// commands to circumvent the ANR. This however causes the vertical scrollbar to
|
||||
// be on the wrong side. Thus we are moving it to the other side, when the list
|
||||
// is inverted.
|
||||
// See also:
|
||||
// - https://github.com/facebook/react-native/issues/35350
|
||||
// - https://issuetracker.google.com/issues/287304310
|
||||
if (applyFix) {
|
||||
view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_LEFT);
|
||||
} else {
|
||||
view.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
+386
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.views.scroll
|
||||
|
||||
import android.graphics.Color
|
||||
import android.view.View
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.facebook.react.bridge.ReadableArray
|
||||
import com.facebook.react.bridge.ReadableMap
|
||||
import com.facebook.react.bridge.RetryableMountingLayerException
|
||||
import com.facebook.react.module.annotations.ReactModule
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderColor
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderRadius
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderStyle
|
||||
import com.facebook.react.uimanager.BackgroundStyleApplicator.setBorderWidth
|
||||
import com.facebook.react.uimanager.LengthPercentage
|
||||
import com.facebook.react.uimanager.LengthPercentageType
|
||||
import com.facebook.react.uimanager.PixelUtil.getDisplayMetricDensity
|
||||
import com.facebook.react.uimanager.PointerEvents.Companion.parsePointerEvents
|
||||
import com.facebook.react.uimanager.ReactClippingViewGroupHelper
|
||||
import com.facebook.react.uimanager.ReactStylesDiffMap
|
||||
import com.facebook.react.uimanager.StateWrapper
|
||||
import com.facebook.react.uimanager.ThemedReactContext
|
||||
import com.facebook.react.uimanager.ViewGroupManager
|
||||
import com.facebook.react.uimanager.ViewProps
|
||||
import com.facebook.react.uimanager.annotations.ReactProp
|
||||
import com.facebook.react.uimanager.annotations.ReactPropGroup
|
||||
import com.facebook.react.uimanager.style.BorderRadiusProp
|
||||
import com.facebook.react.uimanager.style.BorderStyle.Companion.fromString
|
||||
import com.facebook.react.uimanager.style.LogicalEdge
|
||||
import com.facebook.react.views.scroll.ReactScrollViewCommandHelper.Companion.receiveCommand
|
||||
import com.facebook.react.views.scroll.ReactScrollViewCommandHelper.ScrollCommandHandler
|
||||
import com.facebook.react.views.scroll.ReactScrollViewCommandHelper.ScrollToCommandData
|
||||
import com.facebook.react.views.scroll.ReactScrollViewCommandHelper.ScrollToEndCommandData
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.parseOverScrollMode
|
||||
import com.facebook.react.views.scroll.ReactScrollViewHelper.parseSnapToAlignment
|
||||
import com.facebook.react.views.scroll.ScrollEventType.Companion.getJSEventName
|
||||
|
||||
/**
|
||||
* View manager for [ReactScrollView] components.
|
||||
*
|
||||
* Note that [ReactScrollView] and [ReactHorizontalScrollView] are exposed to JS as a single
|
||||
* ScrollView component, configured via the `horizontal` boolean property.
|
||||
*/
|
||||
@ReactModule(name = ReactScrollViewManager.REACT_CLASS)
|
||||
public open class ReactScrollViewManager
|
||||
@JvmOverloads
|
||||
constructor(private val fpsListener: FpsListener? = null) :
|
||||
ViewGroupManager<ReactScrollView>(), ScrollCommandHandler<ReactScrollView> {
|
||||
|
||||
override fun getName(): String = REACT_CLASS
|
||||
|
||||
public override fun createViewInstance(context: ThemedReactContext): ReactScrollView =
|
||||
ReactScrollView(context, fpsListener)
|
||||
|
||||
@ReactProp(name = "scrollEnabled", defaultBoolean = true)
|
||||
public fun setScrollEnabled(view: ReactScrollView, value: Boolean) {
|
||||
view.setScrollEnabled(value)
|
||||
|
||||
// Set focusable to match whether scroll is enabled. This improves keyboarding
|
||||
// experience by not making scrollview a tab stop when you cannot interact with it.
|
||||
view.isFocusable = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "showsVerticalScrollIndicator", defaultBoolean = true)
|
||||
public fun setShowsVerticalScrollIndicator(view: ReactScrollView, value: Boolean) {
|
||||
view.isVerticalScrollBarEnabled = value
|
||||
}
|
||||
|
||||
@ReactProp(name = "decelerationRate")
|
||||
public fun setDecelerationRate(view: ReactScrollView, decelerationRate: Float) {
|
||||
view.setDecelerationRate(decelerationRate)
|
||||
}
|
||||
|
||||
@ReactProp(name = "disableIntervalMomentum")
|
||||
public fun setDisableIntervalMomentum(view: ReactScrollView, disableIntervalMomentum: Boolean) {
|
||||
view.setDisableIntervalMomentum(disableIntervalMomentum)
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToInterval")
|
||||
public fun setSnapToInterval(view: ReactScrollView, snapToInterval: Float) {
|
||||
// snapToInterval needs to be exposed as a float because of the Javascript interface.
|
||||
val density = getDisplayMetricDensity()
|
||||
view.setSnapInterval((snapToInterval * density).toInt())
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToOffsets")
|
||||
public fun setSnapToOffsets(view: ReactScrollView, snapToOffsets: ReadableArray?) {
|
||||
if (snapToOffsets == null || snapToOffsets.size() == 0) {
|
||||
view.setSnapOffsets(null)
|
||||
return
|
||||
}
|
||||
|
||||
val density = getDisplayMetricDensity()
|
||||
val offsets: MutableList<Int> = ArrayList()
|
||||
for (i in 0 until snapToOffsets.size()) {
|
||||
offsets.add((snapToOffsets.getDouble(i) * density).toInt())
|
||||
}
|
||||
view.setSnapOffsets(offsets)
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToAlignment")
|
||||
public fun setSnapToAlignment(view: ReactScrollView, alignment: String?) {
|
||||
view.setSnapToAlignment(parseSnapToAlignment(alignment))
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToStart")
|
||||
public fun setSnapToStart(view: ReactScrollView, snapToStart: Boolean) {
|
||||
view.setSnapToStart(snapToStart)
|
||||
}
|
||||
|
||||
@ReactProp(name = "snapToEnd")
|
||||
public fun setSnapToEnd(view: ReactScrollView, snapToEnd: Boolean) {
|
||||
view.setSnapToEnd(snapToEnd)
|
||||
}
|
||||
|
||||
@ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
|
||||
public fun setRemoveClippedSubviews(view: ReactScrollView, removeClippedSubviews: Boolean) {
|
||||
view.removeClippedSubviews = removeClippedSubviews
|
||||
}
|
||||
|
||||
/**
|
||||
* Computing momentum events is potentially expensive since we post a runnable on the UI thread to
|
||||
* see when it is done. We only do that if {@param sendMomentumEvents} is set to true. This is
|
||||
* handled automatically in js by checking if there is a listener on the momentum events.
|
||||
*
|
||||
* @param view
|
||||
* @param sendMomentumEvents
|
||||
*/
|
||||
@ReactProp(name = "sendMomentumEvents")
|
||||
public fun setSendMomentumEvents(view: ReactScrollView, sendMomentumEvents: Boolean) {
|
||||
view.setSendMomentumEvents(sendMomentumEvents)
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag used for logging scroll performance on this scroll view. Will force momentum events to be
|
||||
* turned on (see setSendMomentumEvents).
|
||||
*
|
||||
* @param view
|
||||
* @param scrollPerfTag
|
||||
*/
|
||||
@ReactProp(name = "scrollPerfTag")
|
||||
public fun setScrollPerfTag(view: ReactScrollView, scrollPerfTag: String?) {
|
||||
view.setScrollPerfTag(scrollPerfTag)
|
||||
}
|
||||
|
||||
@ReactProp(name = "pagingEnabled")
|
||||
public fun setPagingEnabled(view: ReactScrollView, pagingEnabled: Boolean) {
|
||||
view.setPagingEnabled(pagingEnabled)
|
||||
}
|
||||
|
||||
/**
|
||||
* When set, fills the rest of the scrollview with a color to avoid setting a background and
|
||||
* creating unnecessary overdraw.
|
||||
*
|
||||
* @param view
|
||||
* @param color
|
||||
*/
|
||||
@ReactProp(name = "endFillColor", defaultInt = Color.TRANSPARENT, customType = "Color")
|
||||
public fun setBottomFillColor(view: ReactScrollView, color: Int) {
|
||||
view.setEndFillColor(color)
|
||||
}
|
||||
|
||||
/** Controls overScroll behaviour */
|
||||
@ReactProp(name = "overScrollMode")
|
||||
public open fun setOverScrollMode(view: ReactScrollView, value: String?) {
|
||||
view.overScrollMode = parseOverScrollMode(value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "nestedScrollEnabled")
|
||||
public fun setNestedScrollEnabled(view: ReactScrollView?, value: Boolean) {
|
||||
if (view != null) {
|
||||
ViewCompat.setNestedScrollingEnabled(view, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCommandsMap(): Map<String, Int>? = ReactScrollViewCommandHelper.getCommandsMap()
|
||||
|
||||
override fun receiveCommand(scrollView: ReactScrollView, commandId: Int, args: ReadableArray?) {
|
||||
receiveCommand<ReactScrollView>(this, scrollView, commandId, args)
|
||||
}
|
||||
|
||||
override fun receiveCommand(
|
||||
scrollView: ReactScrollView,
|
||||
commandId: String,
|
||||
args: ReadableArray?
|
||||
) {
|
||||
receiveCommand<ReactScrollView>(this, scrollView, commandId, args)
|
||||
}
|
||||
|
||||
override fun flashScrollIndicators(scrollView: ReactScrollView) {
|
||||
scrollView.flashScrollIndicators()
|
||||
}
|
||||
|
||||
override fun scrollTo(scrollView: ReactScrollView, data: ScrollToCommandData) {
|
||||
scrollView.abortAnimation()
|
||||
if (data.mAnimated) {
|
||||
scrollView.reactSmoothScrollTo(data.mDestX, data.mDestY)
|
||||
} else {
|
||||
scrollView.scrollTo(data.mDestX, data.mDestY)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactPropGroup(
|
||||
names =
|
||||
[
|
||||
ViewProps.BORDER_RADIUS,
|
||||
ViewProps.BORDER_TOP_LEFT_RADIUS,
|
||||
ViewProps.BORDER_TOP_RIGHT_RADIUS,
|
||||
ViewProps.BORDER_BOTTOM_RIGHT_RADIUS,
|
||||
ViewProps.BORDER_BOTTOM_LEFT_RADIUS],
|
||||
defaultFloat = Float.NaN)
|
||||
public fun setBorderRadius(view: ReactScrollView?, index: Int, borderRadius: Float) {
|
||||
if (view != null) {
|
||||
val radius =
|
||||
if (java.lang.Float.isNaN(borderRadius)) null
|
||||
else LengthPercentage(borderRadius, LengthPercentageType.POINT)
|
||||
setBorderRadius(view, BorderRadiusProp.entries[index], radius)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "borderStyle")
|
||||
public fun setBorderStyle(view: ReactScrollView?, borderStyle: String?) {
|
||||
if (view != null) {
|
||||
val parsedBorderStyle = if (borderStyle == null) null else fromString(borderStyle)
|
||||
setBorderStyle(view, parsedBorderStyle)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactPropGroup(
|
||||
names =
|
||||
[
|
||||
ViewProps.BORDER_WIDTH,
|
||||
ViewProps.BORDER_LEFT_WIDTH,
|
||||
ViewProps.BORDER_RIGHT_WIDTH,
|
||||
ViewProps.BORDER_TOP_WIDTH,
|
||||
ViewProps.BORDER_BOTTOM_WIDTH],
|
||||
defaultFloat = Float.NaN)
|
||||
public fun setBorderWidth(view: ReactScrollView?, index: Int, width: Float) {
|
||||
if (view != null) {
|
||||
setBorderWidth(view, LogicalEdge.entries[index], width)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactPropGroup(
|
||||
names =
|
||||
[
|
||||
"borderColor",
|
||||
"borderLeftColor",
|
||||
"borderRightColor",
|
||||
"borderTopColor",
|
||||
"borderBottomColor"],
|
||||
customType = "Color")
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public fun setBorderColor(view: ReactScrollView?, index: Int, color: Int?) {
|
||||
if (view != null) {
|
||||
setBorderColor(view, LogicalEdge.ALL, color)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "overflow")
|
||||
public fun setOverflow(view: ReactScrollView, overflow: String?) {
|
||||
view.setOverflow(overflow)
|
||||
}
|
||||
|
||||
override fun scrollToEnd(scrollView: ReactScrollView, data: ScrollToEndCommandData) {
|
||||
// ScrollView always has one child - the scrollable area. However, it's possible today that we
|
||||
// execute this method as view command before the child view is mounted. Here we will retry the
|
||||
// view commands as a workaround.
|
||||
val child =
|
||||
scrollView.getChildAt(0)
|
||||
?: throw RetryableMountingLayerException(
|
||||
"scrollToEnd called on ScrollView without child")
|
||||
|
||||
// ScrollView always has one child - the scrollable area
|
||||
val bottom = child.height + scrollView.paddingBottom
|
||||
scrollView.abortAnimation()
|
||||
if (data.mAnimated) {
|
||||
scrollView.reactSmoothScrollTo(scrollView.scrollX, bottom)
|
||||
} else {
|
||||
scrollView.scrollTo(scrollView.scrollX, bottom)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "persistentScrollbar")
|
||||
public fun setPersistentScrollbar(view: ReactScrollView, value: Boolean) {
|
||||
view.isScrollbarFadingEnabled = !value
|
||||
}
|
||||
|
||||
@ReactProp(name = "fadingEdgeLength")
|
||||
public fun setFadingEdgeLength(view: ReactScrollView, value: Int) {
|
||||
if (value > 0) {
|
||||
view.isVerticalFadingEdgeEnabled = true
|
||||
view.setFadingEdgeLength(value)
|
||||
} else {
|
||||
view.isVerticalFadingEdgeEnabled = false
|
||||
view.setFadingEdgeLength(0)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactProp(name = "contentOffset", customType = "Point")
|
||||
public fun setContentOffset(view: ReactScrollView, value: ReadableMap?) {
|
||||
view.setContentOffset(value)
|
||||
}
|
||||
|
||||
@ReactProp(name = "maintainVisibleContentPosition")
|
||||
public fun setMaintainVisibleContentPosition(view: ReactScrollView, value: ReadableMap?) {
|
||||
if (value != null) {
|
||||
view.setMaintainVisibleContentPosition(
|
||||
MaintainVisibleScrollPositionHelper.Config.fromReadableMap(value))
|
||||
} else {
|
||||
view.setMaintainVisibleContentPosition(null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateState(
|
||||
view: ReactScrollView,
|
||||
props: ReactStylesDiffMap,
|
||||
stateWrapper: StateWrapper
|
||||
): Any? {
|
||||
view.setStateWrapper(stateWrapper)
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any>? {
|
||||
val baseEventTypeConstants = super.getExportedCustomDirectEventTypeConstants()
|
||||
val eventTypeConstants = baseEventTypeConstants ?: HashMap()
|
||||
eventTypeConstants.putAll(createExportedCustomDirectEventTypeConstants())
|
||||
return eventTypeConstants
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.POINTER_EVENTS)
|
||||
public fun setPointerEvents(view: ReactScrollView, pointerEventsStr: String?) {
|
||||
view.pointerEvents = parsePointerEvents(pointerEventsStr)
|
||||
}
|
||||
|
||||
@ReactProp(name = "scrollEventThrottle")
|
||||
public fun setScrollEventThrottle(view: ReactScrollView, scrollEventThrottle: Int) {
|
||||
view.scrollEventThrottle = scrollEventThrottle
|
||||
}
|
||||
|
||||
@ReactProp(name = "horizontal")
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
public fun setHorizontal(view: ReactScrollView?, horizontal: Boolean) {
|
||||
// Do Nothing: Align with static ViewConfigs
|
||||
}
|
||||
|
||||
@ReactProp(name = "isInvertedVirtualizedList")
|
||||
public fun setIsInvertedVirtualizedList(view: ReactScrollView, applyFix: Boolean) {
|
||||
// Usually when inverting the scroll view we are using scaleY: -1 on the list
|
||||
// and on the parent container. HOWEVER, starting from android API 33 there is
|
||||
// a bug that can cause an ANR due to that. Thus we are using different transform
|
||||
// commands to circumvent the ANR. This however causes the vertical scrollbar to
|
||||
// be on the wrong side. Thus we are moving it to the other side, when the list
|
||||
// is inverted.
|
||||
// See also:
|
||||
// - https://github.com/facebook/react-native/issues/35350
|
||||
// - https://issuetracker.google.com/issues/287304310
|
||||
if (applyFix) {
|
||||
view.verticalScrollbarPosition = View.SCROLLBAR_POSITION_LEFT
|
||||
} else {
|
||||
view.verticalScrollbarPosition = View.SCROLLBAR_POSITION_DEFAULT
|
||||
}
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val REACT_CLASS: String = "RCTScrollView"
|
||||
|
||||
public fun createExportedCustomDirectEventTypeConstants(): Map<String, Any> =
|
||||
mapOf(
|
||||
getJSEventName(ScrollEventType.SCROLL) to mapOf("registrationName" to "onScroll"),
|
||||
getJSEventName(ScrollEventType.BEGIN_DRAG) to
|
||||
mapOf("registrationName" to "onScrollBeginDrag"),
|
||||
getJSEventName(ScrollEventType.END_DRAG) to
|
||||
mapOf("registrationName" to "onScrollEndDrag"),
|
||||
getJSEventName(ScrollEventType.MOMENTUM_BEGIN) to
|
||||
mapOf("registrationName" to "onMomentumScrollBegin"),
|
||||
getJSEventName(ScrollEventType.MOMENTUM_END) to
|
||||
mapOf("registrationName" to "onMomentumScrollEnd"))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user