I'm a React Native newbie and I'm trying to assess the viability of porting to Android a React Native app that was originally written (not by me...) with iOS in mind.
At the moment I'm not trying to have code that will easily generate both Android and iOS bundles, just having the Android app working properly, with whatever alteration needed. We are using React Native 0.65.3
After setting up the Android environment, I'm compiling it on a MacBook Pro M1 with this command:
npx react-native bundle --entry-file ./index.js --platform android --dev false --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res
The app has several custom buttons, all working properly on iOS. But several are not firing the onPress event on Android...this is the generic MyIconButton code that all the buttons implement:
import React from 'react';
import { View, Pressable, StyleSheet } from 'react-native';
import { MyIcon } from './MyIcon';
import { Theme } from 'styles';
interface MyIconButtonProps {
onPress: () => void;
icon: string;
iconProps?: { [x: string]: any };
disable?: boolean;
testID?: string;
}
export const MyIconButton: React.FC<MyIconButtonProps> = ({
onPress,
icon,
iconProps,
disable,
testID,
}) => {
const buttonStyle = {
...styles.button,
opacity: disable ? 0.5 : 1.5,
};
return (
<View testID={testID}>
<Pressable style={buttonStyle} onPress={onPress} disabled={disable}>
<MyIcon name={icon} fill="currentColor" {...iconProps} />
</Pressable>
</View>
);
};
const { Spacing } = Theme;
const styles = StyleSheet.create({
button: { padding: Spacing.x4 },
});
And here is a working button:
<View style={{ zIndex: 5 }}>
<MyIconButton
onPress={onPress}
icon="Hangup"
iconProps={{ fill: Colors.red, width: 31, height: 31 }}
/>
</View>
The following won't fire the onPress event:
<View style={styles.container}>
<MyIconButton
icon="Microphone"
iconProps={{
fill: this.props.isMicRecording
? '#E51235'
: 'rgba(255, 255, 255, 0.5)',
width: 30,
height: 30,
}}
onPress={() =>
this.props.isMicRecording
? this.stopRecognizing()
: this.startRecognizing()
}
disable={this.props.disabled}
/>
</View>
const styles = StyleSheet.create({
container: {
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
},
});
This one too won't fire the event:
<MyIconButton
onPress={() =>
this.changeVol(volume !== 0 ? 0 : 0.5)
}
icon="Mute"
iconProps={{
fill: volume !== 0 ? Rgba.white.x5 : Colors.blue,
height: 24,
width: 24,
}}
/>
The only notable difference I can spot is the "zIndex: 5" in the View encapsulating the button...but I did try to add the zIndex property with no improvement...
Thank you all for any idea of what is going wrong here!
Related
I am fairly new to react native, but I have some experience. I am creating my own app for both ios and android by following along a tutorial that I had already completed and making my own modifications. As I was in the middle of creating an app, I forgot to add a background image. After struggling with this for several days, I'm desperate, so I decided to ask my question on here.
I am trying to add the background image to my App.js file. The image loads properly, but my page content ( which is inside <LifelineNavigator />) is either hidden or has disappeared for android. And for ios, the content seems to be in a small centered flexbox. Also, I am trying to remove the white background.
Any suggestions would definitely help. Thanks so much! God bless!
Here is my code:
import React, { useState } from "react";
import { StyleSheet, View, ImageBackground } from "react-native";
import * as Font from "expo-font";
import AppLoading from "expo-app-loading";
import { enableScreens } from "react-native-screens";
import LifelineNavigator from "./src/navigation/LifelineNavigator";
enableScreens();
const fetchFonts = () => {
return Font.loadAsync({
"Gotham-Medium": require("./src/assets/fonts/Gotham-Font/Gotham-Medium.otf")
const image = {
uri: "https://i.ibb.co/8z6QbTS/Lifeline-Gradient-Background-24.png",
};
const App = () => {
const [fontLoaded, setFontLoaded] = useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={() => setFontLoaded(true)}
onError={(err) => console.log(err)}
/>
);
}
return (
<View >
<ImageBackground source={image} style={styles.image}>
<View style={ styles.container }>
<LifelineNavigator />
</View>
</ImageBackground>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
// backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
image: {
width: "100%",
height: "100%" ,
}
});
export default App;
IOS Screenshot
Android Screenshot
import React from "react";
import { ImageBackground, StyleSheet, Text, View } from "react-native";
const image = { uri: "https://reactjs.org/logo-og.png" };
const App = () => (
<View style={styles.container}>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>
<Text style={styles.text}>Inside</Text>
</ImageBackground>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
justifyContent: "center"
},
text: {
color: "white",
fontSize: 42,
lineHeight: 84,
fontWeight: "bold",
textAlign: "center",
backgroundColor: "#000000c0"
}
});
export default App;
follow this documentation > https://reactnative.dev/docs/imagebackground
it may solve your problem
Hopefully I can find some help in here.
So for the last day I have been struggling in react native trying to style the shadow on the react navigation header. Problem is that shadow does not display at all on android.
As an example here is the ios display (device: iphone 11 pro max simulator):
And here the android display (device: pocophone f1):
And please find also a code snippet. I tried to style the Stack.screen trough the options prop, and while it works on IOS it doesnt in android.
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import Home from "./components/Home";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import Logo from "./components/Logo";
import Bar from "./components/Bar";
export default function App() {
const Stack = createStackNavigator();
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{}}>
<Stack.Screen
name="Home"
options={{
headerTitle: () => <Logo></Logo>,
title: "home",
headerTitleAlign: "center",
headerStyle: {
backgroundColor: "#48CFAD",
height: 100,
shadowOffset: {
width: 0,
height: 2,
},
shadowColor: "black",
shadowOpacity: 1,
shadowRadius: 3.84,
elevation: 3,
},
}}
component={Home}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
Is anybody else having this issue or asked about it?
Anyway thanks for the help in advance!
Try increasing the elevation a bit,
I set it to 15 and the shadow is showing.
But you might have to use different values to ios and android ans the same value is showing the varying results.
...
<NavigationContainer>
<Stack.Navigator screenOptions={{}}>
<Stack.Screen
name="Home"
options={{
headerTitle: () => <Logo></Logo>,
title: 'home',
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#48CFAD',
height: 100,
shadowOffset: {
width: 0,
height: 3,
},
shadowColor: 'black',
shadowOpacity: 1,
shadowRadius: 3.84,
elevation: 15,
},
}}
component={Home}
/>
</Stack.Navigator>
</NavigationContainer>
...
You can try the working code here: Expo Snack
Snapshot:
Below is the code for my component. Problem is that I cannot add any space in between the buttons, only on Android emulator as you can see in the image. Right now you see marginBottom but if I replace it with padding, it still does not work.
Appreciate if anyone has an idea why is this happening.
import React from 'react';
import { StyleSheet, View} from 'react-native';
import { Button } from 'react-native-elements';
const HomeScreen = ({navigation}) => {
return(
<View style={styles.container}>
<View>
<Button title="Sign In" onPress={() => navigation.navigate('SignIn')} style={{ marginBottom: 20}}/>
<Button title="Sign Up" onPress={() => navigation.navigate('SignUp')} />
</View>
</View>
)
}
HomeScreen.navigationOptions = () => {
return {
header: () => false
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingLeft: 20,
paddingRight: 20,
paddingTop: 40,
backgroundColor: 'white'
}
});
export default HomeScreen;
As I can understand you are using react-native-elements, and style prop is not vailable on that component, I can see on the documentation try using this prop "buttonStyle" to style the button and if not possible wrap the button around a view,
Thanks
My app View style is not working. I`m using react 0.44.0 with 2 emulators, however none of them is working properly. Can someone help me?
Here is my code:
import React, { Component } from 'react';
import {
AppRegistry,
View,
ReactNative,
Text
} from 'react-native';
const Estilos = {
estiloTexto: {
fontSize: 40,
backgroundColor: '#08509B'
},
estiloView: {
backgroundColor: 'skyblue',
height: 300
}
};
//Criar o componente
const App = () => {
const { estiloTexto, estiloView } = Estilos;
return (
<View sytle={{ backgroundColor: 'skyblue', height: 300 }}>
<Text style={estiloTexto}>Frases do Dia</Text>
</View>
);
};
//Renderizar para o dispositivo
AppRegistry.registerComponent('app2', () => App);
The following should be appearing:IOS emulator
But instead I get this: Android
You have a typo in your code
<View sytle={{ backgroundColor: 'skyblue', height: 300 }}>
Change sytle to style
I created a simple activity where in if you press inside the circular area, the text in it should change accordingly. The app runs well but when I press inside the circular area, I get an error saying "undefined is not a function ( evaluating 'this.setState( {pressing: true});' ) ".
Also, the text inside the circular area should be initially set but it is empty.
You can see the activity here. The code is also provided below:
import React, { Component } from "react";
import {
StyleSheet,
View,
AppRegistry,
Text,
TouchableHighlight
} from "react-native";
class dhrumil extends Component {
constructor(props) {
super(props);
this.state = { pressing: false };
}
_inPress() {
this.setState({ pressing: true });
}
_outPress() {
this.setState({ pressing: false });
}
render() {
return (
<View style={styles.mainContainer}>
<TouchableHighlight
onPressIn={this._inPress}
onPressOut={this._outPress}
style={styles.toucher}
>
<View style={styles.smallContainer}>
<Text style={styles.texter}>
{this.state.pressing ? "EEK" : "PUSH ME"}
</Text>
</View>
</TouchableHighlight>
</View>
);
}
}
var styles = StyleSheet.create({
mainContainer: {
flex: 1,
backgroundColor: "white",
justifyContent: "center",
margin: 10,
alignItems: "center"
},
toucher: {
borderRadius: 100
},
smallContainer: {
backgroundColor: "#ff0000",
width: 200,
height: 200,
borderRadius: 100
},
texter: {
color: "white",
fontSize: 10,
fontWeight: "bold"
}
});
AppRegistry.registerComponent("dhrumil", () => dhrumil);
How can I solve this?
The issue is here:
<TouchableHighlight onPressIn={this._inPress}
onPressOut={this._outPress} style={styles.toucher}>
You are setting handlers without fixing the context as the current this.
So when the functions are called setState is not found as this will be different. Use bind.
<TouchableHighlight onPressIn={this._inPress.bind(this)}
onPressOut={this._outPress.bind(this)} style={styles.toucher}>
Or you can also use arrow function:
<TouchableHighlight onPressIn={() => this._inPress()}
onPressOut={() => this._outPress()} style={styles.toucher}>
simply delete node_modules
run npm install
react-native run-android
It's worked for me.