Skip to content

Commit

Permalink
Merge pull request #619 from grahammendick/native-nodesize
Browse files Browse the repository at this point in the history
  • Loading branch information
grahammendick authored Jul 28, 2022
2 parents 79d904f + 51da6f9 commit 9b73421
Show file tree
Hide file tree
Showing 25 changed files with 440 additions and 128 deletions.
14 changes: 6 additions & 8 deletions NavigationReactNative/src/ActionBar.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React, {useState} from 'react'
import React from 'react'
import { requireNativeComponent, Platform, StyleSheet } from 'react-native';

const ActionBar = props => {
const [bounds, setBounds] = useState({});
return Platform.OS == 'android' ? (
const ActionBar = props => (
Platform.OS == 'android' ? (
<NVActionBar
{...props}
onChangeBounds={({nativeEvent: {width, height}}) => {setBounds({width, height})}}
style={[styles.actionView, bounds]} />
) : null;
};
style={styles.actionView} />
) : null
);

const NVActionBar = global.nativeFabricUIManager ? require('./ActionBarNativeComponent').default : requireNativeComponent('NVActionBar');

Expand Down
5 changes: 1 addition & 4 deletions NavigationReactNative/src/ActionBarNativeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNati

type NativeProps = $ReadOnly<{|
...ViewProps,
onChangeBounds: DirectEventHandler<$ReadOnly<{|
width: Float,
height: Float,
|}>>,
onExpanded: DirectEventHandler<null>,
onCollapsed: DirectEventHandler<null>,
|}>;

export default (codegenNativeComponent<NativeProps>(
'NVActionBar',
{interfaceOnly: true}
): HostComponent<NativeProps>);
18 changes: 7 additions & 11 deletions NavigationReactNative/src/TitleBar.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import React, {useState} from 'react'
import React from 'react'
import { requireNativeComponent, StyleSheet, Platform } from 'react-native';

const TitleBar = ({style, ...props}) => {
const [bounds, setBounds] = useState({});
return (
<NVTitleBar
{...props}
onChangeBounds={({nativeEvent: {width, height}}) => {setBounds({width, height})}}
style={[Platform.OS === 'ios' && styles.titleBar, style, bounds]}
/>
)
};
const TitleBar = ({style, ...props}) => (
<NVTitleBar
{...props}
style={[Platform.OS === 'ios' && styles.titleBar, style]}
/>
);

const NVTitleBar = global.nativeFabricUIManager ? require('./TitleBarNativeComponent').default : requireNativeComponent('NVTitleBar');

Expand Down
5 changes: 1 addition & 4 deletions NavigationReactNative/src/TitleBarNativeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNati

type NativeProps = $ReadOnly<{|
...ViewProps,
onChangeBounds: DirectEventHandler<$ReadOnly<{|
width: Float,
height: Float,
|}>>,
|}>;

export default (codegenNativeComponent<NativeProps>(
'NVTitleBar',
{interfaceOnly: true}
): HostComponent<NativeProps>);
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.<String, Object>builder()
.put("topOnExpanded", MapBuilder.of("registrationName", "onExpanded"))
.put("topOnCollapsed", MapBuilder.of("registrationName", "onCollapsed"))
.put("topOnChangeBounds", MapBuilder.of("registrationName", "onChangeBounds"))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,24 @@
import android.content.Context;
import android.view.ViewGroup;

import com.facebook.react.bridge.Arguments;
import androidx.annotation.UiThread;

import com.facebook.react.bridge.GuardedRunnable;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.uimanager.FabricViewStateManager;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;

