I am developing an app in android using react-native. The problem is when I use WebView, it only works on some devices, mostly the ones with older OS on android.
I have tried using this code and modified it a bit. It worked on some phones, but the elements inside the webview doesn't show in my own phones.
It renders like this, while it should have rendered something like this
Here is the snippet of ListSoal.js that contains the code to the WebView
import React, { Component } from 'react'
import {
ScrollView,
TouchableOpacity,
Alert,
Image,
Modal,
Text,
BackHandler,
WebView,
AsyncStorage,
Dimensions,
Platform
} from 'react-native'
const injectedScript = function () {
function waitForBridge () {
if (window.postMessage.length !== 1) {
setTimeout(waitForBridge, 200)
} else {
let height = 0
if (document.documentElement.clientHeight > document.body.clientHeight) {
height = document.documentElement.clientHeight
} else {
height = document.body.clientHeight
}
}
window.postMessage(height)
}
waitForBridge()
}
export default class ListSoal
extends Component {
state = {
webViewHeight: Number,
webViewHeightAnswer: Number
}
static defaultProps = {
autoHeight: true,
autoHeightAnswer: true
}
constructor (props) {
super(props)
this.state = {
webViewHeight: this.props.defaultHeight,
webViewHeightAnswer: this.props.defaultHeight
}
this._onMessage = this._onMessage.bind(this)
this._onMessageAnswer = this._onMessageAnswer.bind(this)
}
_onMessage (e) {
this.setState({
webViewHeight: parseInt(e.nativeEvent.data)
})
}
_onMessageAnswer (e) {
this.setState({
webViewHeightAnswer: parseInt(e.nativeEvent.data)
})
}
render () {
const { loading } = this.state
if (loading === true) {
return <CommonIndicator color={'#eb6a16'} size={'large'} />
}
if (this.state.soals.length <= 0) {
return (
<View style={styles.notContent}>
<Text style={styles.textNull}>{strings.exercises.notExercises}</Text>
</View>
)
}
const _w = this.props.width || Dimensions.get('window').width - '5%'
const _wA = this.props.width || 265
const _h = this.props.autoHeight ? this.state.webViewHeight : this.props.defaultHeight
const _hA = this.props.autoHeightAnswer ? this.state.webViewHeightAnswer : this.props.defaultHeight
const { animate, soals, no, totalQuestion, displayNumber, selected } = this.state
return (
<View style={styles.mainContainer}>
<View style={styles.topButtonGroup}>
<View style={{flexDirection: 'row', width: '100%', justifyContent: 'space-between'}}>
<View style={{width: '50%'}}>
<TouchableOpacity
onPress={() => this.onNumberModal()}
style={styles.btnNumber}>
<Text style={styles.textbutton}>{strings.exercises.number}</Text>
</TouchableOpacity>
</View>
<View style={{width: '50%'}}>
{
loading === true
? null
: soals[no].question.solution_id === null
? <View
style={[styles.btnSale, {backgroundColor: '#dddddd'}]}>
<Text style={styles.textbutton}>{strings.exercises.solution}</Text>
</View>
: <TouchableOpacity
onPress={() => this.checkSolution()}
style={styles.btnSale}>
<Text style={styles.textbutton}>{strings.exercises.solution}</Text>
</TouchableOpacity>
}
</View>
</View>
<View style={{flex: 1}} />
</View>
<View style={styles.backgquestion}>
<ScrollView>
<View animation={animate} duration={1100} style={styles.listquestion}>
<View style={styles.modal}>
<Text style={styles.number}>Number: {displayNumber + 1}</Text>
</View>
{
soals[no].question.image === null ? null : <Image resizeMode={'stretch'} source={{uri: config.storageUrl + soals[no].question.image}} style={styles.imagequestion} />
}
<View style={styles.soals}>
<WebView
scalesPageToFit={Platform.OS !== 'ios'}
ref={(ref) => { this.webview = ref }}
injectedJavaScript={'(' + String(injectedScript) + ')();'}
scrollEnabled={this.props.scrollEnabled || false}
onMessage={this._onMessage}
javaScriptEnabled={true}
automaticallyAdjustContentInsets={true}
{...this.props}
source={{html: soals[no].question.question}}
style={[{width: _w}, this.props.style, {height: _h}]}
/>
</View>
I have tried changing flex properties many times, but it seems that the problem comes from height = document.body.clientHeight or height document.elementBody.clientHeight because when I changed it to an integer, it worked.
Any suggestions? Thanks in advance
Related
Hello there, I world be extremely grateful if someone could help me with this problem. I am new to react native and I wanted to the data inside the table instead of having its text because I think it will look better.I have stuck with this problem for a quite while and I couldnt find any sources to deal with this problem. Hope you can help me. Here is my code:
import React, { useState } from 'react';
import {View, Dimensions, Alert, Text, StyleSheet, Button, ScrollView, Pressable, ToastAndroid } from 'react-native';
import DestinationSearch from '../../components/DestinationSearch'
import { useRoute, useNavigation, useFocusEffect, useIsFocused } from '#react-navigation/native';
import { useEffect } from 'react';
import AsyncStorage from '#react-native-async-storage/async-storage';
import moment from 'moment';
import { Table, Row, Rows } from 'react-native-table-component';
const MapScreen = (props) => {
async function loopBusPressed (loopBusId) {
const locations = JSON.parse(await AsyncStorage.getItem('locations'));
const loopBusesCurrentLocation = JSON.parse(await AsyncStorage.getItem('loopBusesCurrentLocation'));
const loopBus = loopBusesCurrentLocation.find(bus => bus.id == loopBusId);
const loopBusLocation = locations.find(loc => loc.id == loopBus.loopBusLocationId)
const mockUserLocation = JSON.parse(await AsyncStorage.getItem('mockUserLocation'));
setloopBusLocation(loopBusLocation)
setmockUserLocation(mockUserLocation)
setCoordinates(
[
loopBusLocation.coordinates,
mockUserLocation.coordinates
]
)
setSelectedLoopBus(loopBusId)
const arrivalDetails = [];
const filteredLoopBusLocations = locations.filter(loc => loc.loopBusId == loopBusId)
filteredLoopBusLocations.forEach(loc => {
const currentBusStopNum = loopBusLocation.stopNumber
const destStopNum = loc.stopNumber
let calculatedArrival;
let aggMinutes = 0;
let includedLocations;
if (currentBusStopNum > destStopNum) {
includedLocations = filteredLoopBusLocations.filter(loc => loc.stopNumber > currentBusStopNum || loc.stopNumber <= destStopNum)
includedLocations.forEach(loc => {
aggMinutes += loc.durationInto
})
calculatedArrival = moment(new Date()).add(aggMinutes, 'm').format('LT')
} else if (currentBusStopNum < destStopNum) {
includedLocations = filteredLoopBusLocations.filter(loc => loc.stopNumber > currentBusStopNum && loc.stopNumber <= destStopNum )
includedLocations.forEach(loc => {
aggMinutes += loc.durationInto
})
calculatedArrival = moment(new Date()).add(aggMinutes, 'm').format('LT')
} else {
filteredLoopBusLocations.forEach(loc => {
aggMinutes += loc.durationInto
})
calculatedArrival = moment(new Date()).add(aggMinutes, 'm').format('LT')
}
arrivalDetails.push({
stopNumber: loc.stopNumber,
location: loc.location,
arrival: calculatedArrival
})
})
setArrivalDetails(arrivalDetails)
console.log(arrivalDetails)
}
const [coordinates, setCoordinates] = useState([]);
const [loopBusLocation, setloopBusLocation] = useState({});
const [mockUserLocation, setmockUserLocation] = useState({});
const [selectedLoopBus, setSelectedLoopBus] = useState(1);
const [arrivalDetails, setArrivalDetails] = useState([]);
useEffect(() => {
loopBusPressed(1)
}, []);
// const selectedItem = {
// title: 'Selected item title',
// description: 'Secondary long descriptive text ...',
// };
const header = ['Bus Stop', 'Location', 'Time']
const data = [
['gfg1', 'gfg2', 'gfg3'],
['gfg4', 'gfg5', 'gfg6'],
['gfg7', 'gfg8', 'gfg9']
]
const isFocused = useIsFocused();
alert(isFocused);
useFocusEffect(
React.useCallback(() => {
return () => null;
}, [])
);
return (
<View style={{display: 'flex', justifyContent: 'space-between'}}>
<View style={{height: Dimensions.get('window').height - 400}}>
<DestinationSearch coordinates={coordinates} />
</View>
<View style={{height: 400}}>
<ScrollView>
<View style={styles.page}>
<View style={styles.container}>
{/* TODO */}
<Pressable
style ={styles.button}
onPress={() => loopBusPressed(1)}
>
<Text style ={styles.buttonText}>Loop Bus 1</Text>
</Pressable>
{/* TODO */}
<Pressable
style ={styles.button}
onPress={() => loopBusPressed(2)}
>
<Text style ={styles.buttonText}>Loop Bus 2</Text>
</Pressable>
</View>
<View style={styles.page}>
{/* TODO */}
<Text style={styles.subTitle}>LOOP BUS {selectedLoopBus} TRANSIT DETAILS</Text>
{/* TODO */}
<Text style={styles.txt}>Current bus location: </Text>
<Text style={styles.description}>{loopBusLocation.location} </Text>
<View style={styles.separator}/>
{/* TODO */}
<Text style={styles.txt}>Your location: </Text>
<Text style={styles.description}>{mockUserLocation.location} </Text>
<View style={styles.separator}/>
</View>
<View style={styles.page}>
{
arrivalDetails.map((details, index) => {
return <Text>(Stop {details.stopNumber}) --- ({details.location}) --- ({details.arrival})</Text>
})
}
</View>
<View style={styles.page}>
<Table borderStyle={{ borderWidth: 2,
borderColor: '#c8e1ff' }}>
<Row data={header} />
<Rows data={data} />
</Table>
</View>
</View>
</ScrollView>
</View>
</View>
);
};
export default MapScreen;
I am learning React Native and i am trying to display some dynamic data using for loop and arrow function.
I am facing issues exactly data is not showing on screen but inside log it is printing for loop data.
What is wrong in this code ? As i am only able to see 49 as a value in console.warn.
Code
import React, { Component } from 'react';
import { StyleSheet, View, Text, ScrollView, Platform, Alert } from 'react-native';
export default class MyApp extends Component {
constructor() {
super();
}
dynamicList = () => {
var myloop = [];
for (let i = 0; i < 50; i++) {
console.warn(i)
myloop.push(
<View key={i} style={styles.item}>
<Text style={styles.item_text_style} onPress={() => { Alert.alert('Alert', `Title ${i.toString()}`) }}>Title {i}</Text>
<View style={styles.item_separator} />
</View>
);
}
}
render() {
return (
<ScrollView>
<View >
<Text >Welcome to React Native!</Text>
{this.dynamicList()}
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create(
{
MainContainer:
{
flex: 1,
paddingTop: 25
},
item_text_style:
{
fontSize: 20,
color: '#000',
padding: 10
},
item_separator:
{
height: 1,
width: '100%',
backgroundColor: '#263238',
}
});
wrap your function in componentDidMount() above render, like
componentDidMount(){
this.dynamicList()
}
Also, you are pushing your items in an array, so should use javasSript map method to display the key value pairs from an array
Please update your dynamicList function to following
dynamicList = () => {
var myloop = [];
for (let i = 0; i < 50; i++) {
console.warn(i)
myloop.push(
<View key={i} style={styles.item}>
<Text style={styles.item_text_style} onPress={() => { Alert.alert('Alert', `Title ${i.toString()}`) }}>Title {i}</Text>
<View style={styles.item_separator} />
</View>
);
}
return myloop;
}
I'm using react native expo for the following project basically i want to retrive the selected item form an flat list and display it in a modal
import React,{ Component}from 'react';
import {View,Text,Image,StyleSheet,Modal,Button} from 'react-native';
import { FlatList, TouchableOpacity, ScrollView } from 'react-native-gesture-handler';
import Card from '../shared/card';
import { AppLoading } from 'expo';
import * as Font from 'expo-font';
export default class MealSearch extends Component{
constructor(props){
super(props)
this.state = {
loaded:false,
show:false,
key:''
}}
render(){
const meal= [ {title:'My hero Academia',img:{uri:'https://i.cdn.turner.com/adultswim/big/img/2018/05/10/MHA_Header.png'}, body:'Rating : 4.5/5' , id :'1'},
{title:'Naruto',img:{uri:'https://store-images.s-microsoft.com/image/apps.15041.71343510227343465.377174a9-abc8-4da3-aaa6-8874fdb9e2f5.00fc0a9e-295e-40ca-a391-58ed9f83e9a0?mode=scale&q=90&h=1080&w=1920&background=%23FFFFFF'}, body:'Rating : 5/5' , id :'2'},
{title:'Attack On Titan',img:{uri:'https://www.denofgeek.com/wp-content/uploads/2013/12/attack-on-titan-main.jpg?fit=640%2C380'}, body:'Rating : 4.5/5' , id :'3'},
{title:'Fate: Unlimited Blade Works',img:{uri:'https://derf9v1xhwwx1.cloudfront.net/image/upload/c_fill,q_60,h_750,w_1920/oth/FunimationStoreFront/2066564/Japanese/2066564_Japanese_ShowDetailHeaderDesktop_496a6d81-27db-e911-82a8-dd291e252010.jpg'}, body:'Rating : 4.5/5' , id :'4'}
]
const handlePress = (meal_data) =>{
this.setState({show: true});
this.setState({selectedMeal:meal_data});
console.log(meal_data)
}
return(
<View style={styles.view} >
<FlatList
keyExtractor={item => item.id}
data={meal}
renderItem={({item})=>(
<Card>
<TouchableOpacity onPress={(_item)=>{handlePress(item)}}>
<View style={styles.mealItem}>
<Image style={{width:300,height:150}} resizeMode={'contain'} source={item.img} marginLeft={30}/>
<View style={styles.descrip}>
<Text style={styles.rating}>{item.title}</Text>
<Text style={styles.name}>{item.body}</Text>
</View>
</View>
</TouchableOpacity>
</Card>
)}
/>
<Modal
transparent={true}
visible={this.state.show}
>
<View style={styles.modal}>
<View style={styles.inModal}>
<Button title='End' onPress={()=>{this.setState({show:false})}}/>
</View>
</View>
</Modal>
</View>
);}
}
this is the code I'm currently working on I want the 'meal_data' in 'handlePress' to be displayed inside my modal 'meal_data' is the selected item from the flat list .
<Modal
transparent={true}
visible={this.state.show}
>
<View style={styles.modal}>
<View style={styles.inModal}>
<Button title='End' onPress={()=>{this.setState({show:false})}}/>
</View>
</View>
</Modal>
I want to display it in here above the button
Change these lines of code:
Change: <TouchableOpacity onPress={(_item)=>{handlePress(item)}}>
To
<TouchableOpacity onPress={() => this.handlePress(item)}>
Delete this code inside render():
const handlePress = (meal_data) =>{
this.setState({show: true});
this.setState({selectedMeal:meal_data});
console.log(meal_data)
}
And put this code above render() medthod instead:
handlePress = (meal_data) =>{
this.setState({show: true, selectedMeal: meal_data});
console.log(meal_data)
}
Inside state
this.state = {
loaded:false,
show:false,
key:''
selectedMeal: null // Add this property
}}
After that, you'll be able to access selectedMeal inside your Modal.
Put this code inside the Modal (or somewhere else)
{this.state.selectedMeal && (
<View>
<Text>{this.state.selectedMeal.title}</Text>
</View>
)}
First of declare your handlePress outside of render method. Other thing is that this.setState() is Async so, first set you data then show the modal. Your final code should look like this :
import React, { Component } from 'react';
import { View, Text, Image, StyleSheet, Modal, Button } from 'react-native';
import { FlatList, TouchableOpacity, ScrollView } from 'react-native-gesture-handler';
import Card from '../shared/card';
import { AppLoading } from 'expo';
import * as Font from 'expo-font';
export default class MealSearch extends Component {
constructor(props) {
super(props)
this.state = {
loaded: false,
show: false,
key: ''
}
}
handlePress = (meal_data) => {
this.setState({ selectedMeal: meal_data }, () => {
this.setState({ show: true });
});
console.log(meal_data)
}
render() {
const meal = [
{ title: 'My hero Academia', img: { uri: 'https://i.cdn.turner.com/adultswim/big/img/2018/05/10/MHA_Header.png' }, body: 'Rating : 4.5/5', id: '1' },
{ title: 'Naruto', img: { uri: 'https://store-images.s-microsoft.com/image/apps.15041.71343510227343465.377174a9-abc8-4da3-aaa6-8874fdb9e2f5.00fc0a9e-295e-40ca-a391-58ed9f83e9a0?mode=scale&q=90&h=1080&w=1920&background=%23FFFFFF' }, body: 'Rating : 5/5', id: '2' },
{ title: 'Attack On Titan', img: { uri: 'https://www.denofgeek.com/wp-content/uploads/2013/12/attack-on-titan-main.jpg?fit=640%2C380' }, body: 'Rating : 4.5/5', id: '3' },
{ title: 'Fate: Unlimited Blade Works', img: { uri: 'https://derf9v1xhwwx1.cloudfront.net/image/upload/c_fill,q_60,h_750,w_1920/oth/FunimationStoreFront/2066564/Japanese/2066564_Japanese_ShowDetailHeaderDesktop_496a6d81-27db-e911-82a8-dd291e252010.jpg' }, body: 'Rating : 4.5/5', id: '4' }
]
return (
<View style={styles.view} >
<FlatList
keyExtractor={item => item.id}
data={meal}
renderItem={({ item }) => (
<Card>
<TouchableOpacity onPress={() => { this.handlePress(item) }}>
<View style={styles.mealItem}>
<Image style={{ width: 300, height: 150 }} resizeMode={'contain'} source={item.img} marginLeft={30} />
<View style={styles.descrip}>
<Text style={styles.rating}>{item.title}</Text>
<Text style={styles.name}>{item.body}</Text>
</View>
</View>
</TouchableOpacity>
</Card>
)}
/>
<Modal
transparent={true}
visible={this.state.show}
>
<View style={styles.modal}>
<View style={styles.inModal}>
<Button title='End' onPress={() => { this.setState({ show: false }) }} />
</View>
</View>
</Modal>
</View>
);
}
}
I have a develop website where i can upload a single file and multiple file which give me the download link. I also make and api to fetch my id. (http://lkcfesnotification.000webhostapp.com/api/notifications). From the api i can fetch the image using JSON.parse but when come to my attachment(file) i want to be a hyperlink to download from the browser. from the api i am certain with the path with store in my storage. and the storage also have my images which i can view my images How can i do this?
I use let attachment = member && JSON.parse(member.attachment); then
Linking.openURL('http://lkcfesnotification.000webhostapp.com/storage/' + attachment[0]) } >Click here for to Download file but this show me page not found
import React, { Component } from 'react';
import {
Alert,
Image,
StyleSheet,
ScrollView,
View,
Text,
Linking,
} from 'react-native';
import {
InputWithLabel
} from './UI';
import { FloatingAction } from 'react-native-floating-action';
type Props = {};
export default class ShowScreen extends Component<Props> {
static navigationOptions = ({navigation}) => {
return {
title: navigation.getParam('headerTitle')
};
};
constructor(props) {
super(props)
this.state = {
id: this.props.navigation.getParam('id'),
member: '',
};
this._load = this._load.bind(this);
}
componentDidMount() {
this._load();
}
_load() {
let url = 'http://lkcfesnotification.000webhostapp.com/api/notifications/' + this.state.id;
fetch(url)
.then((response) => {
if(!response.ok) {
Alert.alert('Error', response.status.toString());
throw Error('Error ' + response.status);
}
return response.json()
})
.then((member) => {
this.setState({member});
})
.catch((error) => {
console.error(error);
});
}
render() {
let member = this.state.member;
// let af = 'http://lkcfesnotification.000webhostapp.com/storage/';
console.log(member);
console.log(member.image);
let image = member && JSON.parse(member.image);
let attachment = member && JSON.parse(member.attachment);
return (
<View style={styles.container}>
<ScrollView>
<InputWithLabel style={styles.output}
label={'Title'}
value={member ? member.title : ''}
orientation={'vertical'}
multiline={true}
editable={false}
/>
<InputWithLabel style={styles.output}
label={'Department'}
value={member ? member.department : ''}
orientation={'vertical'}
editable={false}
/>
<InputWithLabel style={styles.output}
label={'Publish'}
value={member ? member.updated_at : ''}
orientation={'vertical'}
editable={false}
/>
<InputWithLabel style={[styles.output, {height: 600, textAlignVertical: 'top'}]}
label={'Description'}
value={member ? member.description : ''}
orientation={'vertical'}
editable={false}
multiline={true}
/>
<Text>
{image && image.length && image.map(image => {
return <Image
source={{uri: 'http://lkcfesnotification.000webhostapp.com/storage/' + image}}
style={{width: 300, height: 300}}
orientation={'vertical'}
/>
})
}
</Text>
<Text style={styles.TextStyle} onPress={ ()=> Linking.openURL('http://lkcfesnotification.000webhostapp.com/storage/' + attachment[0]) } >Click here for to Download file</Text>
<Text style={styles.TextStyle} onPress={ ()=> Linking.openURL(member.link) } >Click here for More Detail</Text>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#fff',
},
output: {
fontSize: 24,
color: '#000099',
marginTop: 10,
marginBottom: 10,
},
TextStyle: {
color: '#E91E63',
textDecorationLine: 'underline',
fontSize: 30
},
});
I want to press the hyperlink i directly connect to default browser of the device and download the file
I want to set different click listeners on different words of . Currently what i have is
<Text>Android iOS React Native<Text>
Now i want to know when user click on Android, iOS and React Native, i have to perform some analytics on that so need click listeners for seperate words.
Does any one have idea about it? I have checked this thread but i din't found it useful for my requirement.
Update
String i have given is just an example string, in real time i will be getting dynamic strings.
This is what i will be getting as dynamic string
{
"str":"Hi i am using React-Native, Earlier i was using Android and so on"
"tagWords":["React-Native","Android"]
}
And in output i want, "Hi i am using React-Native, Earlier i was using Android and so on"
with click event on "React-Native" and "Android". Is is possible?
The post you sent is the simplest way you can achieve the desired behavior. Sinse you need to have different listeners you need to implement different Text components.
Example
export default class App extends Component {
onTextPress(event, text) {
console.log(text);
}
render() {
return (
<View style={styles.container}>
<Text>
<Text onPress={(e) => this.onTextPress(e, 'Android')} style={styles.red}>{'Android '}</Text>
<Text onPress={(e) => this.onTextPress(e, 'iOS')} style={styles.purple}>{'iOS '}</Text>
<Text onPress={(e) => this.onTextPress(e, 'React Native')} style={styles.green}>{'React Native'}</Text>
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
red: {
fontSize: 20,
color: 'red'
},
purple: {
fontSize: 20,
color: 'purple'
},
green: {
fontSize: 20,
color: 'green'
}
});
Update 1 (Dynamic text)
render() {
const fixedString = 'I\'m a fixed string that slipleted';
const arrayOfStrings = ['These', 'are', 'strings', 'from', 'array'];
return (
<View style={styles.container}>
<Text style={styles.textContainer}>
{
fixedString.split(' ').map((str, index) => {
return (
<Text onPress={(e) => this.onTextPress(e, str)}>
{`${str}${index !== (fixedString.split(' ').lenght -1) && ' '}`}
</Text>
)
})
}
</Text>
<Text style={styles.textContainer}>
{
arrayOfStrings.map((str, index) => {
return (
<Text onPress={(e) => this.onTextPress(e, str)}>
{`${str}${index !== (arrayOfStrings.lenght -1) && ' '}`}
</Text>
)
})
}
</Text>
</View>
);
}
Update 2 (for example dynamic data)
removePunctuation = (text) => {
// this is a hack to remove comma from the text
// you may want to handle this different
return text.replace(/[.,\/#!$%\^&\*;:{}=\_`~()]/g,"");
}
render() {
const arrayOfObjects = [{
str: 'Hi i am using React-Native, Earlier i was using Android and so on',
tagWords: ['React-Native', 'Android']
}];
return (
<View style={styles.container}>
<Text style={styles.textContainer}>
{
arrayOfObjects.map((obj) => {
return obj.str.split(' ').map((s, index) => {
if ( obj.tagWords.indexOf(this.removePunctuation(s)) > -1 ) {
return (
<Text onPress={(e) => this.onTextPress(e, s)} style={styles.red}>
{`${s} ${index !== (obj.str.split(' ').lenght - 1) && ' '}`}
</Text>
)
} else return `${s} `;
})
})
}
</Text>
</View>
);
}
all you need to use is TouchableOpacity(for the tap effect and clicks), View for the alignment of texts. and certain styling. I am providing you the code snippet that will work for you , all other syntax will remain same
import {Text, View, TouchableOpacity} from 'react-native'
<View style={{flexDirection:'row'}}>
<TouchableOpacity onPress={{()=>doSomethingAndroid()}}>
<Text>Android</Text>
</TouchableOpacity>
<TouchableOpacity onPress={{()=>doSomethingiOS()}}><Text> iOS</Text>
</TouchableOpacity>
<TouchableOpacityonPress={{()=>doSomethingReactNative()}}><Text> React Native</Text>
</TouchableOpacity>
</View>
i hope this works, comment back if any issue happens
You can wrap each clickable words into 'TouchableOpacity' component, and tract the onPress event as follows
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={() => {
console.log('Android Clicked');
}}>
<Text>Android</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => {
console.log('iOS Clicked');
}}>
<Text>Ios</Text>
</TouchableOpacity>
</View>
Please do adjust the spacing between words.
Edit:
For dynamic string you can proceed as follows
...
handleWordClick(str, handler) {
var words = str.split(' '), // word separator goes here,
comp = [];
words.forEach((s, ind) =>{
comp.push(
<TouchableOpacity key={ind} onPress={() => handler.call(this, s)}>
<Text>{s}</Text>
</TouchableOpacity>
);
})
return comp;
}
render() {
var comp = this.handleWordClick('Android iOS React-Native', (word) => {
//handle analytics here...
console.log(word);
});
return (
<View>
...
<View style={{flexDirection: 'row'}}>
{comp}
</View>
...
</View>
)
}
I am not sure what will be your word separator as the example you have given has 'React Native' as single word. Please pay attention on this part.
Hope this will help you.