scrollview can't scroll when focus textinput react native - android-edittext

I have a TextInput inside a ScrollView.
The scroll isn't working when the TextInput is on focus. This problem is only affecting Android.

setting
<ScrollView keyboardShouldPersistTaps="always"
in combination with the textInput component below (custom component that i created for text inputs to solve this issue) solved my problem:
<TouchableOpacity
activeOpacity={1}
onPress={()=>this.input.focus()}>
<View pointerEvents="none"
<TextInput
ref = {(input) => this.input = input}
/>
</View>
</TouchableOpacity>

In scrollView use keyboardShouldPersistTaps
<ScrollView keyboardShouldPersistTaps="handled">
it solve your problem
check docs here https://facebook.github.io/react-native/docs/scrollview.html#keyboarddismissmode

That is the expected behavior.
For more information Official TextInput documentation
You might want to try something like this: react-native-kayboard-aware-scroll-view

i use simple trick for TextInput and that work for me correctly .Should add this prop in TextInput :
<TextInput
multiline={true}
numberOfLines={1}
/>

This is a very good example: http://blog.arjun.io/react-native/mobile/cross-platform/2016/04/01/handling-the-keyboard-in-react-native.html
The thing that was really important for me was to add:
android:windowSoftInputMode="adjustResize"
in AndroidManifest.xml in order to focus the textInput

