From c9b4f74045e34a49f9d7d103e16ad6dd07b06b01 Mon Sep 17 00:00:00 2001 From: Marcuz Larsen Date: Fri, 22 Apr 2022 08:27:06 +0200 Subject: [PATCH 1/2] Initial --- .../ScrollViewKeyboardAvoidExample.tsx | 115 +++++++----------- .../InputField/InputAnimationWrapper.tsx | 41 +++++++ src/components/InputField/Regular.tsx | 40 ++++++ src/index.tsx | 3 +- 4 files changed, 126 insertions(+), 73 deletions(-) create mode 100644 src/components/InputField/InputAnimationWrapper.tsx create mode 100644 src/components/InputField/Regular.tsx diff --git a/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx b/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx index 191be48..687aef1 100644 --- a/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx +++ b/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx @@ -7,6 +7,7 @@ import Animated, { } from 'react-native-reanimated'; import styled from 'styled-components/native'; import InputField from '../InputField'; +import Regular from '../InputField/Regular'; import ScrollViewKeyboardAvoid from '../ScrollViewKeyboardAvoid'; import { SCROLL_EVENT_THROTTLE } from '../../constants/configs'; @@ -23,38 +24,20 @@ const inputStyle = { backgroundColor: 'white', }; -const fakeScrollItem = [ - { - text: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt +const text = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat - cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`, - }, - { - text: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt - ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco - laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in - voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat - cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`, - }, - { - text: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt - ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco - laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in - voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat - cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`, - }, -]; + cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +`; const Wrapper = styled.View<{ windowHeight: number }>` height: ${({ windowHeight }): number => windowHeight}px; width: 100%; `; -const FakeContentWrapper = styled.View<{ windowHeight: number }>` - background: white; - height: ${({ windowHeight }): number => windowHeight}px; +const FakeContentWrapper = styled.View` + height: 100%; width: 100%; padding: 32px 16px; `; @@ -69,9 +52,6 @@ const ScrollViewKeyboardAvoidExample: React.FC = () => { const isKeyboardVisible = useSharedValue(false); const animatedStyle = useAnimatedStyle(() => { return { - position: 'absolute', - bottom: 0, - height: isKeyboardVisible?.value ? 150 : windowHeight, transform: [ { translateY: translationY.value, @@ -82,52 +62,43 @@ const ScrollViewKeyboardAvoidExample: React.FC = () => { return ( - - - <> - {fakeScrollItem.map(({ text }, i) => ( - - - - {text} - - - - - ))} - - - + + + {text} + + + + + ); }; diff --git a/src/components/InputField/InputAnimationWrapper.tsx b/src/components/InputField/InputAnimationWrapper.tsx new file mode 100644 index 0000000..2caf31f --- /dev/null +++ b/src/components/InputField/InputAnimationWrapper.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import Animated, { useAnimatedRef, useSharedValue } from 'react-native-reanimated'; + +import { getAnimatedMeasures } from '../helpers'; + +const InputAnimationWrapper: React.FC = () => { + const inputRef = useAnimatedRef(); + const positionY = useSharedValue(0); + const translationY = useSharedValue(0); + + /* TODO: + - Ensure that translation Y is right above keyboard. + The value is probably coming from the outside + - Add flexibility to input position + + + + if (isMounted.value && measureRef?.current) { + getAnimatedMeasures({ + ref: measureRef, + callback: ({ height }) => { + const snapPointBottom = + height > 0 ? height - configSnapPointBottom - (extraSnapPointBottomOffset ?? 0) : 0; + + onOpenOrCloseCardRequest({ + closeBottomSheetRequest, + openBottomSheetRequest, + isCardCollapsed, + snapEffectDirection, + scrollViewRef, + scrollY, + isAnimationRunning, + translationY, + snapPointBottom, + }); + }, + }); + +} +*/ +}; diff --git a/src/components/InputField/Regular.tsx b/src/components/InputField/Regular.tsx new file mode 100644 index 0000000..9d10df4 --- /dev/null +++ b/src/components/InputField/Regular.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { TextInput as RNTextInput } from 'react-native'; +import styled from 'styled-components/native'; + +interface InputFieldProps { + placeholder: string; +} + +const AVAILABLE_SPACE_DESKTOP = 68; +const AVAILABLE_SPACE_MOBILE = 38; + +const TextInput = styled.TextInput` + flex: 1; +`; + +const Regular: React.FC = ({ placeholder }) => { + const TEXT_INPUT_STYLE = { + padding: 6, + fontSize: 40, + fontWeight: 'bold', + color: 'white', + textAlign: 'center', + outline: 'none', + borderWidth: 3, + borderColor: 'grey', + borderRadius: 7, + textShadow: '2px 2px 5px rgba(0, 0, 0, 0.85)', + }; + + return ( + + ); +}; + +export default Regular; diff --git a/src/index.tsx b/src/index.tsx index fcc4cde..1e55f48 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,8 @@ import React from 'react'; +import ScrollViewKeyboardAvoidExample from './components/Examples/ScrollViewKeyboardAvoidExample'; import NoHardRerenderingEffect from './components/Examples/NoHardRerenderingEffect'; import 'setimmediate'; -const App: React.FC = () => ; +const App: React.FC = () => ; export default App; From 78190733f34f393e6e80a810b44c13fb44dc8901 Mon Sep 17 00:00:00 2001 From: Marcuz Larsen Date: Wed, 4 May 2022 17:15:00 +0200 Subject: [PATCH 2/2] Initial --- ios/Podfile.lock | 4 +- .../ScrollViewKeyboardAvoidExample.tsx | 28 ++++- .../InputField/InputAnimationWrapper.tsx | 109 +++++++++++++----- src/components/InputField/Regular.tsx | 6 +- 4 files changed, 110 insertions(+), 37 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 37c0a48..2cb287d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -376,7 +376,7 @@ PODS: - React-RCTText - ReactCommon/turbomodule/core - Yoga - - RNSVG (12.2.0): + - RNSVG (12.3.0): - React-Core - SocketRocket (0.6.0) - Yoga (1.14.0) @@ -577,7 +577,7 @@ SPEC CHECKSUMS: ReactCommon: bf2888a826ceedf54b99ad1b6182d1bc4a8a3984 RNGestureHandler: 50e6ffee79932d14ea747d4ea4cc99aac0f24e86 RNReanimated: e42de406edd11350af29016cf6802ef16ee364d0 - RNSVG: 4ecc2e8f38b6ebe7889909570c26f3abe8059767 + RNSVG: 302bfc9905bd8122f08966dc2ce2d07b7b52b9f8 SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608 Yoga: 17cd9a50243093b547c1e539c749928dd68152da YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx b/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx index 687aef1..12070e0 100644 --- a/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx +++ b/src/components/Examples/ScrollViewKeyboardAvoidExample.tsx @@ -8,6 +8,7 @@ import Animated, { import styled from 'styled-components/native'; import InputField from '../InputField'; import Regular from '../InputField/Regular'; +import InputAnimationWrapper from '../InputField/InputAnimationWrapper'; import ScrollViewKeyboardAvoid from '../ScrollViewKeyboardAvoid'; import { SCROLL_EVENT_THROTTLE } from '../../constants/configs'; @@ -39,6 +40,7 @@ const Wrapper = styled.View<{ windowHeight: number }>` const FakeContentWrapper = styled.View` height: 100%; width: 100%; + border: 2px solid black; padding: 32px 16px; `; @@ -49,7 +51,25 @@ const ScrollViewKeyboardAvoidExample: React.FC = () => { const scrollViewRef = useAnimatedRef(); const windowHeight = useWindowDimensions().height; const translationY = useSharedValue(0); + + const scrollY = useSharedValue(0); + const scrollViewHeight = useSharedValue(0); + const contentHeight = useSharedValue(0); + const keyboardHeight = useSharedValue(0); + const isInputFieldFocused = useSharedValue(false); + const isScrollable = useSharedValue(false); const isKeyboardVisible = useSharedValue(false); + + const animationScrollValues = { + scrollY, + scrollViewHeight, + contentHeight, + keyboardHeight, + isInputFieldFocused, + isScrollable, + isKeyboardVisible, + }; + const animatedStyle = useAnimatedStyle(() => { return { transform: [ @@ -67,9 +87,7 @@ const ScrollViewKeyboardAvoidExample: React.FC = () => { bounces={false} alwaysBounceVertical={false} keyboardAvoidBottomMargin={isIOS ? 64 : 100} - connectScrollViewMeasuresToAnimationValues={{ - isKeyboardVisible, - }} + connectScrollViewMeasuresToAnimationValues={animationScrollValues} fadingScrollEdges={{ isEnabled: true, iOSandWebFadingEdgeHeight: 150, @@ -94,9 +112,9 @@ const ScrollViewKeyboardAvoidExample: React.FC = () => { > {text} - + - + diff --git a/src/components/InputField/InputAnimationWrapper.tsx b/src/components/InputField/InputAnimationWrapper.tsx index 2caf31f..7e15728 100644 --- a/src/components/InputField/InputAnimationWrapper.tsx +++ b/src/components/InputField/InputAnimationWrapper.tsx @@ -1,41 +1,98 @@ -import React from 'react'; -import Animated, { useAnimatedRef, useSharedValue } from 'react-native-reanimated'; +import React, { useEffect } from 'react'; +import { useWindowDimensions } from 'react-native'; +import Animated, { + useAnimatedReaction, + useAnimatedRef, + useAnimatedStyle, + useSharedValue, + withTiming, +} from 'react-native-reanimated'; -import { getAnimatedMeasures } from '../helpers'; +import { getAnimatedMeasures } from '../../helpers'; -const InputAnimationWrapper: React.FC = () => { - const inputRef = useAnimatedRef(); +interface InputAnimationWrapperProps { + scrollY: Animated.SharedValue; + scrollViewHeight: Animated.SharedValue; + contentHeight: Animated.SharedValue; + keyboardHeight: Animated.SharedValue; + isKeyboardVisible: Animated.SharedValue; + isInputFieldFocused: Animated.SharedValue; + isScrollable: Animated.SharedValue; +} + +const InputAnimationWrapper: React.FC = ({ + scrollY, + scrollViewHeight, + contentHeight, + keyboardHeight, + isKeyboardVisible, + isInputFieldFocused, + isScrollable, + children, +}) => { + const animatedRef = useAnimatedRef(); const positionY = useSharedValue(0); const translationY = useSharedValue(0); + const animatedStyle = useAnimatedStyle(() => ({ + position: 'absolute', + zIndex: 999, + height: windowHeight, + backgroundColor: 'transparent', + bottom: translationY.value, + })); + + const { height: windowHeight } = useWindowDimensions(); /* TODO: - Ensure that translation Y is right above keyboard. The value is probably coming from the outside - Add flexibility to input position + */ + useEffect(() => { + if (animatedRef?.current) { + getAnimatedMeasures({ + ref: animatedRef, + callback: ({ y }) => { + if (positionY.value !== y) { + positionY.value = y; + } + }, + }); + } + }); + useAnimatedReaction( + () => isInputFieldFocused, + (curr, prev) => { + if (curr.value) { + const keyboardYPosition = windowHeight - keyboardHeight.value; + const diff = positionY.value - keyboardYPosition; - if (isMounted.value && measureRef?.current) { - getAnimatedMeasures({ - ref: measureRef, - callback: ({ height }) => { - const snapPointBottom = - height > 0 ? height - configSnapPointBottom - (extraSnapPointBottomOffset ?? 0) : 0; - - onOpenOrCloseCardRequest({ - closeBottomSheetRequest, - openBottomSheetRequest, - isCardCollapsed, - snapEffectDirection, - scrollViewRef, - scrollY, - isAnimationRunning, - translationY, - snapPointBottom, + // console.log('InputfField is focused', { + // keyboardHeight: keyboardHeight.value, + // contentHeight: contentHeight.value, + // positionY: positionY.value, + // keyboardYPosition, + // windowHeight, + // diff, + // }); + + translationY.value = withTiming(-50, { duration: 250 }, isAnimationDone => { + if (isAnimationDone) { + console.log('animation is done'); + } }); - }, - }); + } + }, + [isInputFieldFocused], + ); -} -*/ + return ( + + {children} + + ); }; + +export default InputAnimationWrapper; diff --git a/src/components/InputField/Regular.tsx b/src/components/InputField/Regular.tsx index 9d10df4..8d5ceda 100644 --- a/src/components/InputField/Regular.tsx +++ b/src/components/InputField/Regular.tsx @@ -9,16 +9,14 @@ interface InputFieldProps { const AVAILABLE_SPACE_DESKTOP = 68; const AVAILABLE_SPACE_MOBILE = 38; -const TextInput = styled.TextInput` - flex: 1; -`; +const TextInput = styled.TextInput``; const Regular: React.FC = ({ placeholder }) => { const TEXT_INPUT_STYLE = { padding: 6, fontSize: 40, fontWeight: 'bold', - color: 'white', + color: 'black', textAlign: 'center', outline: 'none', borderWidth: 3,