How to use PanResponder inside horizontal FlatList - react-native

I want to drag out the selected item from the horizontal FlatList and drop it to another area of the screen. The problem is that my FlatList wrapper must have a fixed height and when trying to pull out selected element out FlatList component overflows it and my element gets hidden.
I have tried to change zIndex and set overflow to visible but it does not work properly because setting zIndex works with siblings only and pretty buggy just yet, overflow:visible did not affect layout at all.
Here is the screenshot:
Here is my code:
import React from 'react';
import {
SafeAreaView,
View,
FlatList,
Text,
StyleSheet,
Animated,
PanResponder
} from 'react-native';
import { v4 } from 'uuid';
export default class App extends React.PureComponent{
state = {
data: [
{ id: v4(), title: 'Lightcoral', hex: '#eb7474' },
{ id: v4(), title: 'Orchid', hex: '#eb74dc' },
{ id: v4(), title: 'Mediumpurple', hex: '#9a74eb' },
{ id: v4(), title: 'Mediumslateblue', hex: '#8274eb' },
{ id: v4(), title: 'Skyblue', hex: '#74b6eb' },
{ id: v4(), title: 'Paleturquoise', hex: '#93ece2' },
{ id: v4(), title: 'Palegreen', hex: '#93ecb6' },
{ id: v4(), title: 'Khaki', hex: '#d3ec93' }
]
}
_position = new Animated.ValueXY()
_panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (event, gesture) => {
this._position.setValue({ x: gesture.dx, y: gesture.dy})
},
onPanResponderRelease: () => {}
})
_keyExtractor = (item) => item.id;
_renderItem = ({item}) => {
return (
<Animated.View
style={this._position.getLayout()}
{...this._panResponder.panHandlers}
>
<View style={[styles.itemBox, {backgroundColor: `${item.hex}`}]}>
<Text>{item.title}</Text>
</View>
</Animated.View>
)
}
render() {
const { data } = this.state
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
<View style={styles.targetArea}>
<Text>Drop HERE!!!</Text>
</View>
<View style={{ height: 80, borderColor: 'black', borderWidth: 2 }}>
<FlatList
data={data}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
horizontal={true}
/>
</View>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
safeArea: {
flex: 1
},
container: {
flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#fff',
},
itemBox: {
width: 80,
height: 80,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#fff'
},
targetArea: {
height: 150,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#eee',
backgroundColor: '#F5FCFF',
marginTop: 40
}
});
I want to move the selected item of flatList around the screen and put it on top of any other element of the screen, if i simply could programmatically set zIndex of each element - I would be over the moon but unfortunately it seems not working as simple as that. Please help me I very desperate(((

set overflow to visible in FlatList style.

Related

FlatList with ScrollTo in React Native

I'm new to React Native, I'm trying to make a FlatList in an application with Expo that will pull some categories of products from a Json, I managed to make the FlatList and also a Json simulation for testing, however I wish that by clicking on any item in the FlatList it directs the Scroll to the respective section, the same when using anchor with id in HTML.
For example: FlatList will display the categories: Combo, Side Dishes, Hot Dog, etc. For each category that is displayed by FlatList I have already created a View that will display products in this category.
What I want to do:
When you click on a category displayed by FlatList the Scroll scrolls to the View that displays the products of this category, that is, if you click on Combo the page scrolls to the View that displays the products of the Combo category, if you click on Side Dishes the page scrolls until the View that displays the products in the Side Dishes category, follows my code:
Follow my code: (it can be simulated here: https://snack.expo.io/#wendell_chrys/06944b)
import React, { useEffect, useState } from 'react';
import { View, Image, ImageBackground, Text, StyleSheet, ScrollView, Dimensions, FlatList, SafeAreaView, TouchableOpacity } from 'react-native';
import { AppLoading } from 'expo';
import Constants from 'expo-constants';
const DATA = [
{
id: "1",
title: "Combos",
categorie: "section1",
},
{
id: "2",
title: "Side Dishes",
categorie: "section2",
},
{
id: "3",
title: "Hot Dog",
categorie: "section3",
},
{
id: "4",
title: "Desserts",
categorie: "section4",
},
{
id: "5",
title: "Drinks",
categorie: "section5",
},
];
const renderItem = ({ item }) => {
return (
<Item
item={item}
/>
);
};
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} >
<Text style={styles.itenscategoria}>{item.title}</Text>
</TouchableOpacity>
);
export default function App() {
return (
<View style={styles.container}>
<View style={styles.categories}>
<FlatList
data={DATA}
horizontal
showsHorizontalScrollIndicator={false}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</View>
<ScrollView>
<View style={styles.section1}>
<Text>Combos</Text>
</View>
<View style={styles.section2}>
<Text>Side Dishes</Text>
</View>
<View style={styles.section3}>
<Text>Hot Dog</Text>
</View>
<View style={styles.section4}>
<Text>Desserts</Text>
</View>
<View style={styles.section5}>
<Text>Drinks</Text>
</View>
</ ScrollView>
</View >
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#000',
padding: 8,
},
categories: {
backgroundColor: '#FFFFFF',
width: '100%',
height: 50,
top: 10,
marginBottom:20,
},
itenscategoria: {
padding:15,
border: 1,
borderRadius:25,
marginRight:10,
},
section1: {
marginTop: 10,
backgroundColor: '#ccc',
width: '100%',
height: 200,
borderRadius: 10,
},
section2: {
marginTop: 10,
backgroundColor: '#ccc',
width: '100%',
height: 200,
borderRadius: 10,
},
section3: {
marginTop: 10,
backgroundColor: '#ccc',
width: '100%',
height: 200,
borderRadius: 10,
},
section4: {
marginTop: 10,
backgroundColor: '#ccc',
width: '100%',
height: 200,
borderRadius: 10,
},
section5: {
marginTop: 10,
backgroundColor: '#ccc',
width: '100%',
height: 200,
borderRadius: 10,
},
});
You can make use of scrollToIndex of FlatList
See complete code below, or the snack here.
import React, { useEffect, useState, useRef } from 'react';
import { View, Image, ImageBackground, Text, StyleSheet, ScrollView, Dimensions, FlatList, SafeAreaView, TouchableOpacity } from 'react-native';
import { AppLoading } from 'expo';
import Constants from 'expo-constants';
const DATA = [
{
id: "1",
title: "Combos",
categorie: "section1",
},
{
id: "2",
title: "Side Dishes",
categorie: "section2",
},
{
id: "3",
title: "Hot Dog",
categorie: "section3",
},
{
id: "4",
title: "Desserts",
categorie: "section4",
},
{
id: "5",
title: "Drinks",
categorie: "section5",
},
];
export default function App() {
const flatListRef = useRef();
const handleItemPress = (index) => {
flatListRef.current.scrollToIndex({ animated: true, index });
};
const renderItem = ({ item, index }) => {
return (
<Item
item={item}
onPress={() => handleItemPress(index)}
/>
);
};
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} >
<Text style={styles.itenscategoria}>{item.title}</Text>
</TouchableOpacity>
);
const renderDetails = ({ item, index }) => (
<View style={styles.section}>
<Text>{item.title}</Text>
</View>
);
return (
<View style={styles.container}>
<View style={styles.categories}>
<FlatList
data={DATA}
horizontal
showsHorizontalScrollIndicator={false}
renderItem={renderItem}
keyExtractor={(item) => item.id}
/>
</View>
<FlatList
ref={flatListRef}
data={DATA}
renderItem={renderDetails}
keyExtractor={(item) => item.id}
/>
</View >
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#000',
padding: 8,
},
categories: {
backgroundColor: '#FFFFFF',
width: '100%',
height: 50,
top: 10,
marginBottom:20,
},
itenscategoria: {
padding:15,
border: 1,
borderRadius:25,
marginRight:10,
},
section: {
marginTop: 10,
backgroundColor: '#ccc',
width: '100%',
height: 200,
borderRadius: 10,
},
});

