I am working with React Native Web and Reactjs and I have the following code on one of my pages.
What I'm trying to do is make the background image and footer scrollable, while keeping the header (HorizontalNavBar) fixed at the top,. The ScrollView works fine when I don't try to render the VerticalNavBar over it, but breaks when I try to do so. It doesn't even work if the VerticalNavBar is present but rendering null.
Any help would be greatly appreciated. Attaching a screenshot. Thx!
var Home = React.createClass({
getInitialState: function() {
return {
source: homeImageSmall,
windowWidth: window.innerWidth,
tutorialDirection: 'row',
verticalNavOpen: false};
},
closeVerticalNav: function() {
this.setState({verticalNavOpen: false})
},
openVerticalNav: function() {
this.setState({verticalNavOpen: true})
},
render() {
return (
<View>
<View style={{flex:0}}>
<HorizontalNavBar verticalNavOpen = {this.state.verticalNavOpen} openVerticalNav = {this.openVerticalNav}/>
<ScrollView style={{flex:0}}>
<View>
<Image
style={contentStyle.backGroundImage}
source={this.state.source}>
<View style = {[styles.doubleIphoneWrapper, {flexDirection: this.state.tutorialDirection}]}>
<Tutorial content={Baseball} name={"Baseball"}/>
<Tutorial content={Football} name={"Football"}/>
</View>
</Image>
<Footer/>
</View>
</ScrollView>
<VerticalNav verticalNavOpen = {this.state.verticalNavOpen} closeVerticalNav = {this.closeVerticalNav}/>
</View>
</View>
)
}
})
Turns out I had overflow: hidden in my HTML file. The above code works if I remove that and set the position of both the horizontal and vertical menus to 'fixed'. #facepalm
Related
I have two ScrollViews. When I scroll one the other should also scroll.
I tried using onScroll event, but it has a delay, the second ScrollView scrolls after a while. I really need it to scroll exactly at the same time.
Is there any other way to do it?
let scroll_ref_1 = null;
let scroll_ref_2 = null;
const Page = () => {
return (
<SafeAreaView>
<ScrollView
ref={ref => scroll_ref_1 = ref}
horizontal
onScroll={e => {
if(scroll_ref_2 !== null) {
scroll_ref_2.scrollTo({
x: e.nativeEvent.contentOffset.x,
animated: false,
});
}
}}
>
...
</ScrollView>
<ScrollView
horizontal
ref={ref => scroll_ref_2 = ref}
>
...
</ScrollView>
</SafeAreaView>
);
};
You can get a similar effect if you use flatlist with 2 columns.
I have been in this code for a while in trying to list my videos from local directory to my react native app. I have asked couple of questions as a newbie in this regards earlier as I started the project but did not get any answer. Somehow I managed to get to this point.
I have been able to get my videos from my local directory but the issue am having now is that my videos are only showing grey thumbnails, and when I tap on any video it gives a ReferenceError: Can't find variable: videos
Below is my screenshot and my code. Please I need to correct the wrong things am doing on this code. Thanks in advance for your help.
constructor(Props) {
super(Props);
this.state = {
videos: [],
playing: false,
screenType: 'content',
resizeMode: 'contain',
currentTime: 0,
videoPlayer: null,
duration: 0,
isFullScreen: false,
isLoading: true,
paused: false,
playerState: PLAYER_STATES.PLAYING,
};
This is my constructor
componentDidMount() {
var filePath = RNFetchBlob.fs.dirs.MovieDir + '/Voc Vedos/';
RNFetchBlob.fs.ls(filePath)
.then(files => {
this.setState({videos:files});
console.warn(files);
}).catch(err=>alert(err.toString()))
}
This is where I got my videos from my local directory on my device
render() {
const { duration, currentTime, paused, overlay } = this.state
return(
<View style={styles.container}>
<FlatList
data={this.state.videos}
keyExtractor={item=>item}
ItemSeparatorComponent={() => { return (<View style={styles.separator} />) }}
// viewabilityConfig={this.viewabilityConfig}
// onViewableItemsChanged={this.onViewableItemsChanged}
// viewabilityConfig={{
// itemVisiblePercentThreshold: 95
// }}
numColumns={3}
renderItem={({ item, index, separators }) => (
<TouchableOpacity
onPress={() => this._onPress(item)}
style={{width:100,height:100}}>
<View
style={{width:100,height:100, margin:8}}
>
<Video
source ={{uri: '/storage/emulated/0/Movies/Voc Vedos/'+{item}}}
ref={(ref: Video) => { this.video = ref }}
style={{width:100,height:100}}
rate={this.state.rate}
paused={this.state.paused}
volume={this.state.volume}
muted={this.state.muted}
resizeMode={this.state.resizeMode}
onLoad={this.onLoad}
onProgress={this.onProgress}
onEnd={this.onEnd}
onAudioBecomingNoisy={this.onAudioBecomingNoisy}
onAudioFocusChanged={this.onAudioFocusChanged}
/>
<MediaControls
isFullScreen={this.state.isFullScreen}
duration={duration}
isLoading={this.state.isLoading}
mainColor="purple"
onFullScreen={noop}
onPaused={this.state.onPaused}
onReplay={this.state.onReplay}
onSeek={this.state.onSeek}
onSeeking={this.state.onSeeking}
playerState={this.state.playerState}
progress={currentTime}
/>
</View>
</TouchableOpacity>
)}
/>
</View>
This is my render code.
please I need help on how to display my videos correctly and play video when tapped
according to react-native-video docs:
for file source in device storage, must write 'file://' begin of path
Example:
source={{ uri: 'file:///sdcard/Movies/sintel.mp4' }}
read document https://github.com/react-native-community/react-native-video#source
How do I Check if element is visible after scrolling for react-native? saw some examples for react, but am looking specifically for react-native. Would like to track impressions and clicks
ended up implementing a lib
https://www.npmjs.com/package/react-native-component-inview
import InView from 'react-native-component-inview'
const [isInView, setIsInView] = useState(false)
const checkVisible = (isVisible:boolean) => {
if (isVisible){
setIsInView(isVisible)
} else {
setIsInView(isVisible)
}
}
<ScrollView>
<InView onChange={(isVisible) => this.checkVisible(isVisible)}>
<View style={[styles.item, {backgroundColor: isInView ? 'yellow' : '#f9c2ff'}]}>
<Text>yay</Text>
</View>
</InView>
</ScrollView>
References:
https://medium.com/#sanishkr/react-components-tracking-impressions-and-clicks-2fc9af1cc2c
I am using React Navigation inside React Native App and i created a Custom Header Component for my routes
like this :
const Router = StackNavigator({
Main: {
screen: Main,
navigationOptions: ({navigation}) => ({
header:<Header title="Main"/>
})
},
})
when using a custom header component the native animation not working
i would like to know how can i achieve the animation in the header the same as here https://reactnavigation.org/
TL:DR; found solution to share the animated.Value / interpolation over screens code below.
Animated Custom Header React-native + React navigation
This post was taunting me for some time - I was faced with the same issue. Hopefully this will reach you even if it's couple of months later :D
So first my issue was this, I made a component for custom header like in your example, my target was having one of the StackNavigator pages, have a scrollView which would in turn manipulate the color of the header.
Similar issue, the information exchange between header and page should help you too, here it goes.
Header.js
export class HeaderBar extends Component {
componentWillMount(){
// might be a bit, ehm but worked so if you have tips how to make the code nice feel free to share
let valueToManipulate= new Animated.Value(0);
this.props.navigation.setParams({
valueToManipulate,
customkey: valueToManipulate.interpolate({
inputRange: [0, 150],
outputRange: ['rgba(0,0,0,0)', 'rgba(0,0,0,1)'],
extrapolate: 'clamp',
})
})
}
render () {
... bit of code ...
// important bit for data binding !
if( ! (this.props.navigation.state.params && this.props.navigation.state.params.customkey) ){
return null;
}
/* unless that variable on params exists we do not ! render */
... bit more of code ...
<View style={ floating }>
<Animated.View style={{backgroundColor: this.props.navigation.state.params.customkey }}> /// <<--- typical bind
<View style={{flexDirection: 'row', justifyContent: "space-between"}}>
... and rest of render ...
So this is the header bit, now for the other "fun" part:
HomePage.js
export default class HomePage extends Component<{}> {
... stufff..... :D
render() {
/* this here, again data binding !, do not let render before we have this var in state params ! */
if( !( this.props.navigation.state.params && this.props.navigation.state.params.valueToManipulate ) )
return null;
return (
<ScrollView
style={styles.container}
onScroll={ Animated.event(
[{ nativeEvent: { contentOffset: { y: this.props.navigation.state.params.valueToManipulate } } }], // <-- tadaaa
)}
bounces={false}
scrollEventThrottle={1}
showsVerticalScrollIndicator={false}
showsHorizontalScrollIndicator={false}
>
... moar stuff ...
}
}
And here ! Finally ! A Demo !
Animated Custom Header React-native + React navigation
I published react-navigation-collapsible.
I hope it would be helpful.
https://github.com/benevbright/react-navigation-collapsible
Im new to React Native so excuse the question if this is simple.
Im trying to toggle icons in a ListView. I'm logging out the correct response but Im unable to see the screen refresh onPress with that icon using "this.state". How should I go about this? Your help is much appreciated.
Here's a piece of code i'm working with.
getInitialState: function() {
return {liked:false};
},
pressedLike: function(){
this.setState({liked: !this.state.liked})
},
renderRow: function (data) {
return (
<View>
<TouchableHighlight
onPress={()=>{this.pressedLike}}>
<View>
{this.state.liked ? <Icon name="ios-heart" size={25} color="red" /> : <Icon name="ios-heart-outline" size={25} color="#555" />}
</View>
</TouchableHighlight>
</View>
);
},
render: function() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow}
refreshControl={
<RefreshControl refreshing={this.state.refreshing} onRefresh= {this.onRefresh}/>
}
/>
);
}
It's pretty simple, here is an example of how to change an Awesome icon on press... using the node_module react-native-vector-icon available on GitHub.
First in getInitialState, declare a variable with the icon you want and a check var to know which logo to display:
return {logo: "star-o", check: false}
Then on the concerned button / clickable zone , add this method:
onPress={() => this.stateChange()}
And declare a stateChange method and add this:
this.state.check === false ? this.setState({logo:'star', check:true}) : this.setState({logo:'star-o', check:false})
This looks for the check var and changes the logo depending on its value. It is ternary syntax.
There's really a lot that needs to happen here. You're going to probably need some sort of data structure that has a liked boolean in it, something like this (just an example):
data = [{name: 'Dog', liked: false}, {name: 'Turtle', liked: false}, {name: 'Cat', liked: false}]
Then in your likeItem method, you will need to get the index of the item you are looping over and update the liked boolean, and reset the state of the dataSource:
likeItem (index) {
const { data } = this.state
data[index].liked = !data[index].liked
this.setState({ dataSource: ds.cloneWithRows(data), data })
}
And you can show the icon based on the liked value:
{rowData.liked && <LikedIcon />}
{!rowData.liked && <NotLikedIcon />}
I wipped up a quick example of the functionality you may need here.
https://rnplay.org/apps/H2hsSg