React Native WebView rendering unexpected border at bottom - ios

This is a little tricky to describe. I'm using a react native WebView component to make a mini-browser. It's working ok, but there's a strange black border at the bottom of it which I didn't put in. It appears when scrolling to or beyond the bottom of the webpage.
You can see the thin black line above the "blah" text below. The reason for the blah text and the pink section at the bottom was to rule out a stray borderBottom* style on the WebView or its container.
Another thing to note is that the border briefly disappears when reloading the page, so it seems it's in the WebView's html. But I don't understand how or why, because a) it appears on all websites and b) it doesn't appear in other iOS browsers.
Am I doing something strange here?
Screenshot:
Elements and Styles:
<View style={styles.container as any}>
<View style={styles.header as any}>
{this.addressbarButtonProps().map(props => React.createElement(Button, { ...props, key: props.title }))}
<TextInput
ref={ADDRESSBAR_REF}
placeholder="type url"
style={{ minWidth: this.screenWidth - 50 * this.addressbarButtonProps().filter(b => !b.hidden).length - 10 }}
/>
</View>
<WebView
ref={WEBVIEW_REF}
source={{uri: this.state.uri}}
style={{ ...styles.web, width: this.screenWidth, paddingBottom: 0, padding: 0 }}
scalesPageToFit={true}
allowsInlineMediaPlayback={true}
onMessage={m => this.onMessage(m.nativeEvent.data)}
injectedJavaScript={js}
startInLoadingState={true}
/>
<Text style={{ borderTopWidth:20, borderTopColor: "red" }}>blah</Text>
</View>
const styles = {
container: {
paddingTop: 20,
flex: 1,
alignItems: "center",
justifyContent: "space-between",
backgroundColor: "#fafafa",
borderBottomColor: "pink",
borderBottomWidth: 100
},
header: {
flexDirection: "row",
alignItems: "flex-start",
justifyContent: "flex-start",
alignSelf: "stretch"
},
web: {
flex: 1,
borderBottomColor: "#fafafa",
backgroundColor: "#fafafa"
}
}

Set the backgroundColor of the WebView to transparent and the "border" won't be rendered.
<Webview style={{backgroundColor: 'transparent'}} .../>

Related

React Native - Scrollview scrolls up with many inputs [iOS]

I have many inputs within ScrollView. Everytime I try to tap the Save button, if the last input focused is out of the screen view (where the Save button is), the screen scrolls automatically up to the input. However, if I scroll down again and press/tap the Save button again, it works. So I have to tap twice the button.
This only happens on iOS devices. On Android works perfectly.
Here is my code:
render() {
const keyboardVerticalOffset = Platform.OS === "ios" ? 40 : 0;
return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : ""}
keyboardVerticalOffset={keyboardVerticalOffset}
style={styles.container}
>
<View
style={{
flexDirection: "column",
justifyContent: "space-between",
height: "100%",
backgroundColor: colors.white,
}}
>
<ScrollView
ref={(scroll) => (this.scroll = scroll)}
keyboardShouldPersistTaps={'handled'}
style={{
marginBottom: this.state.marginBottom,
paddingHorizontal: 20,
}}
>
<DateForm
onChangeDate={this.onChangeDate.bind(this)}
date={this.state.measureDate}
birthdate={this.state.baby.Birthdate}
/>
<MeasureForm
onChangeMeasure={this.onChangeValue.bind(this)}
value={this.state.value}
scrollTo={this.scrollTo.bind(this)}
/>
<ResultsForm
IC={this.state.indexes.IC}
IABC={this.state.indexes.IABC}
colorIC={this.state.indexes.colorIC}
colorIABC={this.state.indexes.colorIABC}
/>
<CBButton
title={global.loc.getTranslation("AddMeasureSaveButton")}
style={{
width: "100%",
marginHorizontal: 0,
flexGrow: 1,
marginTop: 20,
marginBottom: 50,
}}
disabled={!this.state.validForm}
onPress={() => this.disableButton()}
/>
</ScrollView>
</View>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
UPDATE
Here is a minimal reproducible example on snack

KeyboardAvoidingView not working properly in iOS

I'm having trouble getting my KeyboardAvoidingView to register properly on the iOS version of my react-native app. It's nested within another view in my ListFooterComponent of a Flatlist. The behavior is relatively normal on Android, but is not working at all on iOS.
Things I've tried:
Changing the behavior prop (all 3 props didn't end up working)
Changing the keyboardVerticalOffset prop (no amount of offset managed to change anything, it just adds a bunch of padding to the bottom of the screen)
Moving my KeyboardAvoidingView tag to the outermost view in ListFooterComponent. No difference
Adding flex: 1 to inner and outer components
I have seen other posts recommending using other keyboard avoidance libraries, but since this is an Expo Managed project, I don't think these will work for me. Any advice for how to accomplish this using the KeyboardAvoidingView component only?
This is a screenshot of the screen without a keyboard on iOS: this
And this is a screenshot of with a keyboard on iOS: this
And here's the code:
<SafeAreaView style={{ flex: 1 }}>
<FlatList
data={commentData}
style={{ flex: 1 }}
keyboardDismissMode={'on-drag'}
keyboardShouldPersistTaps={'always'}
keyExtractor={item => (item.id)}
renderItem={({ item }) => {
return (
<>
</>
)
}}
ListFooterComponent={() => {
return (
<>
<View style={{ borderColor: "#D6DCE8", marginBottom: 0, borderTopWidth: 2, marginTop: 25, shadowColor: "#000", shadowRadius: 2, shadowOpacity: 0.25, shadowOffset: { width: 0, height: 2 }, elevation: 5 }} />
<View style={{ flex: 1, flexDirection: 'row', paddingTop: 15, paddingBottom: 15 }}>
<TouchableOpacity delayPressIn={20}>
<View style={styles.commentImage}>
<Image source={{ uri: myProfilePicture }} style={styles.image}></Image>
</View>
</TouchableOpacity>
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
keyboardVerticalOffset={Platform.select({ ios: 100, android: 500 })}
style={{ flex: 1, backgroundColor: '#ECECEC', borderRadius: 10, flex: 0.95, paddingVertical: 5, marginLeft: 10 }}>
<TextInput style={{
fontSize: 14,
fontWeight: '500',
paddingHorizontal: 10,
marginHorizontal: 10,
paddingVertical: 6,
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap'
}}
ref={commentRef}
multiline={true}
blurOnSubmit={true}
numberOfLines={2}
onFocus={() => commentRef.current = true}
onBlur={() => commentRef.current = false}
placeholder="Leave a comment..."
defaultValue={comment}
onChangeText={(newValue) => { comment = newValue }}
onSubmitEditing={() => submitComment()} />
</KeyboardAvoidingView>
</View>
<View style={Platform.OS === 'android' ? { marginBottom: 200 } : { marginBottom: 100 }} />
</>
)
}}
ListHeaderComponent={() => {
return (
<>
</>
)
}}
/>
</SafeAreaView>
For the above layout, use KeyboardAvoidingView above FlatList in your hierarchy, and place the comment box not as the footer, but outside of the list component altogether.
Here's a snack with these changes (OP's code simplified for context): https://snack.expo.dev/#mlisik/thankful-tortilla
A few general notes:
padding behaviour should be what you want
keyboarVerticalOffset is useful if your view is nested inside a navigator (eg. from react-navigation), and navigation bar or tabbar are visible - you should then set the value to the height of those bars
disable it on Android (unless you have disabled keyboard/soft input handling in your manifest).

React native, shoutem/ui : navigating back on NavigationBar does not work on iOS

I am struggling to make back navigation arrow on shoutem/ui NavigationBar work on iOS. The navigation bar looks like this and works on Android as expected (tap on the arrow navigates to specific predefined view) :
The related layout is as follows :
import {
Text,
Button,
View,
Image,
Divider,
Spinner,
NavigationBar,
Caption
} from '#shoutem/ui';
render() {
const {navigate} = this.props.navigation;
if (this.state.submitted && this.props.loading) {
return (
<Spinner style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}} />
);
}
return (
<Container style={{ flex: 1, backgroundColor: '#ffffff' }}>
<Content>
<NavigationBar
styleName='no-border'
hasHistory
navigateBack={() => navigate('WelcomeScreen')}
/>
<Grid>
<Row style={{ height: 100, justifyContent: 'center', alignItems: 'center', paddingTop: 100 }}>
<Image
style={{ width: 96, height: 89 }}
source={require('../login-logo.png')}
blurRadius={1} />
</Row>
//some other rows and columns
</Grid>
</Content>
</Container>
);
}
}
On Android the following works as expected. On iOS (Xcode simulator) the navbar is displayed correctly, however tapping on it does nothing. No log events nor errors are generated as well. I assume that the navbar can somehow be overlaid by some other element. However, the same problem exists with the other views with different elements inside the grid below the navbar. Does anyone have experience with this issue? What is the most likely cause and what am I doing wrong?
The "no-border" styleName applied to NavigationBar turned out to be the offending code piece in this case. Replacement with "inline" worked around the issue while introducing a slightly distinguishable border below the NavigationBar. However, this looks like a bug and the following issue has been opened in shoutem/ui GitHub repository : https://github.com/shoutem/ui/issues/398

iOS ReactNative: Text not wrapping and displaying off-screen

I seem to have a problem with a simple text field. The text inside is not wrapping. I'm running on an iOS 5s simulator. Any ideas?
Following the tutorial here: http://www.raywenderlich.com/99473/introducing-react-native-building-apps-javascript
Styles:
var styles = StyleSheet.create({
description: {
marginBottom: 20,
fontSize: 18,
textAlign: 'center',
color: '#656565',
},
container: {
padding: 30,
marginTop: 65,
alignItems: 'center',
},
Code:
<View style={styles.container}>
<Text style={styles.description}>
Search for houses to buy!
</Text>
<Text style={styles.description}>
Search by place-name, postcode or search near your location!
</Text>
</View>
I ran the exact code on rnplayground simulator, but the text did wrap correctly. If you had an outside flex container, you may need to specify the flexWrap property to 'wrap'.
rnplay.org/apps/x0Xf6w

React Native Text component will not center inside a View component

Hi I think this should be simple, but I cannot get it to work. Seems like no matter what I do, I cannot get the text component to center horizontally inside the view. I have tried using alignItems:center, justifyContent:center, alignSelf:center, textAlign:center... nothing works. I can get it to center vertically, but not horizontally. Whyyyyy dear lord?
<Animated.View style={[styles.titleContainer]}>
<Text style={styles.title}>App logo here</Text>
</Animated.View>
How can I get the text to center both vertically and horizontally?
Here is my CSS:
titleContainer: {
flex: 1,
marginTop:30,
marginBottom:30,
justifyContent:'center'
},
title:{
color:'white',
textAlign:'center',
alignSelf:'center'
},
This is my result:
Try this...
Here's a working demo
container: {
flex: 1,
marginTop: 30,
marginBottom: 30,
justifyContent: 'center',
backgroundColor: '#fff',
},
title: {
fontSize: 28,
textAlign: 'center',
},
For anyone looking for a minimal version for the simplest case:
<View style={styles.containerView}>
<Text style={styles.centeredText}>I'm centered</Text>
</View>
const styles = StyleSheet.create({
containerView: {
justifyContent: 'center'
}
centeredText: {
alignSelf: 'center'
}
})
Align Self
Add justifyContent: 'center' to the container view.
React native works different to react.
So alignItems not working, instead justifyContent works.
use textAlign: 'center' property to center text
use alignSelf:'center' property to center View
<View style={{alignSelf:'center'}}>
<Text style={{textAlign:'center'}}>I'm centered</Text>
</View>
set in main View style flex:1 and in Text set textAlign:'center'
Adding flexDirection:'column' helps the items to be aligned centrally column by column:
titleContainer: {
flex: 1,
marginTop:30,
marginBottom:30,
justifyContent:'center',
},
title:{
color:'white',
textAlign:'center',
alignSelf:'center',
flexDirection: 'column'
},

Resources