react-native-navigation 8.8.7 → 8.8.8-snapshot.2616
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3,7 +3,9 @@ package com.reactnativenavigation.views.stack.topbar.titlebar;
|
|
|
3
3
|
import android.annotation.SuppressLint;
|
|
4
4
|
import android.content.Context;
|
|
5
5
|
import android.util.TypedValue;
|
|
6
|
+
import android.view.Gravity;
|
|
6
7
|
import android.view.View;
|
|
8
|
+
import android.widget.FrameLayout;
|
|
7
9
|
|
|
8
10
|
import com.reactnativenavigation.options.ComponentOptions;
|
|
9
11
|
import com.reactnativenavigation.options.params.Number;
|
|
@@ -23,6 +25,17 @@ public class TitleBarReactButtonView extends ReactView {
|
|
|
23
25
|
this.component = component;
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
@Override
|
|
29
|
+
public void onViewAdded(View child) {
|
|
30
|
+
super.onViewAdded(child);
|
|
31
|
+
if (child.getLayoutParams() instanceof FrameLayout.LayoutParams) {
|
|
32
|
+
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) child.getLayoutParams();
|
|
33
|
+
layoutParams.gravity = layoutParams.gravity == -1
|
|
34
|
+
? Gravity.CENTER_VERTICAL
|
|
35
|
+
: (layoutParams.gravity & ~Gravity.VERTICAL_GRAVITY_MASK) | Gravity.CENTER_VERTICAL;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
@Override
|
|
27
40
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
28
41
|
// This is a workaround, ReactNative throws exception when views have ids, On android MenuItems
|
|
@@ -31,32 +44,34 @@ public class TitleBarReactButtonView extends ReactView {
|
|
|
31
44
|
this.setId(View.NO_ID);
|
|
32
45
|
}
|
|
33
46
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
// Width: bounded (AT_MOST) so the hosted React surface sizes itself to its content. Under
|
|
48
|
+
// Fabric, ReactSurfaceView reports max-of-children under AT_MOST (the laid-out content width)
|
|
49
|
+
// and pushes that to the async layout. Crucially we must NOT push a forced EXACTLY *width*:
|
|
50
|
+
// before the content has laid out that width is collapsed (~1px), Fabric lays the content into
|
|
51
|
+
// it and the button never recovers (#8320/#8326 did this and regressed under the New Arch).
|
|
52
|
+
//
|
|
53
|
+
// Height: EXACTLY the available bar height. Giving the surface a filled height (rather than a
|
|
54
|
+
// content-hugging AT_MOST height) lets content that centers itself (e.g. a flex container with
|
|
55
|
+
// justifyContent: 'center') sit vertically centered in the bar, matching the legacy layout.
|
|
56
|
+
// It does not cause the width collapse — only a forced width does.
|
|
57
|
+
int widthSpec = component.width.hasValue()
|
|
58
|
+
? createExactSpec(component.width)
|
|
59
|
+
: makeMeasureSpec(resolveAvailableWidth(widthMeasureSpec), AT_MOST);
|
|
60
|
+
int heightSpec = createHeightSpec(heightMeasureSpec, component.height);
|
|
61
|
+
super.onMeasure(widthSpec, heightSpec);
|
|
42
62
|
}
|
|
43
63
|
|
|
44
64
|
private int createHeightSpec(int measureSpec, Number dimension) {
|
|
45
65
|
if (dimension.hasValue()) {
|
|
46
66
|
return createExactSpec(dimension);
|
|
47
67
|
}
|
|
48
|
-
|
|
68
|
+
int availableSize = MeasureSpec.getSize(measureSpec);
|
|
69
|
+
return makeMeasureSpec(availableSize > 0 ? availableSize : Math.max(resolveActionBarSize(), 1), EXACTLY);
|
|
49
70
|
}
|
|
50
71
|
|
|
51
|
-
private int
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
} else {
|
|
55
|
-
// Use bounded wrap-content width to avoid RN/Yoga RTL padding issues caused by
|
|
56
|
-
// UNSPECIFIED, without forcing every custom button to actionBarSize width.
|
|
57
|
-
int availableSize = MeasureSpec.getSize(measureSpec);
|
|
58
|
-
return makeMeasureSpec(availableSize > 0 ? availableSize : fallbackSize, AT_MOST);
|
|
59
|
-
}
|
|
72
|
+
private int resolveAvailableWidth(int measureSpec) {
|
|
73
|
+
int availableSize = MeasureSpec.getSize(measureSpec);
|
|
74
|
+
return availableSize > 0 ? availableSize : Math.max(getResources().getDisplayMetrics().widthPixels, 1);
|
|
60
75
|
}
|
|
61
76
|
|
|
62
77
|
private int createExactSpec(Number dimension) {
|
package/android/src/test/java/com/reactnativenavigation/views/TitleBarReactButtonViewTest.java
CHANGED
|
@@ -9,8 +9,10 @@ import static org.assertj.core.api.Java6Assertions.assertThat;
|
|
|
9
9
|
|
|
10
10
|
import android.app.Activity;
|
|
11
11
|
import android.util.TypedValue;
|
|
12
|
+
import android.view.Gravity;
|
|
12
13
|
import android.view.View;
|
|
13
14
|
import android.view.ViewGroup;
|
|
15
|
+
import android.widget.FrameLayout;
|
|
14
16
|
|
|
15
17
|
import com.reactnativenavigation.BaseTest;
|
|
16
18
|
import com.reactnativenavigation.options.ComponentOptions;
|
|
@@ -21,22 +23,37 @@ import com.reactnativenavigation.views.stack.topbar.titlebar.TitleBarReactButton
|
|
|
21
23
|
|
|
22
24
|
import org.junit.Test;
|
|
23
25
|
|
|
26
|
+
import java.util.ArrayList;
|
|
27
|
+
import java.util.List;
|
|
28
|
+
|
|
24
29
|
public class TitleBarReactButtonViewTest extends BaseTest {
|
|
25
30
|
private static final int PARENT_WIDTH = 200;
|
|
26
31
|
private static final int PARENT_HEIGHT = 100;
|
|
27
32
|
private static final int CHILD_WIDTH = 24;
|
|
28
33
|
private static final int CHILD_HEIGHT = 16;
|
|
29
34
|
|
|
35
|
+
// Without explicit dimensions the button measures the hosted React surface ONCE:
|
|
36
|
+
// - width AT_MOST → the surface sizes itself to its content (max-of-children under Fabric).
|
|
37
|
+
// - height EXACTLY the available bar height → the surface gets a filled box so content that
|
|
38
|
+
// centers itself (flex justifyContent: 'center') stays vertically centered in the bar.
|
|
39
|
+
// It deliberately does not push a forced EXACTLY *width*; under the New Architecture that re-pushes
|
|
40
|
+
// a (initially collapsed) width to the async Fabric layout and the button never recovers.
|
|
30
41
|
@Test
|
|
31
|
-
public void
|
|
42
|
+
public void missingDimensionsSizeWidthToContentAndFillHeight() {
|
|
32
43
|
Activity activity = newActivity();
|
|
33
44
|
TitleBarReactButtonView uut = createView(activity, new ComponentOptions());
|
|
34
|
-
|
|
45
|
+
RecordingContentView child = new RecordingContentView(activity);
|
|
46
|
+
setContentView(uut, child);
|
|
35
47
|
|
|
36
48
|
uut.measure(makeMeasureSpec(PARENT_WIDTH, AT_MOST), makeMeasureSpec(PARENT_HEIGHT, AT_MOST));
|
|
37
49
|
|
|
38
50
|
assertThat(uut.getMeasuredWidth()).isEqualTo(CHILD_WIDTH);
|
|
39
|
-
assertThat(uut.getMeasuredHeight()).isEqualTo(
|
|
51
|
+
assertThat(uut.getMeasuredHeight()).isEqualTo(PARENT_HEIGHT);
|
|
52
|
+
assertThat(child.widthMeasureSpecs.size()).isEqualTo(1);
|
|
53
|
+
assertThat(getMode(child.widthMeasureSpecs.get(0))).isEqualTo(AT_MOST);
|
|
54
|
+
assertThat(getSize(child.widthMeasureSpecs.get(0))).isEqualTo(PARENT_WIDTH);
|
|
55
|
+
assertThat(getMode(child.heightMeasureSpecs.get(0))).isEqualTo(EXACTLY);
|
|
56
|
+
assertThat(getSize(child.heightMeasureSpecs.get(0))).isEqualTo(PARENT_HEIGHT);
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
@Test
|
|
@@ -46,50 +63,70 @@ public class TitleBarReactButtonViewTest extends BaseTest {
|
|
|
46
63
|
component.width = new Number(72);
|
|
47
64
|
component.height = new Number(32);
|
|
48
65
|
TitleBarReactButtonView uut = createView(activity, component);
|
|
49
|
-
|
|
66
|
+
RecordingContentView child = new RecordingContentView(activity);
|
|
67
|
+
setContentView(uut, child);
|
|
50
68
|
|
|
51
69
|
uut.measure(makeMeasureSpec(PARENT_WIDTH, AT_MOST), makeMeasureSpec(PARENT_HEIGHT, AT_MOST));
|
|
52
70
|
|
|
53
71
|
assertThat(uut.getMeasuredWidth()).isEqualTo(UiUtils.dpToPx(activity, 72));
|
|
54
72
|
assertThat(uut.getMeasuredHeight()).isEqualTo(UiUtils.dpToPx(activity, 32));
|
|
73
|
+
assertThat(child.widthMeasureSpecs.size()).isEqualTo(1);
|
|
74
|
+
assertThat(getMode(child.widthMeasureSpecs.get(0))).isEqualTo(EXACTLY);
|
|
75
|
+
assertThat(getSize(child.widthMeasureSpecs.get(0))).isEqualTo(UiUtils.dpToPx(activity, 72));
|
|
76
|
+
assertThat(getMode(child.heightMeasureSpecs.get(0))).isEqualTo(EXACTLY);
|
|
77
|
+
assertThat(getSize(child.heightMeasureSpecs.get(0))).isEqualTo(UiUtils.dpToPx(activity, 32));
|
|
55
78
|
}
|
|
56
79
|
|
|
57
80
|
@Test
|
|
58
|
-
public void
|
|
81
|
+
public void zeroParentSpecsFallBackToScreenWidthAndActionBarHeight() {
|
|
59
82
|
Activity activity = newActivity();
|
|
60
83
|
TitleBarReactButtonView uut = createView(activity, new ComponentOptions());
|
|
61
|
-
|
|
62
|
-
uut
|
|
63
|
-
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
64
|
-
ViewGroup.LayoutParams.MATCH_PARENT
|
|
65
|
-
));
|
|
84
|
+
RecordingContentView child = new RecordingContentView(activity);
|
|
85
|
+
setContentView(uut, child);
|
|
66
86
|
|
|
67
87
|
uut.measure(makeMeasureSpec(0, AT_MOST), makeMeasureSpec(0, AT_MOST));
|
|
68
88
|
|
|
69
|
-
assertThat(
|
|
70
|
-
assertThat(
|
|
89
|
+
assertThat(child.widthMeasureSpecs.size()).isEqualTo(1);
|
|
90
|
+
assertThat(getMode(child.widthMeasureSpecs.get(0))).isEqualTo(AT_MOST);
|
|
91
|
+
assertThat(getSize(child.widthMeasureSpecs.get(0)))
|
|
71
92
|
.isEqualTo(Math.max(activity.getResources().getDisplayMetrics().widthPixels, 1));
|
|
72
|
-
assertThat(getMode(child.
|
|
73
|
-
assertThat(getSize(child.
|
|
93
|
+
assertThat(getMode(child.heightMeasureSpecs.get(0))).isEqualTo(EXACTLY);
|
|
94
|
+
assertThat(getSize(child.heightMeasureSpecs.get(0))).isEqualTo(Math.max(resolveActionBarSize(activity), 1));
|
|
74
95
|
}
|
|
75
96
|
|
|
76
97
|
@Test
|
|
77
|
-
public void
|
|
98
|
+
public void rtlMissingDimensionsUseBoundedWidthAndFilledHeight() {
|
|
78
99
|
Activity activity = newActivity();
|
|
79
100
|
TitleBarReactButtonView uut = createView(activity, new ComponentOptions());
|
|
80
|
-
|
|
101
|
+
RecordingContentView child = new RecordingContentView(activity);
|
|
81
102
|
uut.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
|
|
82
|
-
uut
|
|
103
|
+
setContentView(uut, child);
|
|
104
|
+
|
|
105
|
+
uut.measure(makeMeasureSpec(PARENT_WIDTH, AT_MOST), makeMeasureSpec(PARENT_HEIGHT, AT_MOST));
|
|
106
|
+
|
|
107
|
+
assertThat(child.widthMeasureSpecs.size()).isEqualTo(1);
|
|
108
|
+
assertThat(getMode(child.widthMeasureSpecs.get(0))).isEqualTo(AT_MOST);
|
|
109
|
+
assertThat(getSize(child.widthMeasureSpecs.get(0))).isEqualTo(PARENT_WIDTH);
|
|
110
|
+
assertThat(getMode(child.heightMeasureSpecs.get(0))).isEqualTo(EXACTLY);
|
|
111
|
+
assertThat(getSize(child.heightMeasureSpecs.get(0))).isEqualTo(PARENT_HEIGHT);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@Test
|
|
115
|
+
public void contentCenteringReplacesExistingVerticalGravityOnly() {
|
|
116
|
+
Activity activity = newActivity();
|
|
117
|
+
TitleBarReactButtonView uut = createView(activity, new ComponentOptions());
|
|
118
|
+
RecordingContentView child = new RecordingContentView(activity);
|
|
119
|
+
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
|
|
83
120
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
84
121
|
ViewGroup.LayoutParams.MATCH_PARENT
|
|
85
|
-
)
|
|
122
|
+
);
|
|
123
|
+
params.gravity = Gravity.TOP | Gravity.RIGHT;
|
|
86
124
|
|
|
87
|
-
uut.
|
|
125
|
+
uut.addView(child, params);
|
|
88
126
|
|
|
89
|
-
|
|
90
|
-
assertThat(
|
|
91
|
-
assertThat(
|
|
92
|
-
assertThat(getSize(child.lastHeightMeasureSpec)).isEqualTo(resolveActionBarSize(activity));
|
|
127
|
+
FrameLayout.LayoutParams updatedParams = (FrameLayout.LayoutParams) child.getLayoutParams();
|
|
128
|
+
assertThat(updatedParams.gravity & Gravity.VERTICAL_GRAVITY_MASK).isEqualTo(Gravity.CENTER_VERTICAL);
|
|
129
|
+
assertThat(updatedParams.gravity & Gravity.HORIZONTAL_GRAVITY_MASK).isEqualTo(Gravity.RIGHT);
|
|
93
130
|
}
|
|
94
131
|
|
|
95
132
|
private TitleBarReactButtonView createView(Activity activity, ComponentOptions component) {
|
|
@@ -98,6 +135,14 @@ public class TitleBarReactButtonViewTest extends BaseTest {
|
|
|
98
135
|
return new TitleBarReactButtonView(activity, component);
|
|
99
136
|
}
|
|
100
137
|
|
|
138
|
+
private void setContentView(TitleBarReactButtonView uut, View child) {
|
|
139
|
+
uut.removeAllViews();
|
|
140
|
+
uut.addView(child, new ViewGroup.LayoutParams(
|
|
141
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
142
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
143
|
+
));
|
|
144
|
+
}
|
|
145
|
+
|
|
101
146
|
private int resolveActionBarSize(Activity activity) {
|
|
102
147
|
TypedValue tv = new TypedValue();
|
|
103
148
|
if (activity.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
|
|
@@ -106,30 +151,26 @@ public class TitleBarReactButtonViewTest extends BaseTest {
|
|
|
106
151
|
return UiUtils.dpToPx(activity, 48);
|
|
107
152
|
}
|
|
108
153
|
|
|
109
|
-
private static class
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
@Override
|
|
115
|
-
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
116
|
-
setMeasuredDimension(CHILD_WIDTH, CHILD_HEIGHT);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private static class RecordingView extends View {
|
|
121
|
-
int lastWidthMeasureSpec;
|
|
122
|
-
int lastHeightMeasureSpec;
|
|
154
|
+
private static class RecordingContentView extends View {
|
|
155
|
+
final List<Integer> widthMeasureSpecs = new ArrayList<>();
|
|
156
|
+
final List<Integer> heightMeasureSpecs = new ArrayList<>();
|
|
123
157
|
|
|
124
|
-
|
|
158
|
+
RecordingContentView(Activity activity) {
|
|
125
159
|
super(activity);
|
|
126
160
|
}
|
|
127
161
|
|
|
128
162
|
@Override
|
|
129
163
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
164
|
+
widthMeasureSpecs.add(widthMeasureSpec);
|
|
165
|
+
heightMeasureSpecs.add(heightMeasureSpec);
|
|
166
|
+
|
|
167
|
+
int measuredWidth = getMode(widthMeasureSpec) == EXACTLY
|
|
168
|
+
? getSize(widthMeasureSpec)
|
|
169
|
+
: Math.min(CHILD_WIDTH, getSize(widthMeasureSpec));
|
|
170
|
+
int measuredHeight = getMode(heightMeasureSpec) == EXACTLY
|
|
171
|
+
? getSize(heightMeasureSpec)
|
|
172
|
+
: Math.min(CHILD_HEIGHT, getSize(heightMeasureSpec));
|
|
173
|
+
setMeasuredDimension(measuredWidth, measuredHeight);
|
|
133
174
|
}
|
|
134
175
|
}
|
|
135
176
|
}
|