Open MarceloPrado opened 1 year ago
Hi @MarceloPrado
It seems like interpolatedScrollTo
has incorrect values. In example app I didn't encounter such behaviour. Try to console.log
the value and try to understand why it's bigger than expected :) The idea was to interpolate keyboardHeight
to distance
(like keyboard height is 200
, but you'll need to scroll only 20
px, so we interpolate 200 to 20).
I believe this would be a great addition to the component, since it enables a more seamless migration from react-native-keyboard-aware-scroll-view
Yes, I agree with it. I had a plan to include this component in the library (like an alternative to react-native-keyboard-aware-scroll-view
), but with better animations. However I don't like the approach with capturing touch point on a screen - instead we should get coordinates of text input and I'm currently working on it. The near plan is to release 1.6.0
version with the support for synchronous calculation of layout in worklets and then release 1.7.0
with pre-bundled components (KeyboardAvoidingView
/KeyboardAwareScrollView
).
P. S. that's how KeyboardAwareScrollView
works in example app:
Awesome, I agree with your take on capturing the input coordinates instead of the view. And thanks for the demo and explanation, will debug what I'm doing wrong.
Figured out what happened. I was passing flex: 1
to the scroll view's contentContainerStyle
. This caused a lot of issues. Once I removed it, the base code from /examples
worked great!
@kirillzyusko I think I need your input here. I noticed the provided example doesn't work properly if you need the scroll view's content to fill the available space.
Once I add flexGrow: 1
to the contentContainerStyle
, and center the content, here's what happens:
While it works smoothly without the flex-grow, if you need to center the content of the scroll view, you have no workaround. Have you seen this before?
Minimal repro:
const styles = StyleSheet.create({
centered: {
alignItems: "center",
flex: 1,
justifyContent: "center",
},
container: {
flex: 1,
},
contentContainer: {
backgroundColor: "#f7d7d7",
flexGrow: 1,
},
});
const Centered: FC<{ children: ReactNode }> = ({ children }) => (
<View style={styles.centered}>{children}</View>
);
function randomColor() {
return "#" + Math.random().toString(16).slice(-6);
}
export function AwareScrollView() {
useResizeMode();
return (
<KeyboardAwareScrollView
contentContainerStyle={styles.contentContainer}
style={styles.container}
>
<Centered>
{new Array(4).fill(0).map((_, i) => (
<TextInput
key={i}
placeholder={`${i}`}
placeholderTextColor="black"
style={{
width: "100%",
height: 50,
backgroundColor: randomColor(),
marginTop: 50,
}}
/>
))}
</Centered>
</KeyboardAwareScrollView>
);
}
Hi @MarceloPrado No, I haven't seen this before. I'll try to have a look on your code tomorrow or in nearest days π
That's strange - current behaviour looks like a KeyboardAvoidingView π€·ββοΈ I think it should be fixable anyway, because you have all variables to calculate the trajectory of content movement, but I'll try to have a look when I have free time for that!
Hi @kirillzyusko, just a friendly ping - had you had any time to investigate this issue? Thanks in advance!
Hi @MarceloPrado
Not exactly this issue, but I've got some requests of what could be improved in the library when you have to deal with avoiding functionality and I was busy with that - was trying to design a new API/integrate new functionality into existing methods and got some success.
New KeyboardAwareScrollView
handles more cases - it has stable bottom-padding (right now it depends on touch area and sometimes keyboard can be very close to the input), it handles TextInput switches when keyboard is open, and I believe can even handle case when multiline TextInput growsπ
Overall the new version of KeyboardAwareScrollView
feels like a much better version/revision of what I had before, so my plan is to prepare a new release (1.6.0) and include a new enhanced API, and once it's done - I'll get back to this issue π
My expectation is that new release preparation will take about a month and after that I will switch to resolving all opened issues including this oneβΊοΈ
That's awesome @kirillzyusko, I'm happy to hear you're coming up with a more powerful API. This is such an important (and hard) problem in the current React Native ecosystem π
I hope everything works out as you expect in the new API. Let me know if you need any help testing these cases, happy to help.
when i focus on TextInput 5, it is a space between textinput and keyboard. how can i make it exaclty fit ?
@NguyenHoangMinhkkkk this is because everything depends on touch area (if you are using version below 1.5.8
).
In 1.6.0
it'll be possible to measure layout without relying on touch area - just for reference https://github.com/kirillzyusko/react-native-keyboard-controller/commit/95a5376ac5062f1a6379d89d009ad3cc8681eb25
@MarceloPrado I had a look on this problem. It happens because AwareScrollView
adds <Reanimated.View style={view} />
below all children.
Since your content is in center and you add an empty view - your content will be pushed up to stay in the center. To overcome this problem you can use contentInset
:
const props = useAnimatedProps(() => ({
contentInset: {
bottom: fakeViewHeight.value,
},
}));
return (
<Reanimated.ScrollView
ref={scrollViewAnimatedRef}
{...rest}
onScroll={onScroll}
animatedProps={props}
scrollEventThrottle={16}
>
{children}
{/*<Reanimated.View style={view} />*/}
</Reanimated.ScrollView>
Such inset don't affect content position, but it works only on iOS (since contentInset
is iOS specific property). I've tested and this problem is present on Android too, so I need more time to find a proper solution π
BTW if you have any suggestions how to fix this problem - I'll be glad to hear them π
@kirillzyusko
New version 1.7.0 with Aware Scroll View & KeyboardAvoidingView is amazing. The only problem that I figure out while testing is IOS behavior.
Aware Scroll View issue:
Attaching detailed demo:
As you said before I believe it takes much more time to investigate all these moments including multiline input handling.
Thanks a lot for your job, you made a huge impact for resolving a painful Keyboard handling for react-native π.
@VladyslavMartynov10 is it iOS feature to scroll to the input if it's not visible and you are typing something? Or iOS just dispatched onStart/onEnd events from keyboard lifecycle?
Basically, if you need to maintain TextInput visible while typing - you can achieve that just by calling maybeScroll
when onTextChanged
is fired (of course with some debounce in order not to overuse CPU).
I'm not sure if iOS has this functionality out of the box, but it seems that only 'onStart' and 'onEnd' events are dispatched during the keyboard lifecycle. Thanks for the maybeScroll
idea, I will investigate.
@VladyslavMartynov10 I investigated this topic a little bit more and it seems like iOS fires keyboardWillShow
/keyboardDidShow
events when user types a first symbol in TextInput
:
I don't know why it happens in this way, but it seems like Apple engineers needed in this functionality π
So I'd suggest you to go with calling maybeScroll
when onTextChanged
event is fired (with debounce/throttle). In this case your focused TextInput
will always remain above the keyboard even if the user scrolled it to invisible part of the screen.
@kirillzyusko Thanks!
Recently I've created the new Swift UI project in order to be sure that the problem lies in IOS implementation itself. This feature is not supported out of box, so we have to create our own logic. I don't know why Apple doesn't include it, sounds funny π .
So yeah maybeScroll
is the most convenient solution in this case :)
@kirillzyusko sorry for the delay, if possible, let's try keeping this issue to the original thread to ensure we're all talking about the same thing π
To recap for everyone, the existing KeyboardAwareScrollView
adds a "dummy" Reanimated view at the bottom that grows in size relative to the keyboard progress. This is what enables the view to actually scroll once the keyboard is shown. However, there's a downside: if you need a vertically centered scroll view, this implementation causes your view to scroll even in unwanted cases as seen here.
@kirillzyusko I have to spend some time prototyping. One immediate approach I can think of is to add a top "dummy" view to counter the bottom one in this case. I'm not sure how the "syncing" would happen. Not very fond of this since it's easy to get messy.
One other way: when the keyboard is shown, I think it's valid to assume we don't want to "respect" the vertically centered layout. I wonder if we could de-activate flexGrow: 1
/flex: 1
once progress > 0 ?
I have to spend some time prototyping. One immediate approach I can think of is to add a top "dummy" view to counter the bottom one in this case. I'm not sure how the "syncing" would happen. Not very fond of this since it's easy to get messy.
@MarceloPrado Cool idea. I think it will compensate the movement, but in casual scenarios (when you have a lot of TextInputs and they take more space than height of the screen) after keyboard is shown you'll be able to scroll to top and you will see this "fake" view.
One other way: when the keyboard is shown, I think it's valid to assume we don't want to "respect" the vertically centered layout. I wonder if we could de-activate flexGrow: 1/flex: 1 once progress > 0 ?
@MarceloPrado we can de-activate these styles by setting undefined
and I think it could be a good option to try π Need to experiment to see whether such approach is not causing additional problems (such as layout jump, etc.).
I've also tried to use react-native-keyboard-aware-scrollview
to see whether this package has the same problem. And on iOS this package doesn't have this problem because they are setting contentInset
(I haven't tested Android, but may assume, that this OS has the same problem).
Another approach that I was going to check was to use react-native-avoid-softinput
and see how such layout is handled there and whether it has the same problem as described here π
@kirillzyusko
Recently I was trying to migrate to new version 1.9.4 and lost scroll-to-focused input effect at least on Android. For now when the input is focused and under keyboard, maybeScrollCallback never fires.
I've realised that we've got a discussion before https://github.com/kirillzyusko/react-native-keyboard-controller/issues/168#issuecomment-1712495008 with the support of this feature, but I think it should be handled somehow on native side in order to avoid multiple calls of the same callback in RN.
Any ideas how it can be achieved without reinventing the wheel & performance lost? Thanks beforehand π!
Hello @VladyslavMartynov10 π
Would you mind to create a new issue? I remember your problem (to keep focused input in visible area while user is typing) and I have some ideas on how to handle it on a KeyboardAwareScrollView
level without adding code on user components level.
So, please, create a new issue and we will discuss an approach with you there (don't want to mix different problems in this single issue).
Hello @VladyslavMartynov10 π
Would you mind to create a new issue? I remember your problem (to keep focused input in visible area while user is typing) and I have some ideas on how to handle it on a
KeyboardAwareScrollView
level without adding code on user components level.So, please, create a new issue and we will discuss an approach with you there (don't want to mix different problems in this single issue).
@kirillzyusko Did it
Another workaround was discovered in #405 - you can specify minHeight
so that the content in KeyboardAwareScrollView
will not be resized. So code can look like:
const STATUS_BAR_HEIGHT = 44;
const HEADER_HEIGHT = 56;
const styles = StyleSheet.create({
centered: {
alignItems: "center",
flex: 1,
justifyContent: "center",
minHeight:
Dimensions.get("window").height - STATUS_BAR_HEIGHT - HEADER_HEIGHT, // <- fix is here
},
container: {
flex: 1,
},
contentContainer: {
backgroundColor: "#f7d7d7",
flexGrow: 1,
},
});
const Centered: FC<{ children: ReactNode }> = ({ children }) => (
<View style={styles.centered}>{children}</View>
);
function randomColor() {
return "#" + Math.random().toString(16).slice(-6);
}
export default function AwareScrollView() {
useResizeMode();
return (
<KeyboardAwareScrollView
contentContainerStyle={styles.contentContainer}
style={styles.container}
>
<Centered>
{new Array(4).fill(0).map((_, i) => (
<TextInput
key={i}
placeholder={`${i}`}
placeholderTextColor="black"
style={{
width: "100%",
height: 50,
backgroundColor: randomColor(),
marginTop: 50,
}}
/>
))}
</Centered>
</KeyboardAwareScrollView>
);
}
Describe the bug I'm trying to replicate the
KeyboardAwareScrollView
behavior fromreact-native-keyboard-aware-scroll-view
. Using the KeyboardAwareScrollView found in/examples
, I noticed the scroll view scrolls more than it needs to:https://github.com/kirillzyusko/react-native-keyboard-controller/assets/8047841/ecd6d68a-7525-4972-9965-304352661e4b
Notice how once I press the input with the
scroll begins here
placeholder, it scrolls much further than it should. I'm trying to make the input align with my sticky action bar (it should be a fixed amount above the sticky bar).Code snippet I used the code from your examples folder, with one modification:
I added an if/else branch that skips scrolling when the click wouldn't overlap with the keyboard + bottom offset. Now, I need to figure out the right interpolation math that causes the view to scroll only by the right/minimum amount.
note:
extraScrollHeight
is a prop, similar to yourBOTTOM_OFFSET
.Let me know if I can help with more details! I believe this would be a great addition to the component, since it enables a more seamless migration from
react-native-keyboard-aware-scroll-view
.