public class ActionBarView extends ViewGroup {
public class ActionBarView extends ViewGroup implements FabricViewStateManager.HasFabricViewStateManager {
private boolean layoutRequested = false;
private int resizeLoopCount = 0;
private final FabricViewStateManager fabricViewStateManager = new FabricViewStateManager();

public ActionBarView(Context context) {
super(context);
Expand All @@ -36,18 +42,55 @@ void collapsed() {
eventDispatcher.dispatchEvent(new ActionBarView.CollapsedEvent(getId()));
}

void changeBounds(int width, int height, int oldw, int oldh) {
void changeBounds(final int width, final int height, int oldw, int oldh) {
super.onSizeChanged(width, height, oldw, oldh);
if (Math.abs(width - oldw) > 5 || Math.abs(height - oldh) > 5)
resizeLoopCount = 0;
if (Math.abs(width - oldw) <= 5 && Math.abs(height - oldh) <= 5)
resizeLoopCount++;
if (resizeLoopCount <= 3) {
ReactContext reactContext = (ReactContext) getContext();
EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, getId());
eventDispatcher.dispatchEvent(new ActionBarView.ChangeBoundsEvent(getId(), width, height));
if (fabricViewStateManager.hasStateWrapper()) {
updateState(width, height);
} else {
final int viewTag = getId();
final ReactContext reactContext = (ReactContext) getContext();
reactContext.runOnNativeModulesQueueThread(
new GuardedRunnable(reactContext) {
@Override
public void runGuarded() {
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
if (uiManager != null)
uiManager.updateNodeSize(viewTag, width, height);
}
});

}
requestLayout();
}

@UiThread
public void updateState(final int width, final int height) {
final float realWidth = PixelUtil.toDIPFromPixel(width);
final float realHeight = PixelUtil.toDIPFromPixel(height);
ReadableMap currentState = getFabricViewStateManager().getStateData();
if (currentState != null) {
float delta = (float) 0.9;
float stateScreenHeight =
currentState.hasKey("frameHeight")
? (float) currentState.getDouble("frameHeight")
: 0;
float stateScreenWidth =
currentState.hasKey("frameWidth") ? (float) currentState.getDouble("frameWidth") : 0;

if (Math.abs(stateScreenWidth - realWidth) < delta
&& Math.abs(stateScreenHeight - realHeight) < delta) {
return;
}
}
fabricViewStateManager.setState(
new FabricViewStateManager.StateUpdateCallback() {
@Override
public WritableMap getStateUpdate() {
WritableMap map = new WritableNativeMap();
map.putDouble("frameWidth", realWidth);
map.putDouble("frameHeight", realHeight);
return map;
}
});
}

@Override
Expand All @@ -70,6 +113,11 @@ public void run() {
}
};

@Override
public FabricViewStateManager getFabricViewStateManager() {
return fabricViewStateManager;
}

static class ExpandedEvent extends Event<ActionBarView.ExpandedEvent> {
public ExpandedEvent(int viewId) {
super(viewId);
Expand Down Expand Up @@ -101,28 +149,4 @@ public void dispatch(RCTEventEmitter rctEventEmitter) {
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), null);
}
}

static class ChangeBoundsEvent extends Event<ActionBarView.ChangeBoundsEvent> {
private final int width;
private final int height;

public ChangeBoundsEvent(int viewId, int width, int height) {
super(viewId);
this.width = width;
this.height = height;
}

@Override
public String getEventName() {
return "topOnChangeBounds";
}

@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
WritableMap event = Arguments.createMap();
event.putInt("width", (int) PixelUtil.toDIPFromPixel(this.width));
event.putInt("height", (int) PixelUtil.toDIPFromPixel(this.height));
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import androidx.annotation.Nullable;

import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ReactStylesDiffMap;
import com.facebook.react.uimanager.StateWrapper;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.ViewManagerDelegate;
Expand Down Expand Up @@ -42,7 +44,13 @@ public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.<String, Object>builder()
.put("topOnExpanded", MapBuilder.of("registrationName", "onExpanded"))
.put("topOnCollapsed", MapBuilder.of("registrationName", "onCollapsed"))
.put("topOnChangeBounds", MapBuilder.of("registrationName", "onChangeBounds"))
.build();
}

@Override
public Object updateState(
ActionBarView view, ReactStylesDiffMap props, StateWrapper stateWrapper) {
view.getFabricViewStateManager().setStateWrapper(stateWrapper);
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
import androidx.annotation.Nullable;
import androidx.appcompat.view.CollapsibleActionView;

import com.facebook.react.bridge.GuardedRunnable;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,4 @@ public String getName() {
protected TitleBarView createViewInstance(@Nonnull ThemedReactContext reactContext) {
return new TitleBarView(reactContext);
}

@Override
public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
return MapBuilder.<String, Object>builder()
.put("topOnChangeBounds", MapBuilder.of("registrationName", "onChangeBounds"))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@
import android.content.Context;
import android.view.ViewGroup;

import com.facebook.react.bridge.Arguments;
import androidx.annotation.UiThread;

import com.facebook.react.bridge.GuardedRunnable;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.uimanager.FabricViewStateManager;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.events.Event;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.react.uimanager.UIManagerModule;

public class TitleBarView extends ViewGroup {
public class TitleBarView extends ViewGroup implements FabricViewStateManager.HasFabricViewStateManager {
private boolean layoutRequested = false;
private int resizeLoopCount = 0;
private final FabricViewStateManager fabricViewStateManager = new FabricViewStateManager();

public TitleBarView(Context context) {
super(context);
Expand All @@ -27,16 +29,52 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
@Override
protected void onSizeChanged(final int w, final int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (Math.abs(w - oldw) > 5 || Math.abs(h - oldh) > 5)
resizeLoopCount = 0;
if (Math.abs(w - oldw) <= 5 && Math.abs(h - oldh) <= 5)
resizeLoopCount++;
if (resizeLoopCount <= 3) {
ReactContext reactContext = (ReactContext) getContext();
EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, getId());
eventDispatcher.dispatchEvent(new TitleBarView.ChangeBoundsEvent(getId(), w, h));
if (fabricViewStateManager.hasStateWrapper()) {
updateState(w, h);
} else {
final int viewTag = getId();
final ReactContext reactContext = (ReactContext) getContext();
reactContext.runOnNativeModulesQueueThread(
new GuardedRunnable(reactContext) {
@Override
public void runGuarded() {
UIManagerModule uiManager = reactContext.getNativeModule(UIManagerModule.class);
if (uiManager != null)
uiManager.updateNodeSize(viewTag, w, h);
}
});
}
requestLayout();
}

@UiThread
public void updateState(final int width, final int height) {
final float realWidth = PixelUtil.toDIPFromPixel(width);
final float realHeight = PixelUtil.toDIPFromPixel(height);
ReadableMap currentState = getFabricViewStateManager().getStateData();
if (currentState != null) {
float delta = (float) 0.9;
float stateScreenHeight =
currentState.hasKey("frameHeight")
? (float) currentState.getDouble("frameHeight")
: 0;
float stateScreenWidth =
currentState.hasKey("frameWidth") ? (float) currentState.getDouble("frameWidth") : 0;

if (Math.abs(stateScreenWidth - realWidth) < delta
&& Math.abs(stateScreenHeight - realHeight) < delta) {
return;
}
}
fabricViewStateManager.setState(
new FabricViewStateManager.StateUpdateCallback() {
@Override
public WritableMap getStateUpdate() {
WritableMap map = new WritableNativeMap();
map.putDouble("frameWidth", realWidth);
map.putDouble("frameHeight", realHeight);
return map;
}
});
}

@Override
Expand All @@ -59,27 +97,8 @@ public void run() {
}
};

static class ChangeBoundsEvent extends Event<TitleBarView.ChangeBoundsEvent> {
private final int width;
private final int height;

public ChangeBoundsEvent(int viewId, int width, int height) {
super(viewId);
this.width = width;
this.height = height;
}

@Override
public String getEventName() {
return "topOnChangeBounds";
}

@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
WritableMap event = Arguments.createMap();
event.putInt("width", (int) PixelUtil.toDIPFromPixel(this.width));
event.putInt("height", (int) PixelUtil.toDIPFromPixel(this.height));
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), event);
}
@Override
public FabricViewStateManager getFabricViewStateManager() {
return fabricViewStateManager;
}
}
Loading

0 comments on commit 9b73421

Please sign in to comment.