Преглед на файлове

Add layout.componentBackgroundColor

This property is used to set background color only for components,
unlike backgroundColor which sets color for every type of layout.

Motivation
When a view appears, its options are resolved according to its
currently displayed children. Basically this means that child options
are hoisted to the parent as children can declare options which effect
their parent.
This means that if a component has declared layout.backgroundColor or
if that property was declared in defaultOptions, each view will have a
background color, which might contribute to a significant overdraw.
Guy Carmeli преди 5 години
родител
ревизия
cb48065aaf

+ 2
- 1
docs/docs/styling.md Целия файл

@@ -228,7 +228,8 @@ Navigation.mergeOptions(this.props.componentId, {
228 228
   },
229 229
   layout: {
230 230
     topMargin: Navigation.constants().statusBarHeight, // Set the layout's top margin
231
-    orientation: ['portrait', 'landscape'] | ['sensorLandscape'] // An array of supported orientations
231
+    orientation: ['portrait', 'landscape'] | ['sensorLandscape'], // An array of supported orientations
232
+    componentBackgroundColor: 'red' // Set background color only for components, helps reduce overdraw if background color is set in default options.
232 233
   },
233 234
   topBar: {
234 235
     height: 70, // TopBar height in dp

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutFactory.java Целия файл

@@ -146,7 +146,7 @@ public class LayoutFactory {
146 146
                 new ComponentViewCreator(reactInstanceManager),
147 147
                 parse(typefaceManager, node.getOptions()),
148 148
                 new Presenter(activity, defaultOptions),
149
-                new ComponentPresenter()
149
+                new ComponentPresenter(defaultOptions)
150 150
         );
151 151
 	}
152 152
 

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/LayoutOptions.java Целия файл

@@ -15,6 +15,7 @@ public class LayoutOptions {
15 15
         if (json == null) return result;
16 16
 
17 17
         result.backgroundColor = ColorParser.parse(json, "backgroundColor");
18
+        result.componentBackgroundColor = ColorParser.parse(json, "componentBackgroundColor");
18 19
         result.topMargin = NumberParser.parse(json, "topMargin");
19 20
         result.orientation = OrientationOptions.parse(json);
20 21
 
@@ -22,11 +23,13 @@ public class LayoutOptions {
22 23
     }
23 24
 
24 25
     public Colour backgroundColor = new NullColor();
26
+    public Colour componentBackgroundColor = new NullColor();
25 27
     public Number topMargin = new NullNumber();
26 28
     public OrientationOptions orientation = new OrientationOptions();
27 29
 
28 30
     public void mergeWith(LayoutOptions other) {
29 31
         if (other.backgroundColor.hasValue()) backgroundColor = other.backgroundColor;
32
+        if (other.componentBackgroundColor.hasValue()) componentBackgroundColor = other.componentBackgroundColor;
30 33
         if (other.topMargin.hasValue()) topMargin = other.topMargin;
31 34
         if (other.orientation.hasValue()) orientation = other.orientation;
32 35
 
@@ -34,6 +37,7 @@ public class LayoutOptions {
34 37
 
35 38
     public void mergeWithDefault(LayoutOptions defaultOptions) {
36 39
         if (!backgroundColor.hasValue()) backgroundColor = defaultOptions.backgroundColor;
40
+        if (!componentBackgroundColor.hasValue()) componentBackgroundColor = defaultOptions.componentBackgroundColor;
37 41
         if (!topMargin.hasValue()) topMargin = defaultOptions.topMargin;
38 42
         if (!orientation.hasValue()) orientation = defaultOptions.orientation;
39 43
     }

+ 20
- 0
lib/android/app/src/main/java/com/reactnativenavigation/presentation/ComponentPresenter.java Целия файл

@@ -4,8 +4,28 @@ import com.reactnativenavigation.parse.Options;
4 4
 import com.reactnativenavigation.views.ComponentLayout;
5 5
 
6 6
 public class ComponentPresenter {
7
+    public Options defaultOptions;
8
+
9
+    public ComponentPresenter(Options defaultOptions) {
10
+        this.defaultOptions = defaultOptions;
11
+    }
12
+
13
+    public void setDefaultOptions(Options defaultOptions) {
14
+        this.defaultOptions = defaultOptions;
15
+    }
16
+
17
+    public void applyOptions(ComponentLayout view, Options options) {
18
+        mergeBackgroundColor(view, options);
19
+    }
7 20
 
8 21
     public void mergeOptions(ComponentLayout view, Options options) {
9 22
         if (options.overlayOptions.interceptTouchOutside.hasValue()) view.setInterceptTouchOutside(options.overlayOptions.interceptTouchOutside);
23
+        mergeBackgroundColor(view, options);
24
+    }
25
+
26
+    private void mergeBackgroundColor(ComponentLayout view, Options options) {
27
+        if (options.layout.componentBackgroundColor.hasValue()) {
28
+            view.setBackgroundColor(options.layout.componentBackgroundColor.get());
29
+        }
10 30
     }
11 31
 }

+ 8
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ComponentViewController.java Целия файл

@@ -30,6 +30,12 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
30 30
         this.presenter = componentPresenter;
31 31
     }
32 32
 
33
+    @Override
34
+    public void setDefaultOptions(Options defaultOptions) {
35
+        super.setDefaultOptions(defaultOptions);
36
+        presenter.setDefaultOptions(defaultOptions);
37
+    }
38
+
33 39
     @Override
34 40
     public void onViewAppeared() {
35 41
         super.onViewAppeared();
@@ -50,7 +56,8 @@ public class ComponentViewController extends ChildController<ComponentLayout> {
50 56
     @Override
51 57
     public void applyOptions(Options options) {
52 58
         super.applyOptions(options);
53
-        view.applyOptions(options);
59
+        getView().applyOptions(options);
60
+        presenter.applyOptions(getView(), resolveCurrentOptions(presenter.defaultOptions));
54 61
     }
55 62
 
56 63
     @Override

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleComponentViewController.java Целия файл

@@ -9,6 +9,6 @@ import com.reactnativenavigation.viewcontrollers.*;
9 9
 
10 10
 public class SimpleComponentViewController extends ComponentViewController {
11 11
     public SimpleComponentViewController(Activity activity, ChildControllersRegistry childRegistry, String id, Options initialOptions) {
12
-        super(activity, childRegistry,id, "theComponentName", new TestComponentViewCreator(), initialOptions, new Presenter(activity, new Options()), new ComponentPresenter());
12
+        super(activity, childRegistry,id, "theComponentName", new TestComponentViewCreator(), initialOptions, new Presenter(activity, new Options()), new ComponentPresenter(Options.EMPTY));
13 13
     }
14 14
 }

+ 27
- 5
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ComponentViewControllerTest.java Целия файл

@@ -9,6 +9,7 @@ import com.reactnativenavigation.mocks.TestReactView;
9 9
 import com.reactnativenavigation.parse.Options;
10 10
 import com.reactnativenavigation.presentation.ComponentPresenter;
11 11
 import com.reactnativenavigation.presentation.Presenter;
12
+import com.reactnativenavigation.views.ComponentLayout;
12 13
 import com.reactnativenavigation.views.StackLayout;
13 14
 
14 15
 import org.junit.Test;
@@ -22,8 +23,9 @@ import static org.mockito.Mockito.when;
22 23
 
23 24
 public class ComponentViewControllerTest extends BaseTest {
24 25
     private ComponentViewController uut;
25
-    private IReactView view;
26
-    private ComponentPresenter componentPresenter;
26
+    private ComponentLayout view;
27
+    private ComponentPresenter presenter;
28
+    private Options resolvedOptions = new Options();
27 29
 
28 30
     @Override
29 31
     public void beforeEach() {
@@ -32,12 +34,32 @@ public class ComponentViewControllerTest extends BaseTest {
32 34
         view = spy(new TestComponentLayout(activity, new TestReactView(activity)));
33 35
         ParentController<StackLayout> parentController = TestUtils.newStackController(activity).build();
34 36
         Presenter presenter = new Presenter(activity, new Options());
35
-        this.componentPresenter = spy(new ComponentPresenter());
36
-        uut = new ComponentViewController(activity, new ChildControllersRegistry(), "componentId1", "componentName", (activity1, componentId, componentName) -> view, new Options(), presenter, this.componentPresenter);
37
+        this.presenter = spy(new ComponentPresenter(Options.EMPTY));
38
+        uut = new ComponentViewController(activity, new ChildControllersRegistry(), "componentId1", "componentName", (activity1, componentId, componentName) -> view, new Options(), presenter, this.presenter) {
39
+            @Override
40
+            public Options resolveCurrentOptions(Options defaultOptions) {
41
+                return resolvedOptions;
42
+            }
43
+        };
37 44
         uut.setParentController(parentController);
38 45
         parentController.ensureViewIsCreated();
39 46
     }
40 47
 
48
+    @Test
49
+    public void setDefaultOptions() {
50
+        Options defaultOptions = new Options();
51
+        uut.setDefaultOptions(defaultOptions);
52
+        verify(presenter).setDefaultOptions(defaultOptions);
53
+    }
54
+
55
+    @Test
56
+    public void applyOptions() {
57
+        Options options = new Options();
58
+        uut.applyOptions(options);
59
+        verify(view).applyOptions(options);
60
+        verify(presenter).applyOptions(view, resolvedOptions);
61
+    }
62
+
41 63
     @Test
42 64
     public void createsViewFromComponentViewCreator() {
43 65
         assertThat(uut.getView()).isSameAs(view);
@@ -93,6 +115,6 @@ public class ComponentViewControllerTest extends BaseTest {
93 115
     public void mergeOptions_delegatesToPresenter() {
94 116
         Options options = new Options();
95 117
         uut.mergeOptions(options);
96
-        verify(componentPresenter).mergeOptions(uut.getView(), options);
118
+        verify(presenter).mergeOptions(uut.getView(), options);
97 119
     }
98 120
 }

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java Целия файл

@@ -63,7 +63,7 @@ public class OptionsApplyingTest extends BaseTest {
63 63
                 (activity1, componentId, componentName) -> view,
64 64
                 initialNavigationOptions,
65 65
                 new Presenter(activity, new Options()),
66
-                new ComponentPresenter()
66
+                new ComponentPresenter(Options.EMPTY)
67 67
         ) {
68 68
             @Override
69 69
             public boolean isViewShown() {

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java Целия файл

@@ -92,7 +92,7 @@ public class TopTabsViewControllerTest extends BaseTest {
92 92
                     new TestComponentViewCreator(),
93 93
                     tabOptions.get(i),
94 94
                     new Presenter(activity, new Options()),
95
-                    new ComponentPresenter()
95
+                    new ComponentPresenter(Options.EMPTY)
96 96
             );
97 97
             tabControllers.add(spy(viewController));
98 98
         }

+ 4
- 0
lib/src/interfaces/Options.ts Целия файл

@@ -55,6 +55,10 @@ export interface OptionsLayout {
55 55
    * Set the screen background color
56 56
    */
57 57
   backgroundColor?: Color;
58
+  /**
59
+   * Set background color only for components, helps reduce overdraw if background color is set in default options.
60
+   */
61
+  componentBackgroundColor?: Color;
58 62
   /**
59 63
    * Set the allowed orientations
60 64
    */

+ 3
- 0
playground/src/app.js Целия файл

@@ -24,6 +24,9 @@ function start() {
24 24
   registerScreens();
25 25
   Navigation.events().registerAppLaunchedListener(async () => {
26 26
     Navigation.setDefaultOptions({
27
+      layout: {
28
+        componentBackgroundColor: '#e8e8e8'
29
+      },
27 30
       bottomTab: {
28 31
         iconColor: '#1B4C77',
29 32
         selectedIconColor: '#0f0',

+ 0
- 2
playground/src/screens/WelcomeScreen.js Целия файл

@@ -583,12 +583,10 @@ const styles = {
583 583
     flexGrow: 1,
584 584
     justifyContent: 'center',
585 585
     alignItems: 'center',
586
-    backgroundColor: '#e8e8e8',
587 586
   },
588 587
   bar: {
589 588
     flex: 1,
590 589
     flexDirection: 'column',
591
-    backgroundColor: '#e8e8e8',
592 590
     justifyContent: 'space-between'
593 591
   },
594 592
   h1: {