I handle in different ways to each platform (in Ios focus to inputText is enough,
don't forget to put this.scrollViewRef ref inside ScrollView that wrap inputText and put ref index the inputText
if (Platform.OS == 'android') {
this.inputRefs[field].measure((w, h, px, py, xPage, yPage) => {
this.scrollViewRef.scrollTo({ x: 0, y: yPage, animated: true })
this.inputRefs[field].focus()
})
}
this.inputRefs[field].focus()

Related

Can't press TouchableOpacity when keyboard is up. I need to double press it. React Native

I am making a comments section for my app with React-Native and building for ios. When the keyboard is up to post a comment I can't immedietley press the TouchableOpacity button that submits the post. I need to first press it to close the keyboard then press again to submit.
const CommentCreation = React.forwardRef((props, ref) => {
return (
<View style={commentCreationStyles.container} >
<TextInput
value={props.message}
ref={ref}
style={commentCreationStyles.input}
onChangeText={val => props.setMessage(val)}
autoFocus={false}
multiline={true}
returnKeyType={'next'}
placeholder={'Enter Your Comment'}
numberOfLines={5}
replyBool={props.replyBool}
/>
<TouchableOpacity
style={commentCreationStyles.submitButton}
onPress={props.addCommentEnabled ? () => {props.addComment(); Keyboard.dismiss()} : null}
>
<Ionicons name="ios-send" size={36} color="#D7D7D7" />
</TouchableOpacity>
</View>
)
})
I have tried keyboardShouldPersistTaps="handled" and its variations in conjunction with ScrollView in addition to View and replacing View. I have tried these on all levels of the tree. I'm at a loss, any help is greatly appreciated!
Add keyboardShouldPersistTaps='handled' in the first View as
<View style={commentCreationStyles.container} keyboardShouldPersistTaps='handled' >

How to set height of React Native Webview? [duplicate]

Hi I know it's a known issue about the auto height of webview in react native,
and I have tried all the possibles solutions I've found on the internet such as :
https://gist.github.com/epeli/10c77c1710dd137a1335
https://github.com/danrigsby/react-native-web-container/blob/master/index.js
and all the solutions suggested in:
React native: Is it possible to have the height of a html content in a webview?
But unfortunately none of these seems to work for me,
I understand that the workaround they all suggest is to set the title to the height, but in my case it seems that the title always stays the same which is :
"text/html ...." and the rest of my html.
I get the html content from an API, it comes without a body, head or html tags, I've also tried adding these tags manually to the html and nothing seems to work.
I would love to hear if anyone else had that problem and how did it get fixed.
I wrap WebView inside a View, and set the height from the View.
<View style={{ height: 200 }}>
<WebView
automaticallyAdjustContentInsets={false}
source={{uri: 'https://player.vimeo.com/video/24156534?title=0&byline=0&portrait=0'}}
/>
</View>
I just follow this guide: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#communicating-between-js-and-native and succeeded in my work. Here is solution:
1. Define script to send document height to native env after loaded website.
2. Handle onMesssage of webview component and reset Height via state.
const webViewScript = `
setTimeout(function() {
window.postMessage(document.documentElement.scrollHeight);
}, 500);
true; // note: this is required, or you'll sometimes get silent failures
`;
...
constructor(props) {
super(props);
this.state = {
webheight:100,
}
...
<WebView style={{height: this.state.webheight}}
automaticallyAdjustContentInsets={false}
scrollEnabled={false}
source={{uri: "http://<your url>"}}
onMessage={event => {
this.setState({webheight: parseInt(event.nativeEvent.data)});
}}
javaScriptEnabled={true}
injectedJavaScript ={webViewScript}
domStorageEnabled={true}
></WebView>
Hope that help!
A reliable implementation of this behavior is with useAutoheight hook from #formidable-webview/webshell library.
The latter allows to inject "features" into WebViews, e.g. scripts and behaviors.
In this example, we will use 3 features + the aforementioned hook:
HandleHTMLDimensionsFeature which is required by useAutoheight hook to get document size updates;
ForceResponsiveViewportFeature to work around mobile virtual viewport;
ForceElementSizeFeature to work around cyclic size constraints
This component should work with any webpage.
import React from 'react';
import makeWebshell, {
HandleHTMLDimensionsFeature,
ForceResponsiveViewportFeature,
ForceElementSizeFeature,
useAutoheight
} from '#formidable-webview/webshell';
import WebView from 'react-native-webview';
const Webshell = makeWebshell(
WebView,
new HandleHTMLDimensionsFeature(),
new ForceResponsiveViewportFeature({ maxScale: 1 }),
new ForceElementSizeFeature({
target: 'body',
heightValue: 'auto',
widthValue: 'auto'
})
);
export default function ResilientAutoheightWebView(props) {
const { autoheightWebshellProps } = useAutoheight({
webshellProps: props
});
return <Webshell {...autoheightWebshellProps} />;
}
More resources:
Try this on Expo
Full guide here.
Using postMessage and onMessage like below worked for me perfectly.
Credit to iamdhj
onWebViewMessage = (event: WebViewMessageEvent) => {
this.setState({webViewHeight: Number(event.nativeEvent.data)})
}
render() {
return (
<ScrollView>
<WebView
style={{ height: this.state.webViewHeight }}
source={{html: '...'}}
onMessage={this.onWebViewMessage}
injectedJavaScript='window.ReactNativeWebView.postMessage(document.body.scrollHeight)'
/>
</ScrollView>
)
}
The WebView has default styles. If you want to set height, you also need to add flex: 0, as stated in the documentation:
Please note that there are default styles (example: you need to add flex: 0 to the style if you want to use height property).
I made a little component to make this functionality reusable if it helps anyone!
import React, { useState } from "react";
import WebView from "react-native-webview";
const DynamicHeightWebView = (props) => {
const [height, setHeight] = useState(0);
const webViewScript = `
setTimeout(function() {
window.ReactNativeWebView.postMessage(document.documentElement.scrollHeight);
}, 500);
true; // note: this is required, or you'll sometimes get silent failures
`;
return <WebView
{...props}
style={{
...props.style,
height: height,
}}
automaticallyAdjustContentInsets={false}
scrollEnabled={false}
onMessage={event => {
setHeight(parseInt(event.nativeEvent.data));
}}
javaScriptEnabled={true}
injectedJavaScript ={webViewScript}
domStorageEnabled={true}
useWebKit={true}
/>
}
export default DynamicHeightWebView;
Apparently the problem was I had javaScriptEnabled={false}.
After enabling it everything worked.
I waste whole day to fix the height issue but in the end I had to shift to another library
This one is easy and good
https://github.com/archriss/react-native-render-html
You can get the content height by injecting the JS code as suggested by #ken-ratanachai-s. Although, You will experience certain irregularities in some devices (Extra height after the content). This is becuase the javascript returns the content height in pixels, but we need to use display points in react native. To fix this, Divide the height from javascript with the pixel ratio as follows.
import { WebView, PixelRatio } from 'react-native'
const [webviewHeight, setWebviewHeight] = useState(0)
const onProductDetailsWebViewMessage = event => {
setWebviewHeight(Number(event.nativeEvent.data)/PixelRatio.get())
}
return <WebView
originWhitelist={['*']}
style={{ height: productDetailsWebviewHeight }}
onMessage={onProductDetailsWebViewMessage}
injectedJavaScript='window.ReactNativeWebView.postMessage(document.body.scrollHeight)'
source={{ html: "..." }}
/>
Pixel ratio ref.: https://reactnative.dev/docs/pixelratio
Courtesy: https://stackoverflow.com/a/65976827/5321660
use package react-native-autoheight-webview
I recommend react-native-autoheight-webview.
it perfect work for me.
https://github.com/iou90/react-native-autoheight-webview
UPDATE:
Best answer is #Ken Ratanachai S.'s answer.
https://stackoverflow.com/a/65976827/9757656

React Native TouchableHighlight in Listview ignores the first click event

I have this issue in both iOS Simulator and in real device too.
I have a Listview with Touchablehighlight. When i press the list at first, it ignores. It only functions when it is double clicked.Can anyone help me out with this.
Here i have a piece of code, that is inside my render function
<ListView dataSource= {ds.cloneWithRows(this.state.searchedAdresses)}
renderRow={this.renderAdress}
renderSeparator={this._renderSeperator}
enableEmptySections={true}
automaticallyAdjustContentInsets={false}
/>
renderAdress = (rowData, sectionID, rowID) => {
return (
<TouchableHighlight onPress = {this._onPressAddressList.bind(this,rowData.place_id,rowData.description)}underlayColor = '#a9a9a9' >
<View shouldRasterizeIOS={true} renderToHardwareTextureAndroid={true}>
<Text style={ styles.listTextInput } >{rowData.description</Text>
</View>
</TouchableHighlight>
);};
Thank you
I can think of 2 cases:
You have TextInput gaining the focus and when you tap your list view item the first time it removes focus from the input and hides the keyboard. This is described here.
They reported that this is an issue with emulator.

React Native iOS TextInput: switching secureTextEntry switches font

I want to implement show password feature in TextInput in React Native 0.30.0. I've implemented 'eye' button next to TextInput which change state of passwordHidden state variable. Here is my code:
...
<View style={[styles.passwordWrapper, styles.textInputBorder]}>
<TextInput
autoCapitalize={'none'}
autoCorrect={false}
clearButtonMode={'while-editing'}
style={[styles.textInput, styles.passwordInput]}
onChangeText={(password) => this.onPasswordChange(password)}
value={this.state.password}
secureTextEntry={this.state.passwordHidden}
multiline={false}
placeholder={Strings.password}
underlineColorAndroid={Colors.surfacePrimary}
/>
<TouchableOpacity style={styles.showPasswordButton} onPress={this.onPressShowPassword}>
<EntypoIcon color={Colors.surfacePrimary} name={this.state.passwordHidden ? 'eye' : 'eye-with-line'} size={20} />
</TouchableOpacity>
</View>
...
onPressShowPassword: function () {
var previousState = this.state.passwordHidden;
requestAnimationFrame(() => {
this.setState({
passwordHidden: !previousState,
});
});
},
Here's how password TextInput looks before clicking on button.
And after clicking:
And when I tap third time and start type then password is immediately cleared. I am not changing fontFamily in styles even in entire app.
Anybody can explain what is going on? Or just how to overcome that annoying behavior.
Workaround that is working for me, is removing focus from TextInput, when user clicks show/hide password. One way to do this, is to add ref (for example ref="password") to your TextInput and then call this.refs.password.blur()
changing the fontSize works for me:
fontSize: (this.state.showPassword) ? 24 : 23

on ios when TextInput focused it's behind keyboard (react-native)

I am using listView with TextInputs, on ios when TextInput focused it's behind keyboard. How to fix it?
Sample code: http://rnplay.org/apps/8baZSA
You need to use <ScrollView> instead of <View> in order to use this method.
The key method is scrollResponderScrollNativeHandleToKeyboard(refToElement, scrollHeight, preventNegativeOffset) (sounds cool, right ;))
I have:
<TextInput ref='ccName' onFocus={(() => this.onFieldFocus('ccName'))} />
where function looks like:
onFieldFocus(fieldName) {
this.setTimeout(() => {
let scrollResponder = this.refs.scrollView.getScrollResponder()
scrollResponder.scrollResponderScrollNativeHandleToKeyboard(
React.findNodeHandle(this.refs[fieldName]), 200, true
)
}, 125)
}
Seems this thread is what you're looking for.
TL;DR: see this stackoverflow question

Resources