Add zIndex support
Summary: Adds zIndex support :) **Test Plan** Tested the following components by adding two of each, overlapping them, and setting a high zIndex on the first of the two: ActivityIndicator Image MapView Picker ScrollView Slider Switch Text TextInput View WebView Tested on Android 4.1 and iOS 8.4. Also tested updating zIndexes on Views in my own app. <img width="359" alt="ios activityindicator" src="https://cloud.githubusercontent.com/assets/4349082/15633473/88f842cc-257b-11e6-8539-c41c0b179f80.png"> <img width="330" alt="android activityindicator" src="https://cloud.githubusercontent.com/assets/4349082/15633475/88f95784-257b-11e6-80c0-2bf3ed836503.png"> <img width="357" alt="ios image" src="https://cloud.githubusercontent.com/assets/4349082/15633474/88f93d80-257b-11e6-9e54-4ff8e4d25f71.png"> <img width="340" alt="android image" src="https://cloud.githubusercontent.com/assets/4349082/15633478/88fd2788-257b-11e6-8c80-29078e65e808.png"> <img width="342" alt="android picker" src="ht Closes https://github.com/facebook/react-native/pull/7825 Differential Revision: D3469374 Pulled By: lexs fbshipit-source-id: b2b74b71d968ebf73ecfd457ace3f35f8f7c7658
This commit is contained in:
parent
3085b35e63
commit
3d3b067f6f
Binary file not shown.
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 128 KiB |
Binary file not shown.
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 153 KiB |
|
@ -5,6 +5,7 @@ package com.facebook.react.uimanager;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
|
@ -21,6 +22,7 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||||
private static final String PROP_TRANSFORM = "transform";
|
private static final String PROP_TRANSFORM = "transform";
|
||||||
private static final String PROP_OPACITY = "opacity";
|
private static final String PROP_OPACITY = "opacity";
|
||||||
private static final String PROP_ELEVATION = "elevation";
|
private static final String PROP_ELEVATION = "elevation";
|
||||||
|
private static final String PROP_Z_INDEX = "zIndex";
|
||||||
private static final String PROP_RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid";
|
private static final String PROP_RENDER_TO_HARDWARE_TEXTURE = "renderToHardwareTextureAndroid";
|
||||||
private static final String PROP_ACCESSIBILITY_LABEL = "accessibilityLabel";
|
private static final String PROP_ACCESSIBILITY_LABEL = "accessibilityLabel";
|
||||||
private static final String PROP_ACCESSIBILITY_COMPONENT_TYPE = "accessibilityComponentType";
|
private static final String PROP_ACCESSIBILITY_COMPONENT_TYPE = "accessibilityComponentType";
|
||||||
|
@ -70,6 +72,12 @@ public abstract class BaseViewManager<T extends View, C extends LayoutShadowNode
|
||||||
// Do nothing on API < 21
|
// Do nothing on API < 21
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = PROP_Z_INDEX)
|
||||||
|
public void setZIndex(T view, float zIndex) {
|
||||||
|
int integerZIndex = Math.round(zIndex);
|
||||||
|
ViewGroupManager.setViewZIndex(view, integerZIndex);
|
||||||
|
}
|
||||||
|
|
||||||
@ReactProp(name = PROP_RENDER_TO_HARDWARE_TEXTURE)
|
@ReactProp(name = PROP_RENDER_TO_HARDWARE_TEXTURE)
|
||||||
public void setRenderToHardwareTexture(T view, boolean useHWTexture) {
|
public void setRenderToHardwareTexture(T view, boolean useHWTexture) {
|
||||||
view.setLayerType(useHWTexture ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, null);
|
view.setLayerType(useHWTexture ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE, null);
|
||||||
|
|
|
@ -12,12 +12,20 @@ package com.facebook.react.uimanager;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class providing children management API for view managers of classes extending ViewGroup.
|
* Class providing children management API for view managers of classes extending ViewGroup.
|
||||||
*/
|
*/
|
||||||
public abstract class ViewGroupManager <T extends ViewGroup>
|
public abstract class ViewGroupManager <T extends ViewGroup>
|
||||||
extends BaseViewManager<T, LayoutShadowNode> {
|
extends BaseViewManager<T, LayoutShadowNode> {
|
||||||
|
|
||||||
|
public static WeakHashMap<View, Integer> mZIndexHash = new WeakHashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LayoutShadowNode createShadowNodeInstance() {
|
public LayoutShadowNode createShadowNodeInstance() {
|
||||||
return new LayoutShadowNode();
|
return new LayoutShadowNode();
|
||||||
|
@ -34,6 +42,59 @@ public abstract class ViewGroupManager <T extends ViewGroup>
|
||||||
|
|
||||||
public void addView(T parent, View child, int index) {
|
public void addView(T parent, View child, int index) {
|
||||||
parent.addView(child, index);
|
parent.addView(child, index);
|
||||||
|
reorderChildrenByZIndex(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setViewZIndex(View view, int zIndex) {
|
||||||
|
mZIndexHash.put(view, zIndex);
|
||||||
|
// zIndex prop gets set BEFORE the view is added, so parent may be null.
|
||||||
|
ViewGroup parent = (ViewGroup) view.getParent();
|
||||||
|
if (parent != null) {
|
||||||
|
reorderChildrenByZIndex(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void reorderChildrenByZIndex(ViewGroup view) {
|
||||||
|
// Optimization: loop through the zIndexHash to test if there are any non-zero zIndexes
|
||||||
|
// If there aren't any, we can just return out
|
||||||
|
Collection<Integer> zIndexes = mZIndexHash.values();
|
||||||
|
boolean containsZIndexedElement = false;
|
||||||
|
for (Integer zIndex : zIndexes) {
|
||||||
|
if (zIndex != 0) {
|
||||||
|
containsZIndexedElement = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!containsZIndexedElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all children to a sortable ArrayList
|
||||||
|
ArrayList<View> viewsToSort = new ArrayList<>();
|
||||||
|
for (int i = 0; i < view.getChildCount(); i++) {
|
||||||
|
viewsToSort.add(view.getChildAt(i));
|
||||||
|
}
|
||||||
|
// Sort the views by zIndex
|
||||||
|
Collections.sort(viewsToSort, new Comparator<View>() {
|
||||||
|
@Override
|
||||||
|
public int compare(View view1, View view2) {
|
||||||
|
Integer view1ZIndex = mZIndexHash.get(view1);
|
||||||
|
if (view1ZIndex == null) {
|
||||||
|
view1ZIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer view2ZIndex = mZIndexHash.get(view2);
|
||||||
|
if (view2ZIndex == null) {
|
||||||
|
view2ZIndex = 0;
|
||||||
|
}
|
||||||
|
return view1ZIndex - view2ZIndex;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Call .bringToFront on the sorted list of views
|
||||||
|
for (int i = 0; i < viewsToSort.size(); i++) {
|
||||||
|
viewsToSort.get(i).bringToFront();
|
||||||
|
}
|
||||||
|
view.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChildCount(T parent) {
|
public int getChildCount(T parent) {
|
||||||
|
|
|
@ -195,6 +195,7 @@ public class ReactViewManager extends ViewGroupManager<ReactViewGroup> {
|
||||||
} else {
|
} else {
|
||||||
parent.addView(child, index);
|
parent.addView(child, index);
|
||||||
}
|
}
|
||||||
|
reorderChildrenByZIndex(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue