React Native: WebView height isn't being set properly - javascript

I'm having a problem with a WebView in my React Native app. When no height for the WebView is specified, it defaults to about half the screen height (iPhone 6S). However, when I set a height with the help of Dimensions, it displays fine, but only the original half is interactive – ie. can only scroll using the top half of the screen.
Here are the main parts of my current code:
import React, { Component } from 'react';
import {
...
Dimensions,
...
WebView,
} from 'react-native';
let ScreenHeight = Dimensions.get("window").height;
let ScreenWidth = Dimensions.get("window").width;
class App extends Component {
render() {
return (
<View style={styles.container}>
...
<WebView
source={{uri: 'http://foo.com'}}
style={{height: ScreenHeight, width: ScreenWidth}}
/>
...
</View>
);
}
}
...
const styles = StyleSheet.create({
container: {
backgroundColor: '#bbb',
flex: 1,
},
...
});
AppRegistry.registerComponent('myApp', () => App);
I look forward to any help that can be offered :)

It's possible that an invisible view from your render function is being drawn on the bottom half of the screen.
With out seeing the rest of the render method I couldn't tell, still worth checking.

Thanks for the answers, guys. I've fixed my issue now, and it seems to be such an easy fix. I basically wrapped the WebView in it's own View container. I'm not sure whether it wasn't working because it had sibling elements (ie. NavBar and TabBarIOS – which I left off my previous snippet – sorry!), but the WebView now works great.
Here is my new render function:
render() {
return (
<View style={styles.container}>
<NavBar>
<View>
<WebView
source={{uri: 'http://foo.com'}}
style={{height: ScreenHeight, width: ScreenWidth}}
/>
</View>
<TabBarIOS>
...
</TabBarIOS>
</View>
);
}

Try adding flex style to WebView. Your code will look like this:
<View style={styles.container}>
...
<WebView
source={{uri: 'http://foo.com'}}
style={{flex:1}}
/>
...
</View>

Related

Scrollable Background Image in React Native

I'm trying to add an image in the background of a screen which is very long and I want the image to be scrollable. Please give suggestions/code snippets for me to achieve this.
Just put the image inside a ScrollView like this
export default function App() {
return (
<>
<ScrollView >
<ImageBackground
style={{
height: 1000,
width: '100%',
}}
source={{
uri: 'https://i.stack.imgur.com/zkNF4.jpg',
}}
/>
</ScrollView>
</>
);
}
Let me know if it worked

How to put a sticky Touchable within an horizontal ScrollView in React Native?

I am trying to make a simple application/game to learn and practice React Native. Currently, I am trying to create a sticky TouchableNativeFeedback that moves with the screen as I am using the ScrollView.
The idea is that left half of the screen would move the character to the left and the right half of the screen would move it to the right. I want these controls to be fixed in the display and not move.
This is how it starts
This is after moving the scrollView a bit
I've initially tried to change value of style.left as I scrolled but that doesn't seem to be a good/stable solution.
Here is the current code:
render() {
return (
<ScrollView
//onScroll={this._onScroll}
ref={(scrollView) => { this.scrollView = scrollView; }}
style={styles.container}
horizontal= {true}
snapToAlignment={"center"}
>
<View style={styles.wrapperView}>
<ImageBackground
style={styles.container}
source={require('../images/second.png')}
>
<TouchableNativeFeedback onPressIn={this._onPressButton} onPressOut={this._onPressButton}>
<View style={
{
width: width/2,
height: '100%',
position: 'absolute',
left: this.state.touchableLeft,
backgroundColor: 'red',
}
}>
</View>
</TouchableNativeFeedback>
... (code about the character)
</ImageBackground>
</View>
</ScrollView>
);
}
and the styles code
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
},
wrapperView:{
width: width*3 + 300,
},
});
and just to have it as a reference, this is what I originally tried:
_onScroll = (event) => {
this.setState( {
touchableLeft: this.state.touchableLeft + event.nativeEvent.contentOffset.x
} )
}
I've looked at the following questions and articles but I couldn't really get to a solution that would help me. Usually people use flex to make their headers sticky above a ScrollView and that is incredibly handy but in this situation I am unsure about how to continue. Articles/Questions:
How to Get ListView Section Header to Stick
http://docs.nativebase.io/docs/examples/StickyHeaderExample.html
Sticky Component inside scrollview
What solved my problem was to take the TouchableNativeFeedback outside of the class. The class in the question was called Background and it was rendered in the class called App.
<View style={styles.container}>
<Background />
<TouchableNativeFeedback onPressIn={this._onPressButton} onPressOut={this._onPressButton}>
<View style={
{
width: '50%',
height: '100%',
position: 'absolute',
left:0,
//left: this.state.touchableLeft,
//backgroundColor: 'red',
}
}>
</View>
</TouchableNativeFeedback>
</View>
As you can see once I moved it to here, it was positioned right where I wanted, even if I move the screeen. What would be good practice, is to take it to another component class and then just call an instance of it.
Thanks to John Ruddell for the help while coming up with the solution

Cannot scroll to bottom of ScrollView in React Native

I have a very simple example of using a ScrollView and I cannot seem to scroll to the bottom.
The example is completely basic, I'm not doing anything special yet the last item is never fully visible.
Expo Code
import React, { Component } from "react";
import { Text, View, ScrollView, StyleSheet } from "react-native";
import { Constants } from "expo";
const data = Array.from({ length: 20 }).map((_, i) => i + 1);
export default class App extends Component {
render() {
return (
<ScrollView style={styles.container}>
{data.map(d => (
<View style={styles.view}>
<Text style={styles.text}>{d}</Text>
</View>
))}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: Constants.statusBarHeight
},
text: {
fontWeight: "bold",
color: "#fff",
textAlign: "center",
fontSize: 28
},
view: {
padding: 10,
backgroundColor: "#018bbc"
}
});
Here is the output:
Apply padding styles to "contentContainerStyle" prop instead of "style" prop of the ScrollView.
I had just a ScrollView in my application and it was working fine. Then I added a header component at the top, and the bottom of my ScrollView was not visible any more. I tried everything and nothing worked. Until I found a solution after an hour of trying every crazy thing and here it is. I fixed the issue by adding paddingBottom as contentContainerStyle to my ScrollView.
<ScrollView contentContainerStyle={{paddingBottom: 60}} >
{this.renderItems()}
</ScrollView>
set flexGrow: 1 to contentContainerStyle of your ScrollView
contentContainerStyle={{ flexGrow: 1 }}
Modify your render() method and wrap the ScrollView inside a View container, and set the paddingTop to that View container:
render() {
return (
<View style={ styles.container}>
<ScrollView >
{data.map(d => <View style={styles.view}><Text style={styles.text}>{d}</Text></View>)}
</ScrollView>
</View>
);
}
I fixed mine by setting Scrollview's contentInset bottom property to a value just enough for me to see bottommost part of my content (a button in my case).
Example:
<ScrollView
contentInset={{bottom: 80}}>
{{ content }}
</ScrollView>
I have this issue and fixed it. To solve it:
flex:1 means “expand it to its parent size”, if parent have a 0 height, it won’t work
flex:-1 means “shrink it to fit its children size”, if child height set to flex:1 (depends on parent) -> it wont’ work -> you ask me? I ask you back. loop.
scrollview have two view in it -> a {flex:1} outer view wrapped a {flex:-1} inner view. when inner view taller than outer view, that’s when scroll happen.
It also means outer view height depends on scrollview parent, inner view depends on children. If you cannot give a height to its outer view, the outer view will become 0 height. You cannot scroll inner view with a 0 height outer view, it will always bounce back to it origin position once your finger release.
wrap it with a <View style={{flex:1}}> may or may not solve your problems because it means the scrollview’s parent expand itself to fit its parent,height then depends on it parent. (the grand parent of your scrollview). So if your grand parent have no height defined, it fail.
The follow example won’t works
<View style={{height:300,width:200}}>
<View> //<-this break
<View {{flex:1}}>
<ScrollView>{contents}</ScrollView>
</View>
</View>
</View>
and this work:
var {Windowheight, width} = Dimensions.get('window');
<View style={{height:Windowheight}}>
<View style={{flex:1}}>
<ScrollView>{contents}</ScrollView>
<View>
</View>
this also work:
var {windowHeight, windowWidth} = Dimensions.get('window');
<View style={{height:windowHeight}}>
<Toolbar or other component with fixed height>
<ScrollView style={{flex:1}}>{contents}</ScrollView>
<Footer or other component with fixed height>
</View>
Conclusion, make sure your scrollview height determinable both from outside and inside. If weird things happen trace the ancestor until you find a height or simply define a solid one within its traceable ancestor without rely on flex:1 Some third party component wrap things with a <View> which breaks things.
Added height style for ScrollView.
height:'100%', width:'100%'
Set the child components height without using % e.g make minHeight: '10%' -> minHeight: 10

