From 2b4cf1f8c44d4e72a884547a9d26d027c2712f9f Mon Sep 17 00:00:00 2001 From: Damiano Plebani Date: Fri, 10 Jan 2025 16:35:58 +0100 Subject: [PATCH 1/2] Fix flickering behavior in the `SearchInput` on iOS --- src/components/searchInput/SearchInput.tsx | 60 +++++++++++++++------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/src/components/searchInput/SearchInput.tsx b/src/components/searchInput/SearchInput.tsx index 5e6b6d62..61dde265 100644 --- a/src/components/searchInput/SearchInput.tsx +++ b/src/components/searchInput/SearchInput.tsx @@ -3,8 +3,7 @@ import React, { forwardRef, useCallback, useImperativeHandle, - useRef, - useState + useRef } from "react"; import { ColorValue, @@ -37,8 +36,12 @@ import { useIOTheme } from "../../core"; import { IOFontSize, makeFontStyleObject } from "../../utils/fonts"; -import { ButtonLink } from "../buttons"; -import { IOIconSizeScale, Icon } from "../icons"; +import { Icon, IOIconSizeScale } from "../icons"; +import { + buttonTextFontSize, + buttonTextLineHeight, + IOText +} from "../typography"; /* Component visual attributes */ const inputPaddingHorizontal: IOSpacingScale = 12; @@ -128,14 +131,19 @@ export const SearchInput = forwardRef( const inputWidth: number = Dimensions.get("window").width - IOVisualCostants.appMarginDefault * 2; - const [cancelButtonWidth, setCancelButtonWidth] = - useState(0); - - const getCancelButtonWidth = ({ nativeEvent }: LayoutChangeEvent) => { - setCancelButtonWidth(nativeEvent.layout.width); - }; + /* Reanimated styles */ + const inputAnimatedWidth = useSharedValue(inputWidth); + const cancelButtonWidth = useSharedValue(0); + const isFocused = useSharedValue(0); - const inputWidthWithCancel: number = inputWidth - cancelButtonWidth; + const getCancelButtonWidth = useCallback( + ({ nativeEvent }: LayoutChangeEvent) => { + if (cancelButtonWidth.value !== nativeEvent.layout.width) { + cancelButtonWidth.value = nativeEvent.layout.width; + } + }, + [cancelButtonWidth] + ); useImperativeHandle( ref, @@ -147,10 +155,6 @@ export const SearchInput = forwardRef( [] ); - /* Reanimated styles */ - const inputAnimatedWidth = useSharedValue(inputWidth); - const isFocused = useSharedValue(0); - /* Applied to the `SearchInput` */ const animatedStyle = useAnimatedStyle(() => ({ width: withTiming(inputAnimatedWidth.value, inputWithTimingConfig), @@ -172,7 +176,7 @@ export const SearchInput = forwardRef( translateX: interpolate( showCancelButton, [0, 1], - [cancelButtonWidth + IOVisualCostants.appMarginDefault, 0], + [cancelButtonWidth.value + IOVisualCostants.appMarginDefault, 0], Extrapolation.CLAMP ) } @@ -200,13 +204,13 @@ export const SearchInput = forwardRef( /* Related event handlers */ const handleFocus = () => { isFocused.value = withTiming(1, inputWithTimingConfig); - inputAnimatedWidth.value = inputWidthWithCancel; + inputAnimatedWidth.value = inputWidth - cancelButtonWidth.value; }; const handleBlur = () => { isFocused.value = withTiming(0, inputWithTimingConfig); inputAnimatedWidth.value = keepCancelVisible - ? inputWidthWithCancel + ? inputAnimatedWidth.value : inputWidth; }; @@ -280,7 +284,25 @@ export const SearchInput = forwardRef( onLayout={getCancelButtonWidth} style={[styles.cancelButton, cancelButtonAnimatedStyle]} > - + + + {cancelButtonLabel} + + ); From d5241dad0ed726b57baf0b5be7b6535b76f10b52 Mon Sep 17 00:00:00 2001 From: Damiano Plebani Date: Wed, 15 Jan 2025 09:53:52 +0100 Subject: [PATCH 2/2] Fix flickering issue without touching anything else --- src/components/searchInput/SearchInput.tsx | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/searchInput/SearchInput.tsx b/src/components/searchInput/SearchInput.tsx index 61dde265..398e9883 100644 --- a/src/components/searchInput/SearchInput.tsx +++ b/src/components/searchInput/SearchInput.tsx @@ -3,7 +3,8 @@ import React, { forwardRef, useCallback, useImperativeHandle, - useRef + useRef, + useState } from "react"; import { ColorValue, @@ -131,19 +132,14 @@ export const SearchInput = forwardRef( const inputWidth: number = Dimensions.get("window").width - IOVisualCostants.appMarginDefault * 2; - /* Reanimated styles */ - const inputAnimatedWidth = useSharedValue(inputWidth); - const cancelButtonWidth = useSharedValue(0); - const isFocused = useSharedValue(0); + const [cancelButtonWidth, setCancelButtonWidth] = + useState(0); - const getCancelButtonWidth = useCallback( - ({ nativeEvent }: LayoutChangeEvent) => { - if (cancelButtonWidth.value !== nativeEvent.layout.width) { - cancelButtonWidth.value = nativeEvent.layout.width; - } - }, - [cancelButtonWidth] - ); + const getCancelButtonWidth = ({ nativeEvent }: LayoutChangeEvent) => { + setCancelButtonWidth(nativeEvent.layout.width); + }; + + const inputWidthWithCancel: number = inputWidth - cancelButtonWidth; useImperativeHandle( ref, @@ -155,6 +151,10 @@ export const SearchInput = forwardRef( [] ); + /* Reanimated styles */ + const inputAnimatedWidth = useSharedValue(inputWidth); + const isFocused = useSharedValue(0); + /* Applied to the `SearchInput` */ const animatedStyle = useAnimatedStyle(() => ({ width: withTiming(inputAnimatedWidth.value, inputWithTimingConfig), @@ -176,7 +176,7 @@ export const SearchInput = forwardRef( translateX: interpolate( showCancelButton, [0, 1], - [cancelButtonWidth.value + IOVisualCostants.appMarginDefault, 0], + [cancelButtonWidth + IOVisualCostants.appMarginDefault, 0], Extrapolation.CLAMP ) } @@ -204,13 +204,13 @@ export const SearchInput = forwardRef( /* Related event handlers */ const handleFocus = () => { isFocused.value = withTiming(1, inputWithTimingConfig); - inputAnimatedWidth.value = inputWidth - cancelButtonWidth.value; + inputAnimatedWidth.value = inputWidthWithCancel; }; const handleBlur = () => { isFocused.value = withTiming(0, inputWithTimingConfig); inputAnimatedWidth.value = keepCancelVisible - ? inputAnimatedWidth.value + ? inputWidthWithCancel : inputWidth; };