Support removeClippedSubviews for horizontal ScrollViews

Summary:
Currently, horizontal `ScrollViews` don't properly support `removeClippedSubviews`.

This is because the container view, `ReactHorizontalScrollContainerView` extends from regular `ViewGroup` instead of `ReactViewGroup` so doesn't have all the logic around clipping children.

Moreover, the `ReactHorizontalScrollContainerViewManager` doesn't actually support the `removeClippedSubviews` prop

This change:
- Makes  `ReactHorizontalScrollContainerView` extend from `ReactViewGroup` while maintaining the special logic around RTL scrolling
- Factors out a common `ReactClippingViewManager` which will be used to bridge all components which extend `ReactViewGroup` and support clipping. It has the logic for adding/removing children and getting child counts while considering clipped subviews
- `ReactViewManager` now extends this new `ReactClippingViewManager`
- `ReactHorizontalScrollContainerViewManager` also extends `ReactClippingViewManager`

Reviewed By: JoshuaGross

Differential Revision: D17708630

fbshipit-source-id: d257566ee54ad46f6d62f176a657c596bba96aa4
This commit is contained in:
Alexander Kawrykow 2019-10-03 15:33:21 -07:00 коммит произвёл Facebook Github Bot
Родитель 21f1cce148
Коммит 42152a3fa3
4 изменённых файлов: 83 добавлений и 66 удалений

Просмотреть файл

@ -6,13 +6,13 @@
package com.facebook.react.views.scroll;
import android.content.Context;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import androidx.core.view.ViewCompat;
import com.facebook.react.modules.i18nmanager.I18nUtil;
import com.facebook.react.views.view.ReactViewGroup;
/** Container of Horizontal scrollViews that supports RTL scrolling. */
public class ReactHorizontalScrollContainerView extends ViewGroup {
public class ReactHorizontalScrollContainerView extends ReactViewGroup {
private int mLayoutDirection;
private int mCurrentWidth;

Просмотреть файл

@ -7,12 +7,12 @@ package com.facebook.react.views.scroll;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.views.view.ReactClippingViewManager;
/** View manager for {@link ReactHorizontalScrollContainerView} components. */
@ReactModule(name = ReactHorizontalScrollContainerViewManager.REACT_CLASS)
public class ReactHorizontalScrollContainerViewManager
extends ViewGroupManager<ReactHorizontalScrollContainerView> {
extends ReactClippingViewManager<ReactHorizontalScrollContainerView> {
public static final String REACT_CLASS = "AndroidHorizontalScrollContentView";

Просмотреть файл

@ -0,0 +1,78 @@
// Copyright (c) Facebook, Inc. and its 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.view;
import android.view.View;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
/**
* View manager which handles clipped subviews. Useful for custom views which extends from {@link
* com.facebook.react.views.view.ReactViewGroup}
*/
public abstract class ReactClippingViewManager<T extends ReactViewGroup>
extends ViewGroupManager<T> {
@ReactProp(
name = com.facebook.react.uimanager.ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
public void setRemoveClippedSubviews(T view, boolean removeClippedSubviews) {
view.setRemoveClippedSubviews(removeClippedSubviews);
}
@Override
public void addView(T parent, View child, int index) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
parent.addViewWithSubviewClippingEnabled(child, index);
} else {
parent.addView(child, index);
}
}
@Override
public int getChildCount(T parent) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
return parent.getAllChildrenCount();
} else {
return parent.getChildCount();
}
}
@Override
public View getChildAt(T parent, int index) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
return parent.getChildAtWithSubviewClippingEnabled(index);
} else {
return parent.getChildAt(index);
}
}
@Override
public void removeViewAt(T parent, int index) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
View child = getChildAt(parent, index);
if (child.getParent() != null) {
parent.removeView(child);
}
parent.removeViewWithSubviewClippingEnabled(child);
} else {
parent.removeViewAt(index);
}
}
@Override
public void removeAllViews(T parent) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
parent.removeAllViewsWithSubviewClippingEnabled();
} else {
parent.removeAllViews();
}
}
}

Просмотреть файл

@ -24,7 +24,6 @@ import com.facebook.react.uimanager.PointerEvents;
import com.facebook.react.uimanager.Spacing;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.UIManagerModule;
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;
@ -35,7 +34,7 @@ import java.util.Map;
/** View manager for AndroidViews (plain React Views). */
@ReactModule(name = ReactViewManager.REACT_CLASS)
public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
public class ReactViewManager extends ReactClippingViewManager<ReactViewGroup> {
@VisibleForTesting public static final String REACT_CLASS = ViewProps.VIEW_CLASS_NAME;
@ -182,12 +181,6 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
fg == null ? null : ReactDrawableHelper.createDrawableFromJSDescription(view, fg));
}
@ReactProp(
name = com.facebook.react.uimanager.ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
public void setRemoveClippedSubviews(ReactViewGroup view, boolean removeClippedSubviews) {
view.setRemoveClippedSubviews(removeClippedSubviews);
}
@ReactProp(name = ViewProps.NEEDS_OFFSCREEN_ALPHA_COMPOSITING)
public void setNeedsOffscreenAlphaCompositing(
ReactViewGroup view, boolean needsOffscreenAlphaCompositing) {
@ -354,58 +347,4 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
root.drawableHotspotChanged(x, y);
}
}
@Override
public void addView(ReactViewGroup parent, View child, int index) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
parent.addViewWithSubviewClippingEnabled(child, index);
} else {
parent.addView(child, index);
}
}
@Override
public int getChildCount(ReactViewGroup parent) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
return parent.getAllChildrenCount();
} else {
return parent.getChildCount();
}
}
@Override
public View getChildAt(ReactViewGroup parent, int index) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
return parent.getChildAtWithSubviewClippingEnabled(index);
} else {
return parent.getChildAt(index);
}
}
@Override
public void removeViewAt(ReactViewGroup parent, int index) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
View child = getChildAt(parent, index);
if (child.getParent() != null) {
parent.removeView(child);
}
parent.removeViewWithSubviewClippingEnabled(child);
} else {
parent.removeViewAt(index);
}
}
@Override
public void removeAllViews(ReactViewGroup parent) {
boolean removeClippedSubviews = parent.getRemoveClippedSubviews();
if (removeClippedSubviews) {
parent.removeAllViewsWithSubviewClippingEnabled();
} else {
parent.removeAllViews();
}
}
}