when creating a scroll view for a mobile app, a common principle could be to have an image on the very top of the list. This could be to showcase the content of the page. Examples for this could be found in the Spotify app, where an album cover is shown first, followed by a list of its songs.
import React, { Component } from 'react';
import {
View,Text,StyleSheet,ScrollView,Image, Animated, Dimensions
} from 'react-native';
HEADER_MAX_HEIGHT = Dimensions.get("window").height*0.4;
HEADER_MIN_HEIGHT = 70;
PROFILE_IMAGE_MAX_HEIGHT = 80;
PROFILE_IMAGE_MIN_HEIGHT = 40;
const IMAGE_SCALE_MAX = 20;
const LABEL_HEADER_MARGIN = 48;
import FastImage, { FastImageProps } from 'react-native-fast-image';
const AnimFastImage = Animated.createAnimatedComponent(FastImage);
class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
pan: new Animated.ValueXY()
};
}
render() {
return (
<ScrollView style={{
flex: 1,
width: '100%',
height: '100%',
backgroundColor: 'white'
}}
showsVerticalScrollIndicator={false}
alwaysBounceVertical={false}
contentContainerStyle={{ padding: 0 }}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.pan.y } } }],
{
useNativeDriver: false,
},
)}
alwaysBounceVertical={false}
contentInsetAdjustmentBehavior="never"
scrollEventThrottle={1}
>
<AnimFastImage
animStyle={{
transform: [
{
translateY: this.state.pan.y.interpolate({
inputRange: [-1000, 0],
outputRange: [-100, 0],
extrapolate: 'clamp',
}),
},
{
scale: this.state.pan.y.interpolate({
inputRange: [-3000, 0],
outputRange: [IMAGE_SCALE_MAX, 1],
extrapolate: 'clamp',
}),
},
],
}}
source={{ uri: 'https://i.picsum.photos/id/1/400/400.jpg?hmac=lOytrN6lDOH_Yx7NwwGIaCtxp6pyuH2V4hD6Eac-VI0', priority: 'high' }}
style={styles.img}
resizeMode="cover"
/>
<Animated.View
style={{
paddingHorizontal: 16,
transform: [
{
translateY: this.state.pan.y.interpolate({
inputRange: [-1000, 0],
outputRange: [LABEL_HEADER_MARGIN * IMAGE_SCALE_MAX, -80],
extrapolate: 'clamp',
}),
},
],
}}>
<Text style={{ fontWeight: 'bold', fontSize: 20}}>
Trần thanh tung
</Text>
<View style={{ height: 700 }} />
</Animated.View>
</ScrollView>
)}
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
img: {
backgroundColor: '#ccc',
width: '100%',
height: 350,
justifyContent: 'flex-end',
padding: 0,
},
});
But it doesn't work as I want it to. I want it to be like the user part of the telegram
what I want
Related
I would like to add a outside box shadow in react-native-navigation.
The desired effect should look like this:
Currently when I apply styles the outside box shadow does not change:
import React, { FunctionComponent } from 'react'
import NavigatorProps from './NavigatorBottomTabs.type'
import { Screen } from '../../Module/Navigation/Navigation.type'
import Route from '../../Module/Navigation/Navigation.route'
import { ANY } from '../../Type/Type'
import TabBar from './NavigatorBottomTabs.TabBar'
const RenderScreen = (Tab: ANY) => (screen: Screen) =>
<Tab.Screen key={screen.name} {...screen} />
const NavigatorBottomTabs: FunctionComponent<NavigatorProps> = (props) => {
const Tab = props.Tab
return (
<>
<Tab.Navigator
tabBar={TabBar}
initialRouteName={Route.RootDabshboardProfileRouter}
tabBarOptions={{
borderWidth: 1,
borderColor: 'red',
marginTop: 10,
style: {
borderTopWidth: 0,
elevation: 8,
backgroundColor: '#d9d9d9',
shadowColor: '#000000',
shadowOpacity: 0.8,
shadowRadius: 2,
shadowOffset: {
height: 1,
width: 1
}
}
}}
screenOptions={{
tabBarStyle: {
elevation: 8,
borderTopWidth: 0,
backgroundColor: '#d9d9d9',
shadowColor: '#000000',
shadowOpacity: 0.8,
shadowRadius: 2,
shadowOffset: {
height: 1,
width: 1
}
}
}}
>
{props.screens.map(RenderScreen(Tab))}
</Tab.Navigator>
</>
)
}
export default NavigatorBottomTabs
I want to create a round Button for profile pic in React Native, but it did not work. The button should be round and clickable, and should have a pmg image inside it. What am I doing wrong here?
I used a blue background image, then on top op it TouchableOpacity wrapper for holding the image as button.
const Main = () => {
return (
// Container
<View style={styles.container} >
<ImageBackground
source={require('../images/background.png')}
style={styles.backgroundImage}>
<View>
<TouchableOpacity style={styles.profileButton}>
<Image source={require('../images/profilePicture/boy.png')} />
</TouchableOpacity>
</View>
</ImageBackground>
</View>
);
}
const styles = StyleSheet.create({
container: {
// paddingTop: '6%',
flex: 1,
},
backgroundImage: {
flex: 1,
resizeMode: "cover",
width: '100%',
height: '100%',
},
topBar: {
height: '40%',
// color : 'red',
// flex: 1,
// alignItems: 'stretch'
},
profileButton: {
borderWidth: 1,
borderColor: 'rgba(0,0,0,0.2)',
alignItems: 'center',
justifyContent: 'center',
width: '13%',
height: 50,
// backgroundColor: '#fff',
borderRadius: 50,
},
});
export default Main;
Be sure to add image dimensions. Lol. I completely forgot that:
profileButton: {
borderWidth: 1,
// borderColor: 'rgba(0,0,0,0.2)',
width: '13%',
height: 50,
backgroundColor: '#fff',
borderRadius: 50,
padding: '1%',
margin: '1%',
},
profileImage: {
height: undefined,
width: undefined,
flex: 1
},
I succeeded in running the code provided by the site using react-native-maps-super-cluster.
However I cannot know how can I add my custom marker to the code.
How can I add my custom markers.
When I add my marker, it did not clustered.
The number of markers are exceed 1000+.
Dependencies are
"dependencies": {
"geolocation": "^0.2.0",
"react": "16.9.0",
"react-native": "0.61.5",
"react-native-geolocation-service": "^3.1.0",
"react-native-maps": "0.26.1",
"react-native-maps-super-cluster": "^1.6.0",
},
Bellows are current code.
import React, { Component } from 'react'
import {
Text,
View,
Image,
StyleSheet,
SafeAreaView,
TouchableOpacity,
} from 'react-native'
import { Marker, Callout } from 'react-native-maps'
import ClusteredMapView from 'react-native-maps-super-cluster'
import { generateRandomPoints, generateRandomPoint } from './generator'
const italyCenterLatitude = 37.521291,
italyCenterLongitude = 126.991733,
radius = 600000
export default class App extends Component {
constructor(props) {
super(props)
this.state = {
pins: []
}
this.reload = this.reload.bind(this)
this.loadMore = this.loadMore.bind(this)
this.renderMarker = this.renderMarker.bind(this)
this.renderCluster = this.renderCluster.bind(this)
}
componentDidMount() {
this.reload()
}
reload = () => {
const pins = generateRandomPoints({ latitude: italyCenterLatitude, longitude: italyCenterLongitude }, radius, 50, this.state.pins.length)
this.setState({ pins: pins })
}
loadMore = () => {
const pins = generateRandomPoints({ latitude: italyCenterLatitude, longitude: italyCenterLongitude }, radius, 50, this.state.pins.length)
this.setState({ pins: this.state.pins.concat(pins) })
}
renderCluster = (cluster, onPress) => {
const pointCount = cluster.pointCount,
coordinate = cluster.coordinate,
clusterId = cluster.clusterId
return (
<Marker identifier={`cluster-${clusterId}`} coordinate={coordinate} onPress={onPress}>
<View style={styles.clusterContainer}>
<Text style={styles.clusterText}>
{pointCount}
</Text>
</View>
</Marker>
)
}
renderMarker = (pin) => {
return (
<Marker identifier={`pin-${pin.id}`} key={pin.id} coordinate={pin.location} />
)
}
render() {
return (
<SafeAreaView style={styles.container}>
{/* Cluster Map Example */}
<ClusteredMapView
style={{ flex: 1 }}
data={this.state.pins}
renderMarker={this.renderMarker}
renderCluster={this.renderCluster}
initialRegion={{ latitude: italyCenterLatitude, longitude: italyCenterLongitude, latitudeDelta: 12, longitudeDelta: 12 }}>
<Marker coordinate={{ latitude: 44.710968, longitude: 10.640131 }} pinColor={'#65bc46'} />
// Bellows are my marker. It do not clustered.
<Marker
coordinate={{ latitude: 37.5299448479299, longitude: 126.837746714377, }}
image={require('../gudu6/GuduIcon1w100.png')}
pinColor={'#65bc46'}
title=" 양천구 신월동 " description=" 228-1 번지" />
<Marker
coordinate={{ latitude: 37.58758812498327, longitude: 127.03790040097465, }}
image={require('../gudu6/GuduIcon1w100.png')}
pinColor={'#65bc46'}
title=" 동대문구 제기동 " description=" 1212 번지" />
<Marker
coordinate={{ latitude: 37.579331071917416, longitude: 127.04206659725423, }}
image={require('../gudu6/GuduIcon1w100.png')}
pinColor={'#65bc46'}
title=" 동대문구 제기동 " description=" 652-1 번지" />
</ClusteredMapView>
<View style={styles.controlBar}>
<TouchableOpacity
style={styles.button}
onPress={this.reload}>
<Text style={styles.text}>Reload</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={this.loadMore}>
<Text style={styles.text}>Load more</Text>
</TouchableOpacity>
</View>
<Image
resizeMode='contain'
source={require('./simbol.png')}
style={{ position: 'absolute', bottom: 26, right: 8, width: 64, height: 64 }} />
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#F5FCFF',
},
clusterContainer: {
width: 30,
height: 30,
padding: 6,
borderWidth: 1,
borderRadius: 15,
alignItems: 'center',
borderColor: '#65bc46',
justifyContent: 'center',
backgroundColor: 'white',
},
clusterText: {
fontSize: 13,
color: '#65bc46',
fontWeight: '500',
textAlign: 'center',
},
controlBar: {
top: 48,
left: 25,
right: 25,
height: 40,
borderRadius: 20,
position: 'absolute',
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 20,
backgroundColor: 'white',
justifyContent: 'space-between',
},
button: {
paddingVertical: 8,
paddingHorizontal: 20,
},
novaLabLogo: {
right: 8,
bottom: 8,
width: 64,
height: 64,
position: 'absolute',
},
text: {
fontSize: 16,
fontWeight: 'bold'
},
clusterContainer: {
width: 24,
height: 24,
borderWidth: 1,
borderRadius: 12,
alignItems: 'center',
borderColor: '#65bc46',
justifyContent: 'center',
backgroundColor: '#fff'
},
counterText: {
fontSize: 14,
color: '#65bc46',
fontWeight: '400'
},
calloutStyle: {
width: 64,
height: 64,
padding: 8,
borderRadius: 8,
borderColor: '#65bc46',
backgroundColor: 'white',
},
})
I think your issue is that you are defining each marker statically within your mapview component. The function you pass to the renderMarker prop will render a marker for each marker given to the data prop of the Mapview. This will allow the package to dynamically cluster your array of markers.
How to get the userdata props value in head component ?I am mapping state to
props but not able to take that value in head component.How to pass this.
Passing values to Higher order component.Provinding the code.Can someone
please go through it. How to get the userdata props value in head component ?I am mapping state to
props but not able to take that value in head component.How to pass this.
Passing values to Higher order component.Provinding the code.Can someone
please go through it
import React from "react";
import {Image, Text, View, ToastAndroid} from "react-native";
import {createDrawerNavigator} from 'react-navigation-drawer';
import {createMaterialTopTabNavigator, createStackNavigator, createAppContainer,DrawerActions} from "react-navigation";
import {Icon} from 'react-native-elements';
import DrawerContent from "./DrawerContent";
import {connect} from "react-redux";
import FirstList from "./FirstList";
import SecList from "./SecList";
import ThirList from "./ThirList";
import color from "../util/Colors";
import DashBoard from "./DashBoard";
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const TabNavigator = createMaterialTopTabNavigator(
{
FirstList : FirstList ,
SecList : SecList ,
},
{
tabBarOptions: {
labelStyle: {fontSize: 13},
activeTintColor: color.basecolor,
inactiveTintColor: 'black',
scrollEnabled: false,
style: {
backgroundColor: 'white',
height:45
},
indicatorStyle: {
backgroundColor: color.basecolor,
}
},
title: 'Details',
}
);
const StackNavigator1 = createStackNavigator({
TabNavigator: {
screen: TabNavigator,
navigationOptions:({navigation})=>{
return{
header: (
<Head/>
)
}
},
},
List: {
screen: ThirList
navigationOptions:({navigation})=>{
return{
header: null
}
},
},
});
const RootNav = createAppContainer(StackNavigator1);
var name;
class Head extends React.Component {
constructor(props) {
super(props);
name='';
var today = new Date();
this.state = {
'date': today.getDate() + " " + monthNames[today.getMonth()] + " " + today.getFullYear()
};
console.log(JSON.stringify(this.props)+"userdata");
}
render() {
const {date} = this.state;
return (
<View>
<View style={{flexDirection: 'row', backgroundColor: color.mainback, height: 40,padding:10}}>
<Text style={{
fontSize: 14,
textAlign: 'left',
marginLeft: 10,
flex:1,
color:color.textcolor,
fontWeight:'bold',
textAlignVertical: "center"
}}>Orders</Text>
<Text style={{
fontSize: 10,
textAlign: 'right',
marginLeft: 20,
marginRight: 20,
fontWeight: 'bold',
color:color.datetextcolor,
textAlignVertical: "center"
}}>{date}</Text>
</View>
</View>
);
}
}
class RootScreen extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<RootNav/>
</View>
);
}
}
const StackNavigator = createStackNavigator({
DrawerNavigator: {
screen: RootScreen,
activeTintColor: color.basecolor,
navigationOptions: ({navigation}) => ({title: 'Home'}, {
headerLeft:
<View style={{flexDirection: 'row', marginLeft: 20}}>
<Icon name="menu" onPress={()=>navigation.dispatch(DrawerActions.toggleDrawer())} size={30} color="white"/>
<Image source={require('../images/logo.png')}
style={{height: 35, width: 150, resizeMode: 'contain'}}/>
</View>,
}
),
},
Dashboard: {
screen: DashBoard,
navigationOptions: {
headerTitle: (
<View style={{flex: 1, flexDirection: 'row', justifyContent: 'center'}}>
<View style={{flex: 1, justifyContent: 'center'}}>
<Image
source={require('../images/logo.png')}
style={{height: 35, width: 150, marginLeft: -20, resizeMode: 'contain'}}
/>
</View>
</View>
),
},
},
}, {
defaultNavigationOptions: {
headerTintColor: 'white',
headerStyle: {
backgroundColor: color.basecolor,
},
}
}
);
const DrawerNavigator = createDrawerNavigator(
{
Home: StackNavigator
},
{
contentComponent: DrawerContent,
drawerWidth: 280,
navigationOptions: {
header: null
},
}
);
function mapStateToProps(state) {
return {
userdata: state.auth.userdata
}
}
export default connect(mapStateToProps) (DrawerNavigator);
Your aim is to connect Head component to Redux Store, right?
Simply using connect() function will suffice.
The solution would be to add this line of code.
const NewHead = connect(mapStateToProps)(Head)
Replace the <Head/> with <NewHead/> in StackNavigator1
Then, access the data within the Head component in the following manner.
this.props.userdata
OR
If you want to pass data to routes when you navigate to them, you can refer to this documentation.
I'm trying to simultaneously restrict the values of my animation (using clamp as well as interpolate) but also get the values out of the interpolation so I can use them. Specifically because I want to update a piece of state with them and create an observable from that. I just can't figure out how to extract the 'real' value out of the AnimatedValue that is produced by the interpolation (in this case state.panValue). I've tried
this.state.panValue.value
and
this.state.panValue._value
and they come back as undefined. If anyone could help me out would be amazing!
EDIT: I'd also be really happy to just have the
this.state.pan.x
variable updated within the limits so I can skip the whole updating the state variable 'panValue' thing. A nice guy on Facebook suggested that I could implement this limit somehow inside the onPanResponderMove by switching the variable to a function or something but I've tried several things and all I get are errors, I guess because I don't really know how to 'safely' amend these animated values.
onPanResponderMove: Animated.event([
null,
{ dx: this.state.pan.x },
]),
Original Code:
import React, { Component } from 'react';
import {
View,
Animated,
PanResponder,
Text,
} from 'react-native';
import styles from './styles';
class ClockInSwitch extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
panValue: 0,
};
}
componentWillMount() {
this._animatedValueX = 0;
this._animatedValueY = 0;
this.state.pan.x.addListener((value) => {
this._animatedValueX = value.value;
this.setState({
panValue: this.state.pan.x.interpolate({
inputRange: [-30, 0, 120,],
outputRange: [-10, 0, 120,],
extrapolate: 'clamp',
}),
});
});
this._panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
this.state.pan.setOffset({
x: this._animatedValueX,
});
this.state.pan.setValue({ x: 0, y: 0 });
},
onPanResponderMove: Animated.event([
null,
{ dx: this.state.pan.x },
]),
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
this.state.pan.flattenOffset();
Animated.timing(this.state.pan, {
toValue: 0,
duration: 500,
}).start();
},
onPanResponderTerminate: (evt, gestureState) => {
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return true;
},
});
}
componentWillUnMount() {
this.state.pan.x.removeAllListeners();
}
render() {
const animatedStyle = {
transform: [{
translateX: this.state.panValue,
},
],
};
return (
<View>
<Text>{this.state.pan.x._value}</Text>
<View style={styles.buttonStyle}>
<Animated.View
style={[styles.sliderButtonStyle, animatedStyle]}
{...this._panResponder.panHandlers}
/>
</View>
</View>
);
}
}
export default ClockInSwitch;
I think this is what you're looking for. I'm using exponent so your declaration for vector icons would probably need to be changed. Cheers!
/**
* #providesModule ClockInSwitch
* #flow
*/
import React, {Component} from 'react';
import {View, Animated, StyleSheet, PanResponder, Text} from 'react-native';
import {FontAwesome} from '#exponent/vector-icons';
export class ClockInSwitch extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
panValue: 0
};
}
componentWillMount() {
this._panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderGrant: (e, gestureState) => {
this
.state
.pan
.setValue({x: 0, y: 0});
},
//here's where you can check, constrain and store values
onPanResponderMove: (evt, gestureState) => {
// 300 is the width of the red container (will leave it to you to calculate this
// dynamically) 100 is the width of the button (90) plus the 5px margin on
// either side of it (10px total)
var newXVal = (gestureState.dx < 300 - 100)
? gestureState.dx
: 300 - 100;
this
.state
.pan
.x
.setValue(newXVal);
//set this state for display
this.setState({panValue: newXVal});
},
onPanResponderRelease: (e, {vx, vy}) => {
this
.state
.pan
.flattenOffset();
Animated
.spring(this.state.pan, {
toValue: 0,
duration: 400,
overshootClamping: true
})
.start();
this.setState({panValue: 0});
}
});
}
componentWillUnMount() {
this
.state
.pan
.x
.removeAllListeners();
}
render() {
//decouple the value from the state object
let {pan} = this.state;
let [translateX,
translateY] = [pan.x, pan.y];
let translateStyle = {
transform: [{
translateX
}, {
translateY
}]
};
return (
<View>
<Text style={styles.leftText}>Power Button Demo</Text>
<View style={styles.buttonStyle}>
<Animated.View
style={[styles.sliderButtonStyle, translateStyle]}
{...this._panResponder.panHandlers}>
<FontAwesome
name="power-off"
color="#EA2E49"
style={{
alignSelf: "center",
marginHorizontal: 10
}}
size={36}/>
</Animated.View>
</View>
<Text style={styles.rightText}>{this.state.panValue}: x value</Text>
</View>
);
}
}
export default ClockInSwitch;
const styles = StyleSheet.create({
sliderButtonStyle: {
borderColor: '#FCFFF5',
borderStyle: 'solid',
borderWidth: .5,
backgroundColor: '#FCFFF5',
borderRadius: 45,
height: 90,
width: 90,
justifyContent: 'center',
textAlign: 'center',
marginHorizontal: 5,
shadowColor: '#333745',
shadowOffset: {
width: 2,
height: 2
},
shadowOpacity: .6,
shadowRadius: 5
},
buttonStyle: {
borderColor: '#FCFFF500',
backgroundColor: '#DAEDE255',
borderStyle: 'solid',
borderWidth: 1,
height: 100,
width: 300,
justifyContent: 'center',
borderRadius: 50,
margin: 5,
flexDirection: 'column'
},
rightText: {
justifyContent: 'center',
textAlign: 'right',
fontWeight: '100',
marginHorizontal:15,
fontSize: 20,
color: '#FCFFF5',
marginVertical:25,
flexDirection: 'column'
},
leftText: {
justifyContent: 'center',
textAlign: 'left',
fontWeight: '100',
marginHorizontal:15,
fontSize: 24,
color: '#FCFFF5',
marginVertical:25,
flexDirection: 'column'
}
});