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
     public boolean hasValue() {
44
     public boolean hasValue() {
45
         return name.hasValue();
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
 import org.json.JSONObject;
16
 import org.json.JSONObject;
17
 
17
 
18
 import java.util.ArrayList;
18
 import java.util.ArrayList;
19
+import java.util.Objects;
19
 
20
 
20
 public class Button {
21
 public class Button {
21
     public String instanceId = "btn" + CompatUtils.generateViewId();
22
     public String instanceId = "btn" + CompatUtils.generateViewId();
34
     public Text testId = new NullText();
35
     public Text testId = new NullText();
35
     public Component component = new Component();
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
     private static Button parseJson(JSONObject json, TypefaceLoader typefaceManager) {
54
     private static Button parseJson(JSONObject json, TypefaceLoader typefaceManager) {
38
         Button button = new Button();
55
         Button button = new Button();
39
         button.id = json.optString("id");
56
         button.id = json.optString("id");

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

1
 package com.reactnativenavigation.parse.params;
1
 package com.reactnativenavigation.parse.params;
2
 
2
 
3
+import static com.reactnativenavigation.utils.ObjectUtils.equalsNotNull;
4
+
3
 public abstract class Param<T> {
5
 public abstract class Param<T> {
4
     protected T value;
6
     protected T value;
5
 
7
 
21
     public boolean hasValue() {
23
     public boolean hasValue() {
22
         return value != null;
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
 
2
 
3
 import android.support.annotation.NonNull;
3
 import android.support.annotation.NonNull;
4
 import android.support.annotation.Nullable;
4
 import android.support.annotation.Nullable;
5
+import android.support.v4.util.Pair;
5
 
6
 
6
 import java.util.ArrayList;
7
 import java.util.ArrayList;
7
 import java.util.Collection;
8
 import java.util.Collection;
8
 import java.util.Collections;
9
 import java.util.Collections;
9
 import java.util.HashMap;
10
 import java.util.HashMap;
11
+import java.util.Iterator;
10
 import java.util.List;
12
 import java.util.List;
11
 import java.util.Map;
13
 import java.util.Map;
14
+import java.util.Objects;
12
 
15
 
13
 public class CollectionUtils {
16
 public class CollectionUtils {
14
     public interface Apply<T> {
17
     public interface Apply<T> {
136
         return t == null ? Collections.EMPTY_LIST : t.values();
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
 
16
 
17
 public class ViewUtils {
17
 public class ViewUtils {
18
     @Nullable
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
         for (int i = 0; i < root.getChildCount(); i++) {
20
         for (int i = 0; i < root.getChildCount(); i++) {
21
             View view = root.getChildAt(i);
21
             View view = root.getChildAt(i);
22
             if (clazz.isAssignableFrom(view.getClass())) {
22
             if (clazz.isAssignableFrom(view.getClass())) {

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

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

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

26
     private TopBarAnimator animator;
26
     private TopBarAnimator animator;
27
     private Activity activity;
27
     private Activity activity;
28
 
28
 
29
-    @SuppressWarnings("Convert2Lambda")
30
     @Override
29
     @Override
31
     public void beforeEach() {
30
     public void beforeEach() {
32
         activity = newActivity();
31
         activity = newActivity();