react-native swipeable gesture not working on android? - javascript

I am doing a react native course with Mosh (https://codewithmosh.com/). I am using expo. I am very new to react native and don't really know what I am doing, but I know my code should work. I double-checked my code against his and even went so far as to copy my project over to a friends mac and see if the code works on ios (as mosh is running his code on the ios simulator). On the ios simulator, my code runs perfectly, but on android, nothing happens.
Here is where I implement the swipeable itself:
import React from 'react';
import { StyleSheet, View, Image, TouchableHighlight } from 'react-native';
import Swipeable from 'react-native-gesture-handler/Swipeable';
import AppText from './AppText';
import colors from '../config/colors';
function ListItem({title, subtitle, image, onPress, renderRightActions}) {
return (
<Swipeable renderRightActions={renderRightActions} >
<TouchableHighlight underlayColor={colors.light} onPress={onPress} >
<View style={styles.container} >
<Image style={styles.image} source={image} />
<View>
<AppText style={styles.title} >{title}</AppText>
<AppText style={styles.subTitle}>{subtitle}</AppText>
</View>
</View>
</TouchableHighlight>
</Swipeable>
);
}
I then export this to a different screen:
function MessagesScreen(props) {
return (
<Screen>
<FlatList
data={messages}
keyExtractor={message => message.id.toString}
renderItem={({ item }) => (
<ListItem
title={item.title}
subtitle={item.description}
image={item.image}
onPress={() => console.log('message selected', item)}
renderRightActions={ListItemDeleteAction}
/>
)}
ItemSeparatorComponent={ListItemSeparator}
/>
</Screen>
);
}
the listItemDelete action I am passing into the renderRightActions prop can be seen here:
function ListItemDeleteAction(props) {
return (
<View style={styles.container} ></View>
);
}

Alright so, I found a solution by wrapping the swipeable in a gestureHandlerRootView.
import { GestureHandlerRootView, Swipeable } from "react-native-gesture-handler";
import AppText from "./AppText";
import colors from "../config/colors";
function ListItem({ title, subtitle, image, onPress, renderRightActions }) {
return (
<GestureHandlerRootView>
<Swipeable renderRightActions={renderRightActions}>
<TouchableHighlight underlayColor={colors.light} onPress={onPress}>
<View style={styles.container}>
<Image style={styles.image} source={image} />
<View>
<AppText style={styles.title}>{title}</AppText>
<AppText style={styles.subTitle}>{subtitle}</AppText>
</View>
</View>
</TouchableHighlight>
</Swipeable>
</GestureHandlerRootView>
);
}

I found a solution by wrapping the swipeable in a gestureHandlerRootView.
import { GestureHandlerRootView } from "react-native-gesture-handler";
import AppText from "./AppText";
import colors from "../config/colors";
function ListItem({ title, subtitle, image, renderRightActions }) {
return (
<GestureHandlerRootView>
<Swipeable renderRightActions={renderRightActions}>
<View style={styles.main}>
<Image style={styles.img} source={image} />
</View>
</Swipeable>
</GestureHandlerRootView>
);
}

try this option...
import {
GestureHandlerRootView,
Swipeable,
} from "react-native-gesture-handler";
then wrap on <Swipeable>..</Swipeable>
look example below
<GestureHandlerRootView>
<Swipeable renderRightActions={renderRightActions}>
<TouchableHighlight underlayColor={Colors.ccc} onPress={onPress}>
<View style={styles.view}>
<Image style={styles.image} source={image} />
<View style={styles.details}>
<Txt style={styles.title}>{title}</Txt>
<Txt style={styles.subtitle}>{subtitle}</Txt>
</View>
</View>
</TouchableHighlight>
</Swipeable>
</GestureHandlerRootView>

Related

Modal not getting opened on clicking the image of gallery component

I'm trying to open a model when I click on the image component in the gallery. Here I'm not getting the "flagImage" variable updated in onPress method of TouchableOpacity or the modal component is not getting the updated value of "flagImage" when onPress of TouchableOpacity changes its value. I need help here. The modal doesn't open at all whenever I touch the image component. It just does nothing :( Below is the code for gallery.component.js:
import React from 'react';
import { View, Image, ScrollView, TouchableOpacity, Modal, Text } from 'react-native';
import styles from './cameraStyles';
export default ({captures=[], flagImage=true}) => (
<ScrollView
horizontal={true}
style={[styles.bottomToolbar, styles.galleryContainer]}
>
{captures.map(({ uri }) => (
<View style={styles.galleryImageContainer} key={uri}>
<TouchableOpacity
onPress={()=> {
flagImage = !flagImage;
console.log('Touch: "'+flagImage+'"');
}}
>
<Image source={{ uri }} style={styles.galleryImage}/>
</TouchableOpacity>
<Modal visible={flagImage} onPress={() => {console.log('Modal: "'+flagImage+'"');flagImage = !flagImage;}} onRequestClose={() => flagImage = ! flagImage}>
<View>
<Image source={{ uri }} style={styles.galleryImageLarge}/>
</View>
</Modal>
</View>
))}
</ScrollView>
);
You can make use of useState hook to convert the props into a state where you can update them.
import React from 'react';
import { View, Image, ScrollView, TouchableOpacity, Modal, Text } from 'react-native';
import styles from './cameraStyles';
export default ({captures=[], lflagImage=false}) => {
const [flagImage, setflagImage] = React.useState(lflagImage);
return (
<ScrollView
horizontal={true}
style={[styles.bottomToolbar, styles.galleryContainer]}
>
{captures.map(({ uri }) => (
<View style={flagImage?styles.galleryImageContainer:styles.galleryImageContainerView} key={uri}>
<TouchableOpacity
onPress={()=> {
setflagImage(prevData => !prevData)
console.log('Touch: "'+flagImage+'"');
}}
>
<Image source={{ uri }} style={flagImage?styles.galleryImage:styles.galleryImageLarge}/>
</TouchableOpacity>
<Modal visible={flagImage} onRequestClose={() => setflagImage(prevData => !prevData)}>
<View>
<Image source={{ uri }} style={styles.galleryImageLarge}/>
</View>
</Modal>
</View>
))}
</ScrollView>
)
}

Not able to Scroll React Native

I was creating an app that sells ebooks and when creating the details page for each book, I wrapped the entire component with a scroll view but it does not work, you can see my result in the screen recording attached, I looked through many solutions but could not find a fix for my issue,
Here is my code of the component that's causing the issue:
import React, {useState, useEffect} from 'react';
import axios from '../../axios.config';
import {ScrollView, View, Text, Image, useWindowDimensions} from 'react-native';
import RenderHtml from 'react-native-render-html';
import Button from '../../components/Button';
import OutlineButton from '../../components/OutlineButton';
import Rating from '../../components/Rating';
import Header from './components/Header';
import BookDataRail from './components/BookDataRail';
import {Book} from '../../types/Book';
import {ReadBook, PlayWhite} from '../../icons';
import styles from './styles';
import Review from '../../components/Review';
interface BookDetailsProps {}
const BookDetails: React.FC<BookDetailsProps> = () => {
const [bookDetails, setBookDetails] = useState<Book>();
const {width} = useWindowDimensions();
useEffect(() => {
const getData = async () => {
const {data} = await axios.post('/', {
method: 'bookdetails',
book_id: 4,
});
setBookDetails(data);
};
getData();
}, []);
return (
<View style={{flex: 1}}>
<ScrollView scrollEnabled={true} contentContainerStyle={{backgroundColor: "white", flexGrow: 1}}>
{/* Cover Image/Header */}
<View
style={{
height: '40%',
}}>
<Header coverUrl={bookDetails?.cover_url} />
</View>
{/* Content */}
<View style={styles.body}>
{/* Book Title */}
<Text style={styles.bookTitleText}>{bookDetails?.title}</Text>
{/* Author Name */}
<Text style={styles.authorNameText}>{bookDetails?.author_name}</Text>
{/* Main Rating */}
<View style={styles.ratingContainer}>
<Rating
rating={bookDetails ? bookDetails.rating_review.rating : 0}
/>
</View>
{/* Play Audio/Read Book Buttons */}
<View style={styles.buttonsContainer}>
<Button
title="Play Audio"
width={'48%'}
leftAccessory={
<Image source={PlayWhite} style={styles.buttonIcon} />
}
/>
<OutlineButton
title="Read Book"
width={'48%'}
leftAccessory={
<Image source={ReadBook} style={styles.buttonIcon} />
}
/>
</View>
{/* Add to Wishlist */}
<Text style={styles.addToWishlistText}>+ Add to Wishlist</Text>
{/* Book Details Rail */}
<View style={styles.bookRailContainer}>
{bookDetails && (
<BookDataRail
downloads={bookDetails.downloads}
language={bookDetails.language}
pages={bookDetails.num_pages}
genre={bookDetails.genre_name}
/>
)}
</View>
{/* Book Description */}
<View style={styles.descriptionContainer}>
<Text style={styles.sectionTitle}>Summary</Text>
<ScrollView
nestedScrollEnabled
style={styles.descriptionTextContainer}>
<RenderHtml
contentWidth={width}
source={{html: bookDetails?.description || ''}}
/>
</ScrollView>
</View>
{/* Ratings */}
<View style={styles.ratingsContainer}>
<Text style={styles.sectionTitle}>Reviews</Text>
{/* Ratings Header */}
<View style={styles.ratingsHeader}>
<Text style={styles.ratingText}>
{bookDetails?.rating.toFixed(1)}
</Text>
<View>
<View style={styles.ratingContainerSmall}>
<Rating
rating={bookDetails ? bookDetails.rating_review.rating : 0}
noText
/>
</View>
<Text style={styles.numRatingsText}>
{bookDetails?.rating_review.review_comments.length || 0}{' '}
reviews
</Text>
</View>
</View>
{/* Showing all reviews */}
<View style={styles.reviewCommentsContainer}>
{bookDetails?.rating_review.review_comments.map(
(reviewComment, index) => (
<Review
key={index}
name={reviewComment.name}
rating={reviewComment.rating}
date={reviewComment.date}
comment={reviewComment.comment}
/>
),
)}
</View>
</View>
</View>
</ScrollView>
</View>
);
};
export default BookDetails;
The issue is definitely with the top view that's containing the header, if I remove it it works file, I also tried using it without the Header component inside, but it still does not work...
And here is the result I'm getting
https://drive.google.com/file/d/121x2CNuj3M63aJu_Z1PjxYbYxivCrhuP/view?usp=sharing
Any help would be appreciated,
Thanks
Have you tried to apply contentContainerStyle={{flexGrow: 1}} and container={{flex: 1}}?
Seems like it should do the trick 🙂
How about wrapping the scrollview comp inside a container like below
<View style = {{ flex : 1 }}>
<ScrollView contentContainerStyle = {{ flexGrow : 1 }}>
</ScrollView>
</View>

React Native: I can't set a TextInput value from a 'child' screen

I am working in React Native and I want to set a value in a non-editable TextInput. The value is written on a screen that I am navigating to. Meaning; "parent" screen has the empty input -> I navigate to a "child" screen in which I can enter the value in another TextInput. When I have done that I want to press "OK" and go back to the "parent" screen where the value is displayed.
I have read the documentation as thoroughly as I could, but I still can't get it to work. I can set the value in the "child" screen, but the value is not updated when I navigate back to the parent.
Parent screen
Disregard the code related to equipment, since it will assimilate the barcode logic
import React, { useState } from 'react'
import { Text, TouchableOpacity, View, Image, TextInput } from 'react-native'
import styles from './styles';
import { IMAGE } from '../../constants/Images'
import { CustomHeader } from '../../CustomHeader'
export default function SamplingScreen({ navigation, route }) {
//const [barcodeData, setBarcodeData] = useState('32231321')
const [equipmentID, setEquipmentID] = useState('')
//Guarding against undefined value
const barcode = route.params?.barcode ?? 'Barcode'
return (
<View style={styles.container}>
<CustomHeader title="Sample Oil" navigation={navigation} isHome={true} ></CustomHeader>
<View style={styles.contentContainer}>
<Image
style={styles.logo}
source={IMAGE.ICON_LOGO}
/>
<Text>Send an oil sample for analysis</Text>
<Text>Start by linking a bottle with its barcode</Text>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('BottleID')} /*barcodeData={setBarcodeData}*/ >
<Text style={styles.buttonText} >Link Bottle</Text>
</TouchableOpacity>
<Text>Please link the equipment from which the sample was taken</Text>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('EquipmentID')} equipmentID={setEquipmentID} >
<Text style={styles.buttonText} >Link Equipment</Text>
</TouchableOpacity>
<Text>This is the bottle barcode</Text>
<TextInput
editable={false}
style={styles.input}
defaultValue={barcode}
value={barcode}
underlineColorAndroid="transparent"
autoCapitalize="none">
</TextInput>
<Text>This is the equipment barcode</Text>
<TextInput
editable={false}
style={styles.input}
defaultValue={equipmentID}
value={equipmentID}
underlineColorAndroid="transparent"
autoCapitalize="none">
</TextInput>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Accept</Text>
</TouchableOpacity>
</View>
</View>
)
}
Child screen
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, TextInput } from 'react-native';
import { CustomHeader } from '../../../CustomHeader'
import styles from './styles'
export default function SetBottleIDScreen({ navigation, route }) {
const [barcodeData, setBarcodeData] = useState('')
console.log(barcodeData)
return (
<View style={styles.container} >
<CustomHeader title="Bottle ID" isHome={false} navigation={navigation} ></CustomHeader>
<Text style={{ marginTop: 30, marginBottom: 30 }} > Set barcode for sampling bottle </Text>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Camera')}>
<Text style={styles.buttonText}>Scan Barcode</Text>
</TouchableOpacity>
<Text style={{ marginTop: 60, marginBottom: 10 }} >Insert Barcode</Text>
<TextInput
style={styles.input}
placeholder='Barcode'
placeholderTextColor="#aaaaaa"
onChangeText={(text) => setBarcodeData(text)}
value={barcodeData}
underlineColorAndroid="transparent"
autoCapitalize="none">
</TextInput>
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Sampling', { screen: 'Sampling', params: { barcode: barcodeData }, merge: true })}>
<Text style={styles.buttonText} >OK</Text>
</TouchableOpacity>
</View>
);
}
I am using React Navigation 5.x. I am pretty sure that the value has to be parsed as a parameter with route, but something isn't working as intended.
I solved the issue.
The syntax for setting the parameters were wrong.
It should look like this in stead:
<TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Sampling', { barcode: barcodeData })}>
<Text style={styles.buttonText} >OK</Text>
</TouchableOpacity>