Change color after click on TouchableHighlight in react native

I have done a many research on the color change after press/click. Finally
I got this script for change the state and put it in the TouchableHighlight. But When i clicked on that, only the "underlayColor={'gray'}" is working. Can i get some idea ?
here is my code
import React, { Component } from 'react';
import {
StyleSheet,
Text,
StatusBar ,
TouchableOpacity,
View,
FlatList,
ActivityIndicator,
TouchableHighlight,
PropTypes,
Image,
Alert
} from 'react-native';
import Logo from '../components/Logo';
import Form from '../components/Front';
import {Actions} from 'react-native-router-flux';
export default class Login extends Component<{}> {
constructor() {
super();
this.state = {
dataSource: {},
pressed: false
};
}
izijackpotconfirm() {
Actions.izijackpotconfirm()
}
componentDidMount() {
var that = this;
let items = Array.apply(null, Array(25)).map((v, i) => {
return { id: i+1 };
});
that.setState({
dataSource: items,
});
}
static navigationOptions = {
title: "Izi Jackpot",
headerStyle: {
backgroundColor: "#354247"
},
headerTintColor: "#fff",
headerTitleStyle: {
fontWeight: "bold"
}
};
render() {
var jackpotNumbers = [];
let btn_class = this.state.black ? "NormalSet" : "SelectedSet";
return(
<View style={styles.container}>
<View style={styles.middlecontainer}>
<Text style={styles.logoText}>Please Select 5 Numbers and Submit</Text>
</View>
<FlatList
data={this.state.dataSource}
renderItem={({ item }) => (
<View style={{ flex: 1, flexDirection: 'column', margin: 1 }}>
<TouchableHighlight
onPress={() => { Alert.alert(this.state.pressed) }}
style={[
styles.iziPizi,
this.state.pressed ? { backgroundColor: "blue" } : {}
]}
onHideUnderlay={() => {
this.setState({ pressed: false });
}}
onShowUnderlay={() => {
this.setState({ pressed: true });
}}
underlayColor={'gray'}
>
<Text style={styles.buttonText}>{ item.id}</Text></TouchableHighlight>
</View>
)}
//Setting the number of column
numColumns={5}
keyExtractor={(item, index) => index}
/>
<View style={styles.middlecontainer}>
<TouchableOpacity style={styles.button} onPress={this.izijackpotconfirm} >
<Text style={styles.buttonText}>Submit</Text>
</TouchableOpacity>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container : {
backgroundColor:'#6F9000',
justifyContent: 'center',
flex: 1,
paddingTop: 30,
},
middlecontainer: {
textAlign: 'center',
alignItems: 'center',
justifyContent :'center',
flex:1
},
signupTextCont : {
flexGrow: 1,
alignItems:'flex-end',
justifyContent :'center',
paddingVertical:16,
flexDirection:'row'
},
signupText: {
color:'rgba(255,255,255,0.6)',
fontSize:16
},
signupButton: {
color:'#ffffff',
fontSize:16,
fontWeight:'500'
},
iziPizi: {
width: 55,
padding: 15,
margin: 5,
borderRadius: 80,
borderWidth: 2,
borderColor: '#FFFFFF',
flex:1
},
iziPiziPress: {
width: 55,
padding: 15,
margin: 5,
backgroundColor:'#1c313a',
borderRadius: 80,
borderWidth: 2,
borderColor: '#FFFFFF',
flex:1
},
button: {
width:300,
backgroundColor:'#1c313a',
borderRadius: 25,
marginVertical: 10,
paddingVertical: 13
},
buttonText: {
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
logoText : {
color:'#FFFFFF',
fontSize: 16,
fontWeight: '500',
alignItems: 'center',
justifyContent:'center',
},
imageThumbnail: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
},
});
One more thing to say that, i have used FlatList here. Please help on this. Thanks in advance.
The problem is in how you work with the styles inside the Touchable. My advice is to create 2 styles that contain the changes:
style={
this.state.pressed ? styles.pressed : styles.iziPizi
}
Inside the touchable of course:
<TouchableHighlight
onPress={() => { Alert.alert(this.state.pressed) }}
style={
this.state.pressed ? styles.pressed : styles.iziPizi
}
onHideUnderlay={() => {
this.setState({ pressed: false });
}}
onShowUnderlay={() => {
this.setState({ pressed: true });
}}
underlayColor={'gray'}
>
yes. there was a problem in FlatList. but i dont know what is its problem.
use ListItem of native-base instead.
remember that if you want to use ListItem, in constructor change
this.state = {
dataSource: {},
...
}
to
this.state = {
dataSource: [],
}
use array insead. here is a sample code for you.
<View style={{ flex: 1, flexDirection: 'column', margin: 1 }}>
<List>
{this.state.dataSource.map( item =>
<ListItem>
<TouchableHighlight
onPress={() => {}}
onShowUnderlay={this.onPress.bind(this)}
>
<Text style={styles.buttonText}>{ item.id}</Text>
</TouchableHighlight>
</ListItem> )
}
</List>
</View>
Also define onPress method.
another problem in your code is this that you setState of pressed.
it results that all of your element style will be changed. so all of your button backgroundColor will be changed.
so you must define pressed flag for every element in your array and change this flag

How to handle Drag'n Drop gesture on horizontal FlatList with fixed height

I am trying to implement a Drag'n Drop functionality in my React Native application. I have already made a pretty good study of Gesture Responder System and PanResponder in particular as well as an Animated class, but I can not come up with a proper solution around connecting them with FlatList component.
The problem is that when I am trying to shift a Responder item beyond the scope of the View component wrapping FlatList (height: 80) it is visually getting hidden and parent Component obviously overlaps it..
Here is the screenShot: http://joxi.ru/82Q0dn1CwwE1Vm
Here is my code:
import React from 'react';
import {
SafeAreaView,
View,
FlatList,
Text,
StyleSheet,
Animated,
PanResponder
} from 'react-native';
import { v4 } from 'uuid';
export default class App extends React.PureComponent{
state = {
data: [
{ id: v4(), title: 'Lightcoral', hex: '#eb7474' },
{ id: v4(), title: 'Orchid', hex: '#eb74dc' },
{ id: v4(), title: 'Mediumpurple', hex: '#9a74eb' },
{ id: v4(), title: 'Mediumslateblue', hex: '#8274eb' },
{ id: v4(), title: 'Skyblue', hex: '#74b6eb' },
{ id: v4(), title: 'Paleturquoise', hex: '#93ece2' },
{ id: v4(), title: 'Palegreen', hex: '#93ecb6' },
{ id: v4(), title: 'Khaki', hex: '#d3ec93' }
]
}
_position = new Animated.ValueXY()
_panResponder = PanResponder.create({
onStartShouldSetPanResponder: () => true,
onPanResponderMove: (event, gesture) => {
this._position.setValue({ x: gesture.dx, y: gesture.dy})
},
onPanResponderRelease: () => {}
})
_keyExtractor = (item) => item.id;
_renderItem = ({item}) => {
return (
<Animated.View
style={this._position.getLayout()}
{...this._panResponder.panHandlers}
>
<View style={[styles.itemBox, {backgroundColor: `${item.hex}`}]}>
<Text>{item.title}</Text>
</View>
</Animated.View>
)
}
render() {
const { data } = this.state
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
<View style={styles.targetArea}>
<Text>Drop HERE!!!</Text>
</View>
<View style={{ height: 80, borderColor: 'black', borderWidth: 2 }}>
<FlatList
data={data}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
horizontal={true}
/>
</View>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
safeArea: {
flex: 1
},
container: {
flex: 1,
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: '#fff',
},
itemBox: {
width: 80,
height: 80,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#fff'
},
targetArea: {
height: 150,
width: 150,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
borderColor: '#eee',
backgroundColor: '#F5FCFF',
marginTop: 40
}
});
How can I change the location of the particular item of the FlatList, which is in a horizontal mode and has a fixed height, and move it to another area of the screen??
Please help me to knock that one out, every advice is much appreciated!

Why can't I access this.props.navigation in react native Alert?

Alert.alert(
'',
'Kindly Select from the following Actions',
[
{
text: 'Edit',
onPress: () => this.props.navigation.navigate(
'PositionForm',
{
formType: 'edit',
item: this.props.position
}
)
},
{ text: 'Delete', onPress: () => console.log('delete Pressed') },
]
);
I am looking for a work around. I want to navigate to another page when an edit button is clicked on alert. I am using react-navigation and redux. Kindly Help.
Thanks in advance.
COmplete Component COde is below:
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Alert } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
class PositionItem extends Component {
showAlert() {
Alert.alert(
'',
'Kindly Select from the following Actions',
[
{
text: 'Edit',
onPress: () => this.props.navigation.navigate(
'PositionForm',
{
formType: 'edit',
item: this.props.position
}
)
},
{ text: 'Delete', onPress: () => console.log('delete Pressed') },
]
);
}
render() {
const {
positionContainer,
textStyle,
iconsStyle,
positionName,
starIconStyle
} = styles;
const {
name
} = this.props.position;
return (
<TouchableOpacity onPress={this.showAlert.bind(this)}>
<View style={positionContainer}>
<View style={positionName}>
<Text style={textStyle}>{name}</Text>
</View>
<View style={iconsStyle}>
<Icon style={starIconStyle} name="star-o" size={30} color="#ccc" />
<Icon name="angle-right" size={30} color="#ccc" />
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
positionContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingTop: 15,
paddingBottom: 15,
borderBottomWidth: 1,
borderColor: '#ccc'
},
textStyle: {
marginBottom: 0,
color: '#333333',
fontSize: 20,
fontWeight: '600',
borderLeftWidth: 6,
borderColor: '#cccccc',
paddingLeft: 20,
paddingTop: 5,
paddingBottom: 5,
lineHeight: 20
},
iconsStyle: {
flexDirection: 'row',
flex: 20,
},
starIconStyle: {
paddingTop: 2,
paddingRight: 15
},
positionName: {
flex: 80
}
});
export default PositionItem;
I can't see the issue, but worse case you can just put the variable in the upper scope.
showAlert() {
const {navigation, position} = this.props
Alert.alert(
Also I prefer not to bind and use the new syntax for creating class fields, you always get the right this.
showAlert = () => {
...
}
<TouchableOpacity onPress={this.showAlert}>

React Native FlatList not scrolls vertically with custom renderItem and unable to view all items in the list

I have created a screen put a image as a background for whole screen. I want to show an array list with FlatList. I have created a separate function component as a cardItem for FlatList item and wrapped it inside a <View></View> element. I have searched a lot and read the question answers on lot of sites also, but my FlatList doesn't scrolls vertically and eventually i am unable to view some items in the ArrayList. Here is my some Sample Code :
<View
style={{
width: "100%",
height: "100%",
alignItems: "stretch",
flexDirection: "column",
position: "absolute",
justifyContent: "center"
}}
>
<View
style={{
flex: 2,
alignItems: "center",
justifyContent: "center",
alignSelf: "center"
}}
>
<Text
style={{ fontSize: 22, fontWeight: "bold", color: "#ffffff" }}
>
My Events List
</Text>
</View>
<View
style={{
flex: 8,
alignItems: "center",
justifyContent: "center",
paddingHorizontal: 15
}}
>
<FlatList
style={{ width: "100%", marginBottom: 15 }}
data={eventsCreatedList}
keyExtractor={item => {
return item.id;
}}
renderItem={({ item }) => <EventsCreatedListItem item={item} />}
/>
</View>
</View>
Please tell me where i am going wrong. Thank in advance guys!
I tried this sample at https://snack.expo.io/?session_id=snack-session-wKlWVe6l2, which is working with the Flatlist and showing in a scroll view. Please have a look.
import React from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text } from 'react-native';
import Constants from 'expo-constants';
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'Fourth Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Fifth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Sixth Item',
},
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'Seventh Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Eighth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Nineth Item',
},
];
function Item({ title }) {
return (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
}
export default function App() {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: Constants.statusBarHeight,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});