From 3d3b067f6fc831b6b23726087fe39cf39ef86f00 Mon Sep 17 00:00:00 2001 From: Tucker Connelly Date: Wed, 29 Jun 2016 07:38:30 -0700 Subject: [PATCH] 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. ios activityindicator android activityindicator ios image android image android picker extends BaseViewManager { + public static WeakHashMap mZIndexHash = new WeakHashMap<>(); + @Override public LayoutShadowNode createShadowNodeInstance() { return new LayoutShadowNode(); @@ -34,6 +42,59 @@ public abstract class ViewGroupManager public void addView(T parent, View child, int 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 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 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() { + @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) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java index 6a4bd5d26..ed9dc09e4 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.java @@ -195,6 +195,7 @@ public class ReactViewManager extends ViewGroupManager { } else { parent.addView(child, index); } + reorderChildrenByZIndex(parent); } @Override