Is there a way to change text colour of a text element on a parent component from the child component in React Native?

Is there a way to change the text colour of a text element on a parent component from the child component in React Native?
I have done it with the icon in the code below, can I do it with text?
Discover More Parent Component
import React from 'react';
import {Text, View, TouchableOpacity, StyleSheet} from 'react-native';
import Colors from '#miniclementine:common/appearance/Colors';
import ClementineIcon from '#miniclementine:common/components/ClementineIcon';
export default function DiscoverMore({title, onPress, color}) {
return (
<TouchableOpacity onPress={onPress}>
<View style={styles.btnContainerStyle}>
<ClementineIcon name="add-circle-bold" color={color} size={24} />
<Text style={styles.btnTextStyle}> {title} </Text>
</View>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
btnContainerStyle: {
paddingVertical: 16,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
},
btnTextStyle: {
color: Colors.cornflower,
fontSize: 16,
textAlign: 'center',
}
});
HomePage bringing in DiscoverMore component and changing colour of icon using props
export default function SessionHomepage({navigation, passData, onPress}) {
const onPressSectionHeader = ({onPress}) => {
navigation.navigate(SESSIONS_LIST_PAGE, passData)
// #TODO: navigate to a page using navigation.navigate(pageName, params);
};
const onPressSectionHeaderInvalid = () => {
alert('Out of scope for this task')
// #TODO: navigate to a page using navigation.navigate(pageName, params);
};
const onContactPress = () => {
Linking.openURL('mailto:alina#clementineapp.co.uk?subject=SendMail&body=Description')
}
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<View style={styles.content}>
<SectionHeader
title="Morning Sessions"
onPress={onPressSectionHeaderInvalid}
/>
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeaderInvalid}
color={Colors.cornflower}
/>
<SectionHeader
title="Pick-me-ups"
onPress={onPressSectionHeader}
/>
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeader}
color={Colors.cornflower}
/>
</View>
<View style={styles.sleepSection}>
<Image
source={require('../../assets/illustrations/sleep_section.png')}
style={{height: 250, width: '100%'}}
/>
</View>
<View style={styles.content}>
<View style={styles.sleepSection}>
<SectionHeader
title="Sleep Sessions"
onPress={onPressSectionHeaderInvalid}
/>
<Text>test</Text>
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeaderInvalid}
color={Colors.powderBlue}
/>
</View>
</View>
<BlueButton title="Leave us feedback" onPress={onContactPress}/>
</ScrollView>
</SafeAreaView>
);
}
Try this way
Discover page
export default function DiscoverMore({title, onPress, color, textColor}) {
return (
<TouchableOpacity onPress={onPress}>
<View style={styles.btnContainerStyle}>
<ClementineIcon name="add-circle-bold" color={color} size={24} />
<Text style={[styles.btnTextStyle,{color: textColor}]}> {title} </Text>
</View>
</TouchableOpacity>
);
}
Home Page
<DiscoverMore
title="Discover more sessions"
onPress={onPressSectionHeaderInvalid}
color={Colors.cornflower}
textColor={Colors.cornflower} // add text color here
/>