React Native Swiper multiple images

I'm using the react-native-swiper, but I didn't find any solution for my problem in the docs. Currently it's show me one picture at once. But I want one and half, and always slide one by one. Is it possible somehow, because the slides have a strict width.
A design what I would achive:
There is my current code:
class Featured extends Component {
/**
* Render the featured box
*/
renderFeatured() {
return this.props.featured.data.items.map(object => (
<View style={styles.slide} key={object.id}>
<FeaturedBox
id={object.id}
image={Helpers.getPrimaryImage(object.images)}
text={object.name}
/>
</View>
)
);
}
render() {
if (Helpers.isObjectEmpty(this.props.featured)) {
return (
<View />
);
}
return (
<View>
<Swiper
style={styles.wrapper}
height={150}
horizontal={false}
showsPagination={false}
>
{this.renderFeatured()}
</Swiper>
</View>
);
}
}
const styles = StyleSheet.create({
wrapper: {
},
slide: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
});
Basically the FeaturedBox is just an image.
I found the solution, and change the Swiper to Carousel.
I had the same problem with you.
I tried many times, eventually solved this problem and I created npm package for these use cases.
First of all, You can solve this error by adding specific width in the images via your device.
If your use cases is adding multiple images, then you can solve that easily by using method below.
Hope react-native-image-swiper helps you.
usage
import {Dimensions} from 'react-native';
import ImagesSwiper from "react-native-image-swiper";
const { width, height } = Dimensions.get("window");
<ImagesSwiper width={width} height={height-400} />
I suggest you to use react-native-snap-carousel
follow below link for more details
https://www.npmjs.com/package/react-native-snap-carousel
You can do this via following code;
<Swiper removeClippedSubviews={false}>
<View style={{width: screenWidth - 100}}></View>
<View style={{marginLeft: - 100}}> </View>
</Swiper>

TabBarIOS in ReactNative not working, items overlapping each other

So im making an app and this is my code:
import React, { Component } from 'react';
import {
View,
Text,
TabBarIOS,
StyleSheet,
Dimensions
} from 'react-native';
//import Styles from './LayoutStyle.js';
class Layout extends Component {
constructor(){
super()
this.state = {selectedTab: 'tabThree'}
}
setTab(tabId){
this.setState({selectedTab: tabId})
}
render() {
return(<View style={Styles.Layout}>
<TabBarIOS>
<TabBarIOS.Item
systemIcon='history'
selected={this.state.selectedTab === 'tabOne'}
onPress={() => this.setTab('tabOne')}>
<View>
<Text>Jure1</Text>
</View>
</TabBarIOS.Item>
<TabBarIOS.Item
systemIcon='bookmarks'
selected={this.state.selectedTab === 'tabTwo'}
onPress={() => this.setTab('tabTwo')}>
<View>
<Text>Jure2</Text>
</View>
</TabBarIOS.Item>
<TabBarIOS.Item
systemIcon='more'
selected={this.state.selectedTab === 'tabThree'}
onPress={() => this.setTab('tabThree')}>
<View>
<Text>Jure3</Text>
</View>
</TabBarIOS.Item>
</TabBarIOS>
</View>
);
}
}
const Styles = StyleSheet.create({
Layout: {
alignItems: "center",
justifyContent: "center",
height: Dimensions.get('window').height,
width: Dimensions.get('window').width,
},
TabBar: {
backgroundColor: 'grey'
}
});
export default Layout;
Well what i expected was an app where you have a TabBar on the bottom with three different items to choose from and it should look like i would in a native ios app. Well thats not the case, what i get is this:
Well what should i do? How do i style this item to not overlap? Any ideas?
The layout style is causing the inner content to get centred oddly, change Layout style to this:
Layout: {
flex:1,
}
Additionally, when trying to draw a scene from the tab clicked you will want to use a render function inside the TabBarIOS.Item object, react native provides some good examples of how to do this in the documentation: https://facebook.github.io/react-native/docs/tabbarios.html
I would highly recommend placing a navigator for each object which allows you to have much more control over the scene changes:
<TabBarIOS.Item
systemIcon='history'
title= 'Jure1'
selected={this.state.selectedTab === 'tabOne'}
onPress={() => this.setTab('tabOne')}>
<View style = {{flex:1}}>
<Navigator
renderScene={this._renderScene}
/>
</View>
</TabBarIOS.Item>

Categories

Resources