Improve z-index implementation on Android

Summary:
Use `getChildDrawingOrder` instead of reordering views. The old implementation didn't work properly when `removeClippedSubviews` was enabled and this one should have better performance since we don't play with the view hierarchy at all.

This fixes weird bugs with sticky headers in `SectionList` and allows removing the hack that disabled `removeClippedSubviews` when using sticky section headers.

**Test plan**
Tested using the SectionList and ListViewPaging examples that use sticky headers which uses z-index.
Closes https://github.com/facebook/react-native/pull/13105

Reviewed By: sahrens

Differential Revision: D4765869

Pulled By: achen1

fbshipit-source-id: be3c824658a3ce965b6e7324ad95c77cbd8a86ae
This commit is contained in:
Janic Duplessis authored and Facebook Github Bot committed 2017-04-05 09:17:46 -07:00
1 parent af533ac7f1
commit 9a51fa8e15
7 files changed
+149 -53

No files matched your search

@@ -19,13 +19,15 @@ import java.util.WeakHashMap;
import android.view.View;
import android.view.ViewGroup;
import javax.annotation.Nullable;
/**
* Class providing children management API for view managers of classes extending ViewGroup.
*/
public abstract class ViewGroupManager <T extends ViewGroup>
extends BaseViewManager<T, LayoutShadowNode> {
public static WeakHashMap<View, Integer> mZIndexHash = new WeakHashMap<>();
private static WeakHashMap<View, Integer> mZIndexHash = new WeakHashMap<>();
@Override
public LayoutShadowNode createShadowNodeInstance() {
@@ -43,7 +45,6 @@ public abstract class ViewGroupManager <T extends ViewGroup>
public void addView(T parent, View child, int index) {
parent.addView(child, index);
reorderChildrenByZIndex(parent);
}
/**
@@ -61,54 +62,10 @@ public abstract class ViewGroupManager <T extends ViewGroup>
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 static @Nullable Integer getViewZIndex(View view) {
return mZIndexHash.get(view);
}
public int getChildCount(T parent) {