TouchableOpacity effect on Text

I want my Menu text to have the same effect that TouchableOpacity does on touch.And open a new screen
***Settings.js***
import React, { useState } from 'react'
import{StyleSheet,Text,View,TextInput} from 'react-native'
import { TouchableOpacity,FlatList,ScrollView } from 'react-native-gesture-handler'
export default function App(){
const[menu,menupeople]=useState([
{name:'My Account',key:1},
{name:'Notification Settings',key:2},
{name:'Clear Cache',key:3},
{name:'Legal Information',key:4},
{name:'Rate App Tak',key:5},
{name:'Version',key:6},
{name:'About',key:7},
])
return(
<View style={styles.container}>
<ScrollView>
{menu.map((item)=>{
return(
<View
key={item.key}
>
<Text style={styles.item}
>{item.name}</Text>
</View>
)
})}
</ScrollView>
</View>
)
}
const styles=StyleSheet.create({
container:{
flex:1,
backgroundColor:'#fff',
paddingTop:40,
paddingHorizontal:20,
alignItems:'center'
}
})
Is there any way to do this i am first time applying touchable opacity to a menu of items and each of them opens a new screen
You can use the touchableopacity instead of the View to wrap the menu item like below
{menu.map((item)=>{
return(
<TouchableOpacity onPress={()=>alert(item.name)}
key={item.key}
>
<Text style={styles.item}
>{item.name}</Text>
</TouchableOpacity>
)
})}
Here I've put an alert you can change it to your navigation code.
And please import the TouchableOpacity from react native
import { TouchableOpacity } from "react-native";

Categories

Resources