Skip to content

Commit a8309cb

Browse files
committed
fix : android height Nan issue
1 parent 6a0c7a2 commit a8309cb

File tree

1 file changed

+77
-37
lines changed

1 file changed

+77
-37
lines changed

src/HighLightToolTip.tsx

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
type LayoutRectangle,
99
Dimensions,
1010
Platform,
11+
type LayoutChangeEvent,
12+
InteractionManager,
1113
} from 'react-native';
1214

1315
type TooltipPosition =
@@ -43,38 +45,81 @@ export const HighlightToolTip: React.FC<HighlightOverlayProps> = ({
4345
androidOffsetY = 0,
4446
}) => {
4547
const [hole, setHole] = useState<LayoutRectangle | null>(null);
48+
const [tooltipLayout, setTooltipLayout] = useState<{
49+
width: number;
50+
height: number;
51+
} | null>(null);
4652
const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
4753

4854
useEffect(() => {
49-
if (!targetRef.current) return;
50-
const handle = findNodeHandle(targetRef.current);
51-
UIManager.measureInWindow(
52-
handle!,
53-
(x: number, y: number, width: number, height: number) => {
54-
const isAndroid = Platform.OS === 'android';
55-
setHole({
56-
x,
57-
y: isAndroid ? y + androidOffsetY : y,
58-
width,
59-
height,
55+
const measure = (retryCount = 0) => {
56+
if (!targetRef.current) {
57+
if (retryCount < 5) {
58+
setTimeout(() => measure(retryCount + 1), 100);
59+
}
60+
return;
61+
}
62+
const handle = findNodeHandle(targetRef.current);
63+
if (handle) {
64+
UIManager.measureInWindow(handle, (x, y, width, height) => {
65+
if (
66+
[x, y, width, height].some(
67+
(val) => typeof val !== 'number' || isNaN(val)
68+
) ||
69+
(width === 0 && height === 0)
70+
) {
71+
if (retryCount < 5) {
72+
setTimeout(() => measure(retryCount + 1), 100);
73+
} else {
74+
console.warn(
75+
'HighlightToolTip: Failed to measure target component after multiple retries.'
76+
);
77+
onRequestClose();
78+
}
79+
return;
80+
}
81+
82+
const isAndroid = Platform.OS === 'android';
83+
setHole({
84+
x,
85+
y: isAndroid ? y + androidOffsetY : y,
86+
width,
87+
height,
88+
});
6089
});
90+
} else if (retryCount < 5) {
91+
setTimeout(() => measure(retryCount + 1), 100);
92+
} else {
93+
console.warn(
94+
'HighlightToolTip: Could not find node handle for targetRef after multiple retries.'
95+
);
96+
onRequestClose();
6197
}
62-
);
63-
}, [targetRef, androidOffsetY]);
98+
};
99+
100+
const interactionHandle = InteractionManager.runAfterInteractions(() => {
101+
measure();
102+
});
103+
104+
return () => interactionHandle.cancel();
105+
}, [targetRef, androidOffsetY, onRequestClose]);
106+
107+
const onTooltipLayout = (event: LayoutChangeEvent) => {
108+
const { width, height } = event.nativeEvent.layout;
109+
if (tooltipLayout?.width !== width || tooltipLayout?.height !== height) {
110+
setTooltipLayout({ width, height });
111+
}
112+
};
64113

65114
const getTooltipPosition = () => {
66-
if (!hole) return { top: 0, left: 0 };
115+
if (!hole || !tooltipLayout) {
116+
return { top: 0, left: 0, opacity: 0 };
117+
}
67118

68119
const { x: offsetX = 0, y: offsetY = 0 } = offset;
69-
// Adjust margin based on allowOverlap - use larger margin to prevent overlap
70-
const margin = allowOverlap ? -4 : 24; // Negative margin when overlap is allowed, otherwise larger margin
71-
72-
// Calculate tooltip size dynamically based on screen size
73-
const maxTooltipWidth = Math.min(screenWidth * 0.8, 320); // Max 80% of screen width or 320px
74-
const tooltipWidth = maxTooltipWidth;
75-
const tooltipHeight = 120; // Adjust to actual height + extra space
120+
const margin = allowOverlap ? -4 : 24;
121+
const { width: tooltipWidth, height: tooltipHeight } = tooltipLayout;
76122

77-
// Calculate initial position
78123
let calculatedPosition = { top: 0, left: 0 };
79124

80125
switch (tooltipPosition) {
@@ -151,39 +196,26 @@ export const HighlightToolTip: React.FC<HighlightOverlayProps> = ({
151196
};
152197
}
153198

154-
// Check screen boundaries and auto-adjust
155199
let { top, left } = calculatedPosition;
156-
157-
// Fixed margin for screen boundary adjustment (always positive)
158200
const boundaryMargin = 16;
159201

160-
// Left boundary check
161202
if (left < boundaryMargin) {
162203
left = boundaryMargin;
163204
}
164205

165-
// Right boundary check - ensure tooltip doesn't extend beyond screen
166206
if (left + tooltipWidth > screenWidth - boundaryMargin) {
167207
left = screenWidth - tooltipWidth - boundaryMargin;
168-
// If still not enough space, adjust tooltip width
169-
if (left < boundaryMargin) {
170-
left = boundaryMargin;
171-
}
172208
}
173209

174-
// Top boundary check
175210
if (top < boundaryMargin) {
176-
// If it goes above, move to bottom - maintain allowOverlap setting
177211
if (tooltipPosition.includes('top')) {
178212
top = hole.y + hole.height + (allowOverlap ? -4 : 24);
179213
} else {
180214
top = boundaryMargin;
181215
}
182216
}
183217

184-
// Bottom boundary check
185218
if (top + tooltipHeight > screenHeight - boundaryMargin) {
186-
// If it goes below, move to top - maintain allowOverlap setting
187219
if (tooltipPosition.includes('bottom')) {
188220
top = hole.y - tooltipHeight - (allowOverlap ? -4 : 24);
189221
} else {
@@ -194,11 +226,17 @@ export const HighlightToolTip: React.FC<HighlightOverlayProps> = ({
194226
return {
195227
top: top + offsetY,
196228
left: left + offsetX,
197-
maxWidth: tooltipWidth,
229+
opacity: 1,
230+
maxWidth: screenWidth * 0.9,
198231
};
199232
};
200233

201-
if (!hole) return null;
234+
const isHoleLayoutInvalid =
235+
!hole || [hole.x, hole.y, hole.width, hole.height].some(isNaN);
236+
237+
if (isHoleLayoutInvalid) {
238+
return null;
239+
}
202240

203241
const tooltipStyle = getTooltipPosition();
204242

@@ -256,10 +294,12 @@ export const HighlightToolTip: React.FC<HighlightOverlayProps> = ({
256294

257295
{/* Tooltip */}
258296
<View
297+
onLayout={onTooltipLayout}
259298
style={{
260299
position: 'absolute',
261300
top: tooltipStyle.top,
262301
left: tooltipStyle.left,
302+
opacity: tooltipStyle.opacity,
263303
maxWidth: tooltipStyle.maxWidth,
264304
}}
265305
>

0 commit comments

Comments
 (0)