I have a react native code, using expo, with a graph with text. In Apple, this application is showing it twice. In Android, once.
Here is the code:
import { ScrollView, StyleSheet, Text, View, Alert, Dimensions } from 'react-native';
...
// Charts
import * as scale from 'd3-scale'
import { ProgressCircle, LineChart, XAxis, Grid } from 'react-native-svg-charts';
.... <Other Code> ...
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ padding: 10 }}>
<ProgressCircle
style={{ height: 150, width: 150 }}
startAngle={-Math.PI * 0.5}
endAngle={Math.PI * 0.5}
progress={this.state.perFirstTier}
progressColor={constants.BGC_GREEN}
strokeWidth={10}>
{* THIS IS WHAT IS DOUBLED*}
<Text key ='percentage' style={{
position: "absolute",
marginLeft: 65, marginTop: 50
}}>{(this.state.perFirstTier * 100).toFixed(0)}%</Text>
</ProgressCircle>
<View style={{ marginTop: -40, flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={styles.description}>{i18n.t('activityDashboard.firstGoalDesc')}</Text>
{/* Show colored badge if 100%*/}
{this.state.perSecondTier == 1
? <Image style={styles.medalImage} source={require('../../utils/images/silver_medal.png')}></Image>
: <Image style={styles.medalImage} source={require('../../utils/images/grey_medal.png')}></Image>
}
</View>
</View>
Here is an image comparison of Apple versus Android:
Why is this happening, and how can I make it only show once?
Because progress is already declared in the ProgressCircle component, and it's rendered inside it. Just remove the Text component from the ProgressCircle. I guess it has overflow hidden on Android so it's not displayed there.
if all else fails, try adding a rendering condition for iOS platform.
<ProgressCircle
style={{ height: 150, width: 150 }}
startAngle={-Math.PI * 0.5}
endAngle={Math.PI * 0.5}
progress={this.state.perFirstTier}
progressColor={constants.BGC_GREEN}
strokeWidth={10}
>
{/* THIS IS WHAT IS DOUBLED */}
{Platform.OS === 'ios'
? <View />
: (
<View>
<Text
key ='percentage'
style={{
position: "absolute",
marginLeft: 65,
marginTop: 50
}}
>
{(this.state.perFirstTier * 100).toFixed(0)}%
</Text>
</View>
)
}
</ProgressCircle>
I had a similar issue trying to render YAxis as < Text > on iOS14. I used < Text > because had a hard time using YAxis for putting the label at the top of the chart bar.
My specs:
{
"expo": "~39.0.2",
"react-native-svg-charts": "^5.4.0",
"react-native-svg": "12.1.0"
}
Code:
const Values = ({ x, y, data }) => {
return (
data.map((value, index) => {
return (
<Text
key={index}
style={{
color: '#6e6969',
fontSize: 10,
position: 'absolute',
left: x(index) + 1,
top: y(value) - 15
}}
>
{value}
</Text>
)
})
)}
<BarChart
style={styles.chart}
data={data.plot}
spacing={0.2}
svg={{ fill: 'rgba(134, 65, 244, 0.8)' }}
contentInset={{ top: 20, bottom: 20, left: 0, right: 0 }}
>
<Values />
</BarChart>
<XAxis
style={{ marginHorizontal: -10 }}
data={data.plot}
formatLabel={(value, index) => data.labels[index]}
contentInset={{ left: 30, right: 30 }}
svg={{ fontSize: 10, fill: colors.medium }}
/>
Result
What I needed to do was wrapper the < Text > into a < View > and the issue was solved:
Changed code:
const Values = ({ x, y, data }) => {
return (
data.map((value, index) => {
return (
<View key={index}>
<Text
style={{
color: '#6e6969',
fontSize: 10,
position: 'absolute',
left: x(index) + 1,
top: y(value) - 15
}}
>
{value}
</Text>
</View>
)
})
)}
Result
Both codes worked fine on Android, though.
Related
Everyone.
I need your help.
I made one app with react native expo cli.
But one issue occurred.
I used the ScrollView for horizontal pagination.
*<SafeAreaView>
<ScrollView
snapToInterval={wp("100%")}
horizontal
pagingEnabled
nestedScrollEnabled
decelerationRate="fast"
>
{[...Array(this.state.pageCount)].map((num, index) => {
return (
<View
key={"view" + index}
style={{
width: wp("100%"),
height: "100%",
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
alignContent: "center",
justifyContent: "center",
}}
>
{this.state.categories
.slice(index * 6, index * 6 + 6)
.map((item, key) => (
<TouchableOpacity
key={"touch" + key}
style={styles.itemStyle}
onPress={() => this.openModal(item)}
onLongPress={() => this.selectItem(item)}
>
<Image
source={{ uri: item.Foto }}
style={{ height: 120, width: "90%" }}
resizeMode="cover"
/>
<Text style={{ fontSize: 18 }}>{item.Precio}</Text>
<Text style={{ fontSize: 12 }}>{item.Gemas}</Text>
</TouchableOpacity>
))}
</View>
);
})}
</ScrollView>
</SafeAreaView>*
But the pagination only works on Android Phone and doesn't work on iPhone.
Please help me.
Your <ScrollView> should have style flex: 1, to allow the view fit the screen size.
The width of the Views inside the Scroll should have a numerical value. A width of 100% inside a scrollview is undefined. Your approach should be related to the dimension of the screen.
// import dimensions lib
import Dimensions from 'react-native';
...
...
...
// capture the width of the screen
const screenWidth = Dimensions.get('screen').width;
...
...
...
{[...Array(this.state.pageCount)].map((num, index) => {
return (
<View
key={"view" + index}
style={{
width: screenWidth,
height: "100%",
display: "flex",
flexDirection: "row",
flexWrap: "wrap",
alignContent: "center",
justifyContent: "center",
}}
>
{this.state.categories
.slice(index * 6, index * 6 + 6)
.map((item, key) => (
<TouchableOpacity
key={"touch" + key}
style={styles.itemStyle}
onPress={() => this.openModal(item)}
onLongPress={() => this.selectItem(item)}
>
<Image
source={{ uri: item.Foto }}
style={{ height: 120, width: "90%" }}
resizeMode="cover"
/>
<Text style={{ fontSize: 18 }}>{item.Precio}</Text>
<Text style={{ fontSize: 12 }}>{item.Gemas}</Text>
</TouchableOpacity>
))}
</View>
);
})}
I'M creating ui in expo application using react-native-paper. The UI is getting different for android and iOS platform for Account Screen. However, i tried same code in Snack and it show correct ui in web.
This is ios UI
This is android UI
In Android, some part of ui is hidden.
Snack Code Link
I need look like ios device screenshot have in android.
Here is demo: https://snack.expo.io/#nomi9995/45f132
You should make parent view inside ScrollView and wrap ImageBackground and View
inside this parent view
import React, { useState, useContext } from "react";
import {
SafeAreaView,
View,
ScrollView,
Dimensions,
ImageBackground,
Alert,
} from "react-native";
import { FontAwesome, MaterialIcons } from "#expo/vector-icons";
import { TextInput, Button } from "react-native-paper";
import Constants from "expo-constants";
export default function App() {
const SCREEN_HEIGHT = Dimensions.get("window").height;
const SCREEN_WIDTH = Dimensions.get("window").width;
return (
<SafeAreaView style={{ flex: 1 }}>
<ScrollView style={{ flex: 1, height: SCREEN_HEIGHT }}>
<View style={{ flex: 1, height: SCREEN_HEIGHT }}>
<ImageBackground
source={{
uri:
"https://firebasestorage.googleapis.com/v0/b/ielts-preps.appspot.com/o/1592920135765?alt=media&token=ec911583-06f9-4315-b66c-cf47de120e85",
}}
style={{ width: SCREEN_WIDTH, height: SCREEN_HEIGHT * 0.4 }}
>
<View
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
alignItems: "flex-start",
margin: 20,
}}
>
<FontAwesome name="close" size={30} color="#fff" />
<MaterialIcons name="edit" size={30} color="#fff" />
</View>
</ImageBackground>
<View
style={{
height: SCREEN_HEIGHT * 2,
width: SCREEN_WIDTH * 0.9,
backgroundColor: "red",
position: "absolute",
left: (SCREEN_WIDTH - SCREEN_WIDTH * 0.9) / 2,
top: SCREEN_HEIGHT * 0.3,
zIndex: 1,
elevation: 10,
}}
>
<TextInput
label="First Name"
value=""
mode="flat"
onChangeText={(text) => {}}
style={{ margin: 20, backgroundColor: "#fff" }}
/>
<TextInput
label="Last Name"
value=""
mode="flat"
onChangeText={(text) => {}}
style={{ margin: 20, backgroundColor: "#fff" }}
/>
<Button
style={{
marginHorizontal: 50,
marginVertical: 20,
backgroundColor: "#0af",
padding: 10,
}}
mode="contained"
onPress={() => {}}
>
Update
</Button>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
Actual Behaviour :
I am supposed to implement signature pad in landscape-right mode along with a timestamp of signature drawn. Then take a screenshot of the view, and save it in document directory (iOS) or external directory (Android) in portrait mode by rotating it. I was successful in implementing signature screen in landscape-right mode using transform: [{rotate: '90deg"}] css property, and react-native-signature-capture, save the captured screenshot of signature along with the timestamp of signature drawn in local directory using react-native-view-shot and convert it into base64 format using react-native-fs.
But the saved screenshot is not in portrait mode and I'm trying to rotate the image while saving it in document directory (iOS) or external directory (Android) without using any modules. I also tried rotating the image while saving it using canvas context API but could not find way to access canvas in react-native to rotate image while saving it as canvas is HTML DOM related.
Expected Behaviour :
I'm supposed to save the signature drawn along with timestamp in document directory (iOS) or external directory (Android) in portrait mode as shown in below screenshot.
Additional Resources :
Code :
render() {
return (
<View
style={{
flex: 1,
flexDirection: 'row',
overflow: "hidden",
}}>
<StatusBar hidden={true} />
<View
style={{
flex: 0.8,
flexDirection: 'row-reverse',
marginVertical: width / 18,
overflow: "hidden",
}}>
<ViewShot
ref="viewShot"
style={[styles.viewShot, { transform: [{ rotate: this.state.bool && '90deg' }] }]}>
{/* options={{ width: height, height: width }}> */}
<SignatureCapture
style={styles.signature}
ref={sign => (this.signComponent = sign)}
onSaveEvent={this._onSaveEvent}
onDragEvent={this._onDragEvent}
saveImageFileInExtStorage={true}
showNativeButtons={false}
showTitleLabel={false}
showBorder={false}
viewMode={'portrait'}
square={true}
backgroundColor={"white"}
maxSize={800}
rotateClockwise={!!true}
/>
<View
ref="timeRef"
style={{
width: width / 10,
height: width / 3,
justifyContent: 'flex-end',
flexDirection: 'row-reverse',
}}>
<View
style={{
width: width / 1.8,
height: width / 1.8,
transform: [{ rotate: '-90deg' }],
overflow: "hidden",
paddingLeft: width / 18,
paddingTop: width / 25
}}>
<Text style={styles.time}>{this.state.data}</Text>
</View>
</View>
</ViewShot>
<Image
ref="imageRef"
source={{ uri: this.state.imageUri }}
style={{ transform: [{ rotate: '90deg' }] }}
/>
</View>
<View
style={{
flex: 0.2,
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
overflow: "hidden",
backgroundColor: Colors.white,
}}>
<View
style={{
backgroundColor: Colors.darkGreen,
width: width / 2,
justifyContent: 'center',
alignItems: 'center',
paddingRight: width / 25,
paddingVertical: width / 37.5,
transform: [{ rotate: '-90deg' }],
overflow: "hidden",
}}>
<TouchableOpacity
hitSlop={{ top: 30, left: 50, right: 50, bottom: 30 }}
onPress={() => {
this.saveSign();
}}>
<Text style={{ fontSize: width / 18, color: Colors.white }}>Submit </Text>
</TouchableOpacity>
</View>
<View
style={{
backgroundColor: '#5476ab',
width: width / 2,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: width / 37.5,
transform: [{ rotate: '-90deg' }],
overflow: "hidden",
}}>
<TouchableOpacity
hitSlop={{ top: 30, left: 50, right: 50, bottom: 30 }}
onPress={() => {
this.resetSign();
}}>
<Text style={{ fontSize: width / 18, color: Colors.white }}>Clear</Text>
</TouchableOpacity>
</View>
<View
style={{
backgroundColor: '#73c5de',
width: width / 2,
justifyContent: 'center',
alignItems: 'center',
paddingVertical: 10,
transform: [{ rotate: '-90deg' }],
}}>
<TouchableOpacity
hitSlop={{ top: 30, left: 50, right: 50, bottom: 30 }}
onPress={() => {
this.onCancel();
}}>
<Text style={{ fontSize: width / 18, color: Colors.white }}>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
_onSaveEvent(result) {
this.setState({ signature: result.pathName,
markResult: result.encoded });
}
_onDragEvent() {
this.setState({ dragged: true });
}
saveSign() {
if (this.state.dragged === true) {
this.setState({ bool: true });
this.refs.viewShot.capture().then(uri => {
this.setState({ imageUri: uri });
console.log("uri123", uri);
RNFS.readFile(this.state.imageUri,
'base64').then(image => {
console.log("image123", image);
this.setState({ sign: image }, () => {
this.ChangeOrientation();
});
});
});
} else {
Alert.alert('NALG', 'Please sign the signature
pad to submit');
}
ChangeOrientation() {
this.props.getSignature(this.state.sign);
this.props.setModalVisible(!this.props.modalVisible);
}
Screenshot of Actual Behaviour :
Screenshot of Expected Behaviour :
Environment:
react-native : 0.61.1
react-native-view-shot : ^3.0.2
react-native-signature-capture : ^0.4.10
react-native-fs : ^2.16.2
const showImagePicker = () => {
const options = {
title: i18n.t('issueReport.form.photoSelection'),
storageOptions: {
skipBackup: true,
path: 'images',
},
allowsEditing: true,
};
ImagePicker.showImagePicker(options, response => {
const { originalRotation } = response
console.log('Response = ', response);
console.log('originalRotation = ', originalRotation);
if (originalRotation === 90) {
setOriginalRotation(90)
} else if (originalRotation === 270) {
setOriginalRotation(-90)
}
setSelectedImageFile(response);
if (response && response.height === 3000) {
setLandscape(true)
}
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
} else {
const source = { uri: response.uri };
console.log('Image Path', source);
// You can also display the image using data:
// const source = { uri: 'data:image/jpeg;base64,' + response.data };
setSelectedImage(source);
setPhotoSelectVisible(true);
}
});
};
For more detail
https://github.com/react-native-image-picker/react-native-image-picker/issues/655
I've created a custom dropdown using TouchOpacity component of react native as follows.
<View style={dropDownStyle}>
<TouchableOpacity onPress={() => _switchTimeSpan('Day')}>
<Text style={dropDownItemStyle}>Day</Text>
</TouchableOpacity>
<TouchableOpacity onPress={() => _switchTimeSpan('Week')}>
<Text style={dropDownItemStyle}>Week</Text>
</TouchableOpacity>
</View>
The style is as follows.
dropDownStyle: {
position: 'absolute',
marginTop: 20,
width: 80,
},
dropDownItemStyle: {
marginTop: 5,
flex: 1,
textAlign: 'right',
},
When pressed the TouchOpacity component doesn't trigger the onpress function. This issue only exists in android and not IOS.
Edit 1 : There is a areachart created use react-native-svg-charts which is being overlapped by the mentioned dropdown. However upon inspecting if the reason for the onPress not working could be because of zIndex issues i noticed that the mentioned dropdown is the top most component.
The code for the chart is the following.
I am using react-native-svg-charts
<View style={containerStyle}>
<YAxis
data={data}
style={yAxisStyle}
formatLabel={value => yAxisFormat(value)}
contentInset={verticalContentInset}
numberOfTicks={5}
svg={axesSvg}
/>
<View style={chartWrapperStyle}>
<AreaChart
style={chartStyle}
data={data}
contentInset={verticalContentInset}
curve={shape.curveCatmullRom}
svg={{ fill: '#FF4D4D' }}
animate
/>
<View style={xAxisStyle}>
{
timeSpan !== 'Month' && (
<XAxis
data={data}
// formatLabel={(value, index) => months[value]}
formatLabel={(value, index) => xAxisPoints[index]}
contentInset={{ left: 10, right: 10 }}
// numberOfTicks={5}
svg={axesSvg}
/>
)
}
</View>
</View>
</View>
The style for the chart is as follows.
containerStyle: {
height: 200,
paddingLeft: 20,
paddingRight: 20,
flexDirection: 'row',
},
yAxisStyle: {
// marginBottom: 20,
position: 'absolute',
height: 180,
left: 20,
zIndex: 2,
},
chartStyle: {
flex: 1,
},
chartWrapperStyle: {
flex: 1,
},
xAxisStyle: {
marginHorizontal: -5,
height: 20,
},
When I'm testing this as isolated and only component on screen everything seems to work properly on Android (Samsung Galaxy Tab 2). Try to isolate this component and see if it will work for you on Android, maybe other components affect it. Also you could try to check if container component (with dropDownStyle) has some height or try to set 100%.
As I want to overlap this icon with two other Views, as shown in the image. this code is working on IOS platform but not on android. please suggest if there is any solution for Android.
var tabs = ['Activity', 'Files', 'People'];
this.state = {
tabs
};
return (
<Container style={{backgroundColor: '#F5F5F5'}}>
<View style={styles.topStrip}>
{
this.state.tabs.map((tab, index) => (
<View key={index} >
<TouchableOpacity>
<Text style={styles.streamName}>{tab}</Text>
</TouchableOpacity>
</View>
))
}
<View style={{position: 'absolute', backgroundColor: 'transparent', alignItems: 'center', justifyContent: 'center', zIndex: 5, elevation: 24, marginTop: 15, marginLeft: 300}}>
<EIcon size={40} color='#2196f3' name={'circle-with-plus'} />
</View>
</View>
<View style={{zIndex: -1}}></View>
</Container>
);
}
}
const styles = StyleSheet.create({
topStrip: {
alignItems: 'center',
},
streamName: {
marginTop: 7,
marginBottom: 6,
flexDirection: 'row',
alignSelf: 'center'
}
}
});
<View
style={{
paddingLeft: ITEM_HEIGHT * 3,
flex: 1,
position: "absolute",
top: 0,
right: 0,
bottom: 0,
left: 0,
zIndex: -1
}}
>
<Image
style={styles.centerCircle}
resizeMode="contain"
source={Images.ballSmall}
/>
</View>
In android, to use zIndex you need css with position-properties with top,left,right,bottom css
Tested On: Zenfone 3, Android 7, React Native 0.55.4
This issue is not caused by zIndex (although it does cause problem on Android).
Your icon is put inside the upper container view. React Native on Android does not support overflow: visible. That's why you see your icon being clipped outside the container.
You may put the icon on the "page" component level to solve this issue.
You may also refer to https://stackoverflow.com/a/50991892/6025730.