Browse Source

Apply TopBar buttons only if they are different than current buttons (#5314)

Like all other options, buttons are applied when a screen becomes visible. This means that in a BottomTabs layout,
options are applied when a tab is selected. Since tab change happens involves only changing view visibility, and button creation take a bit long,
the buttons appear to flicker some times.
Guy Carmeli 5 years ago
parent
commit
f15e9b3a2a
No account linked to committer's email address

+ 7
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/Component.java View File

@@ -44,4 +44,11 @@ public class Component {
44 44
     public boolean hasValue() {
45 45
         return name.hasValue();
46 46
     }
47
+
48
+    public boolean equals(Component other) {
49
+        return name.equals(other.name) &&
50
+               componentId.equals(other.componentId) &&
51
+               alignment.equals(other.alignment) &&
52
+               waitForRender.equals(other.waitForRender);
53
+    }
47 54
 }

+ 17
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/params/Button.java View File

@@ -16,6 +16,7 @@ import org.json.JSONArray;
16 16
 import org.json.JSONObject;
17 17
 
18 18
 import java.util.ArrayList;
19
+import java.util.Objects;
19 20
 
20 21
 public class Button {
21 22
     public String instanceId = "btn" + CompatUtils.generateViewId();
@@ -34,6 +35,22 @@ public class Button {
34 35
     public Text testId = new NullText();
35 36
     public Component component = new Component();
36 37
 
38
+    public boolean equals(Button other) {
39
+        return Objects.equals(id, other.id) &&
40
+               text.equals(other.text) &&
41
+               enabled.equals(other.enabled) &&
42
+               disableIconTint.equals(other.disableIconTint) &&
43
+               showAsAction.equals(other.showAsAction) &&
44
+               color.equals(other.color) &&
45
+               disabledColor.equals(other.disabledColor) &&
46
+               fontSize.equals(other.fontSize) &&
47
+               fontWeight.equals(other.fontWeight) &&
48
+               Objects.equals(fontFamily, other.fontFamily) &&
49
+               icon.equals(other.icon) &&
50
+               testId.equals(other.testId) &&
51
+               component.equals(other.component);
52
+    }
53
+
37 54
     private static Button parseJson(JSONObject json, TypefaceLoader typefaceManager) {
38 55
         Button button = new Button();
39 56
         button.id = json.optString("id");

+ 6
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/params/Param.java View File

@@ -1,5 +1,7 @@
1 1
 package com.reactnativenavigation.parse.params;
2 2
 
3
+import static com.reactnativenavigation.utils.ObjectUtils.equalsNotNull;
4
+
3 5
 public abstract class Param<T> {
4 6
     protected T value;
5 7
 
@@ -21,4 +23,8 @@ public abstract class Param<T> {
21 23
     public boolean hasValue() {
22 24
         return value != null;
23 25
     }
26
+
27
+    public boolean equals(Param other) {
28
+        return value == other.value || equalsNotNull(value, other.value);
29
+    }
24 30
 }

+ 22
- 0
lib/android/app/src/main/java/com/reactnativenavigation/utils/CollectionUtils.java View File

@@ -2,13 +2,16 @@ package com.reactnativenavigation.utils;
2 2
 
3 3
 import android.support.annotation.NonNull;
4 4
 import android.support.annotation.Nullable;
5
+import android.support.v4.util.Pair;
5 6
 
6 7
 import java.util.ArrayList;
7 8
 import java.util.Collection;
8 9
 import java.util.Collections;
9 10
 import java.util.HashMap;
11
+import java.util.Iterator;
10 12
 import java.util.List;
11 13
 import java.util.Map;
14
+import java.util.Objects;
12 15
 
13 16
 public class CollectionUtils {
14 17
     public interface Apply<T> {
@@ -136,4 +139,23 @@ public class CollectionUtils {
136 139
         return t == null ? Collections.EMPTY_LIST : t.values();
137 140
     }
138 141
 
142
+    public static <T> boolean equals(@Nullable Collection<T> a, @Nullable Collection<T> b) {
143
+        if (size(a) != size(b)) return false;
144
+        return reduce(zip(a, b), true, (p, currentValue) -> currentValue && Objects.equals(p.first, p.second));
145
+    }
146
+
147
+    public static int size(@Nullable Collection items) {
148
+        return items == null ? 0 : items.size();
149
+    }
150
+
151
+    public static <T> Collection<Pair<T, T>> zip(@Nullable Collection<T> a, @Nullable Collection<T> b) {
152
+        if (a == null || b == null) return new ArrayList<>();
153
+        Iterator iter1 = a.iterator();
154
+        Iterator iter2 = b.iterator();
155
+        ArrayList<Pair<T,T>> result = new ArrayList<>();
156
+        while (iter1.hasNext() && iter2.hasNext()) {
157
+            result.add(new Pair(iter1.next(), iter2.next()));
158
+        }
159
+        return result;
160
+    }
139 161
 }

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/utils/ViewUtils.java View File

@@ -16,7 +16,7 @@ import java.util.List;
16 16
 
17 17
 public class ViewUtils {
18 18
     @Nullable
19
-    public static <T> T findChildByClass(ViewGroup root, Class clazz) {
19
+    public static <T extends View> T findChildByClass(ViewGroup root, Class<T> clazz) {
20 20
         for (int i = 0; i < root.getChildCount(); i++) {
21 21
             View view = root.getChildAt(i);
22 22
             if (clazz.isAssignableFrom(view.getClass())) {

+ 5
- 1
lib/android/app/src/main/java/com/reactnativenavigation/views/topbar/TopBar.java View File

@@ -20,7 +20,6 @@ import android.widget.LinearLayout;
20 20
 import android.widget.RelativeLayout;
21 21
 import android.widget.TextView;
22 22
 
23
-import com.reactnativenavigation.BuildConfig;
24 23
 import com.reactnativenavigation.R;
25 24
 import com.reactnativenavigation.anim.TopBarAnimator;
26 25
 import com.reactnativenavigation.anim.TopBarCollapseBehavior;
@@ -29,6 +28,7 @@ import com.reactnativenavigation.parse.Alignment;
29 28
 import com.reactnativenavigation.parse.AnimationOptions;
30 29
 import com.reactnativenavigation.parse.params.Colour;
31 30
 import com.reactnativenavigation.parse.params.Number;
31
+import com.reactnativenavigation.utils.CollectionUtils;
32 32
 import com.reactnativenavigation.utils.CompatUtils;
33 33
 import com.reactnativenavigation.utils.UiUtils;
34 34
 import com.reactnativenavigation.viewcontrollers.TitleBarButtonController;
@@ -36,6 +36,7 @@ import com.reactnativenavigation.views.StackLayout;
36 36
 import com.reactnativenavigation.views.titlebar.TitleBar;
37 37
 import com.reactnativenavigation.views.toptabs.TopTabs;
38 38
 
39
+import java.util.ArrayList;
39 40
 import java.util.Collections;
40 41
 import java.util.List;
41 42
 
@@ -52,6 +53,7 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
52 53
     private View border;
53 54
     private View component;
54 55
     private float elevation = -1;
56
+    private List<TitleBarButtonController> rightButtons = new ArrayList<>();
55 57
 
56 58
     public TopBar(final Context context, StackLayout parentView) {
57 59
         super(context);
@@ -218,6 +220,8 @@ public class TopBar extends AppBarLayout implements ScrollEventListener.ScrollAw
218 220
     }
219 221
 
220 222
     public void setRightButtons(List<TitleBarButtonController> rightButtons) {
223
+        if (CollectionUtils.equals(this.rightButtons, rightButtons)) return;
224
+        this.rightButtons = rightButtons;
221 225
         titleBar.setRightButtons(rightButtons);
222 226
     }
223 227
 

+ 0
- 1
lib/android/app/src/test/java/com/reactnativenavigation/views/TopBarTest.java View File

@@ -26,7 +26,6 @@ public class TopBarTest extends BaseTest {
26 26
     private TopBarAnimator animator;
27 27
     private Activity activity;
28 28
 
29
-    @SuppressWarnings("Convert2Lambda")
30 29
     @Override
31 30
     public void beforeEach() {
32 31
         activity = newActivity();