I am planning to build a react native app.The app gets targetted to 3 main things.
1ft => Mobiles(IOS,ANDROID),
2ft => Tablets,
10ft => Android TV.
How can we create files so that if I want to build for 1ft(Mobiles),the app should take only 1ft files like
eg; 1ft_android.js,1ft_ios.js
eg; 2ft_android.js ,2ft_ios.js
and in the same how can I build separately without using Platform.Select Or is there any chance to use flavours and is there any way to make this happen?
Edit 1: I have the folder structure as follows:
I want to find a way to let react know that if display metric matches
1ft, take landing.1ft.android.js. I don't want to compare display
metrics everytime. I'm looking for some configuration so react will
pick the respective file like it picks platform specific files.
For Platform specific UI you can Switch using Platform module.
import {Platform, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
height: Platform.OS === 'ios' ? 200 : 100,
});
But if you want to create responsive UI which will adjust its shape
and size with respect to screen you can use the following methods:
Flex: https://facebook.github.io/react-native/docs/height-and-width#flex-dimensions
Screen ratio:
var deviceWidth: Dimensions.get('window').width;
...
myImage { width: deviceWidth, height: deviceWidth * 0.5 }
And for font-size you can use this function:
export const getAdjustedFontSize = (size) => {
return parseInt(size) * metrics.screenWidth * (1.8 - 0.002 * metrics.screenWidth) / 400;
};
Edit:
You can refer to this link also: https://medium.com/react-native-training/build-responsive-react-native-views-for-any-device-and-support-orientation-change-1c8beba5bc23
Related
I have a very old react native application written on Expo using SDK version 32. Unfortunately, we don't have the time and resource to migrate to the latest version of the SDK (40).
So, right now, we struggle with an issue which reproduces on an Android. One of our screens has a background video (implemented with Expo Video component) and two buttons over it.
import React from 'react';
import { TouchableOpacity, StyleSheet, View, Text, Animated, Dimensions } from 'react-native';
import { AppLoading, Asset, Video } from 'expo';
const defaultVideoSource = require('../content/videos/be.mp4');
export default class HomeScreen extends React.Component {
static navigationOptions = {
header: null,
};
constructor(props) {
super(props);
this.state = {
backgroundOpacity: new Animated.Value(0),
loaded: false,
videoHeight: height,
videoWidth: width,
};
}
async componentWillMount() { }
// this is called from the video::onLoad()
fadeInVideo = () => {
const { backgroundOpacity } = this.state;
setTimeout(() => {
Animated.spring(backgroundOpacity, {
toValue: 1
}).start();
}, 400);
};
render() {
const { backgroundOpacity, loaded, videoHeight, videoWidth } = this.state;
if (!loaded) { return <AppLoading />; }
return (
<View style={styles.container}>
<View style={styles.background}>
<Animated.View
style={[
styles.backgroundViewWrapper,
{ opacity: backgroundOpacity }
]}
>
<Video
isLooping
isMuted={false}
onLoad={() => this.fadeInVideo()}
resizeMode="cover"
shouldPlay
source= { defaultVideoSource }
style={{ height: videoHeight, width: videoWidth }}
/>
</Animated.View>
</View>
<View style={styles.overlay}>
// BUTTONS OVER THE VIDEO
</View>
</View>
);
}
}
const styles = StyleSheet.create({
// ...
});
but for some reason, when I publish it to my Expo account and run it from there the video freezes at a certain moment and stops playing.
The buttons over the video are still active and functional. Like nothing happened but I need to restart the application (via Expo client app on Android) in order to start playing again. I have noticed that If I start it in a debug mode with the command:
expo start
and scan the QR code from the Expo client app there's no freezing of the video. So, for that reason, I would like to create a standalone file (.apk) which I can execute directly on my device without the need of using Expo client app. But, the problem here is that when I try to use the command:
expo build:android
I get an error saying:
Unsupported SDK version: our app builders no longer support SDK
version 32. Please, upgrade to at least SDK 36.
But, as I said, we currently don't have the time to do that because this (SDK update) would affect other components of our app that will need to be rewritten and retested. So, my question finally: Is there any alternative for building an .apk while using SDK 32.0?
It's possible to build apps that use old expo sdks, but I'm not sure if play store will accept those old versions, there was a lot of changes around privacy policy and terms of service plus at certain point google started to require 64 bit binaries(I'm not sure if sdk 32 already had those changes). If that's the case your only option is to upgrade to supported SDK.
If you want to build that app, you can do that with turtle-cli https://www.npmjs.com/package/turtle-cli. This tools executes locally the same code that runs on expo servers, but it's not fully integrated with expo infrastructure, so you will need to provide keystore and all the passwords manually in the cli and either your expo credentials(if you use expo publish) or url to the js bundle (if you self-host). You will need to use old enough version of turtle-cli that still have that sdk, you can consult CHANGELOG here https://github.com/expo/turtle/blob/master/CHANGELOG.md to check that.
I'need to show user feed with items where every item contain a chart.
Now I use react-native-svg-charts:
<LineChart
style={{ height: 150, position: 'relative', left: -20 }}
data={data}
curve={shape.curveNatural}
svg={{ stroke: chartColor1, strokeWidth: 5 }}
contentInset={{ top: 20, bottom: 20 }}
showGrid={false}
numberOfTicks={0}
key={props.id}
>
But when I load more then 50 items performance of the app fall down to 10-15 fps.
I think it because of many SVG's on page. Which solution do you think should I use to avoid this?
I answered a similar question recently here: Real-time data update chart in React Native and will suggest the same here.
I've struggled with performance when plotting in React Native with all of the SVG-based libraries I've tried. I recently decided to try using a couple canvas-based plotting libraries within a WebView and had very good results. I ended up making a simple package: https://www.npmjs.com/package/#dpwiese/react-native-canvas-charts.
Should you not want to use this package and instead do it yourself, it's quite straightforward. While the package source code is probably the best resource I'll summarize the steps below:
Create an HTML file and import it into your component:
const htmlTemplate = require("./index.html");
where the HTML contains the JavaScript for the charting library of choice. The linked package above currently supports Chart.js v3 and uPlot. In the steps below I'll show a Chart.js configuration.
Create a ref, for example let webref.
Create a WebView and onLoadEnd you can inject some JavaScript into the WebView that will configure and create your chart
<WebView
originWhitelist={["*"]}
ref={r => (webref = r)}
source={htmlTemplate}
onLoadEnd={() => { addChart(config) }}
/>
where addChart looks something like:
const addChart = config => {
webref.injectJavaScript(`const el = document.createElement("canvas");
document.body.appendChild(el);
window.canvasLine = new Chart(el.getContext('2d'), ${JSON.stringify(config)});`);
};
and config is a valid Chart.js configuration.
To update the chart data simply inject some JavaScript to update the data. In the case of Chart.js here, that'd look like:
const setData = dataSets => {
if (dataSets) {
dataSets.forEach((_, i) => {
webref.injectJavaScript(`window.canvasLine.config.data.datasets[${i}].data = ${JSON.stringify(dataSets[i])};
window.canvasLine.update();`);
});
}
};
where dataSets are valid Chart.js data sets.
That's it! I've only played around with these two plotting libraries via the https://www.npmjs.com/package/#dpwiese/react-native-canvas-charts package, but so far performance has been really good, even with the JSON stringification of all the passed chart data. I haven't quantified it thoroughly, but both libraries are orders of magnitude more performant than any of the SVG-based ones I've tried.
I am wanting to develop an app where a user can select different gamepacks to install on their android or ios device. A gamepack will consist of:
one or more JSON files
images
sounds
Right now I'm not really concerned if these are transferred individually or in a zip file (though a zip file would certainly be preferred). Of course the device will need to be connected to the Internet to get the current list of gamepacks and to download the ones that the user chooses. Once the gamepacks are downloaded to the phone the user will not need an Internet connection to play the game as they will have all the files.
How do I go about implementing this in my project?
How do I download the files? Would I use the react-native-fetch-blob library and save it in a specific location? This library refers to saving it as "cache" rather than permanently, so I am not sure if this is the correct solution. The specific section I am looking at on the library page is "Use Specific File Path". But because it is cache, should I be looking for something else that is more of a longer term storage? It does say on the page that files will not be deleted so I am a bit confused as to what the difference between permanent storage and cache is in this case.
Once the files are downloaded would I then be able to open images and display them, open sound files and play them, and open the json files and process them?
Check out React Native FS, specifically the documentation on downloadFile:
https://github.com/johanneslumpe/react-native-fs#downloadfileoptions-downloadfileoptions--jobid-number-promise-promisedownloadresult-
Here's a working example:
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View,
Image,
} from 'react-native';
import RNFS from 'react-native-fs';
export default class downloadFile extends Component {
constructor() {
super()
this.state = {
isDone: false,
};
this.onDownloadImagePress = this.onDownloadImagePress.bind(this);
}
onDownloadImagePress() {
RNFS.downloadFile({
fromUrl: 'https://facebook.github.io/react-native/img/header_logo.png',
toFile: `${RNFS.DocumentDirectoryPath}/react-native.png`,
}).promise.then((r) => {
this.setState({ isDone: true })
});
}
render() {
const preview = this.state.isDone ? (<View>
<Image style={{
width: 100,
height: 100,
backgroundColor: 'black',
}}
source={{
uri: `file://${RNFS.DocumentDirectoryPath}/react-native.png`,
scale: 1
}}
/>
<Text>{`file://${RNFS.DocumentDirectoryPath}/react-native.png`}</Text>
</View>
) : null;
return (
<View>
<Text onPress={this.onDownloadImagePress}>Download Image</Text>
{preview}
</View>
);
}
}
AppRegistry.registerComponent('downloadFile', () => downloadFile);
It's important to know that the height and width must be set on the Image
I'm just trying to load an image as a static resource. Here is an example that gives me a blank white screen.
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
Image,
View
} = React;
var impowerz = React.createClass({
displayName : "Login",
render: function() {
return (
<View style={styles.container}>
<Image source={require('image!bg-splash')} style={styles.bg} />
</View>
);
}
});
var styles = StyleSheet.create({
bg : {
height: 667,
width: 375
},
container: {
flex: 1,
},
});
AppRegistry.registerComponent('impowerz', () => impowerz);
I checked in Chrome Debugger and this is what I got
[![Chrome Debugger sees my static resource][1]][1]
Edit I wrapped the image tag in a view and added a flex: 1 styles for the container
Update I tried to console.log() the assetsRoot property in react-native/packager/packager.js and it came back as /impowerz/assets/ which is where my image lives. I made a #2x and #3x as suggested [in this answer][2]
I tried using .jpg instead of .png images and tried replacing require('image!bg_splash') with {uri: 'assets/image/bg_splash.jpg'} (with and without the ext).
How did you add "bg-splash" to your android app? It should go under android/app/src/main/res/drawable (or drawable-hdpi, -xhdp etc if you have different version per DPI). Also take into account that android only accept resources names that contain lowercase letters and underscores, so your image name doesn't match that requirement as it contains dash sign.
in react-native v.0.14+
// same syntax for IOS and Android
require('./my-icon.png')
Full Image docs here
As of 0.14 release, React Native provides a unified way of managing images in your iOS and Android apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
<Image source={require('./my-icon.png')} />
//relative path
.
├── button.js
└── img
├── check#2x.png
└── check#3x.png
I couldn't get my images to show up either.
When I went to <yourapp>/android/app/src/main/res, there were only mipmap-<qualifier> folders. I first put the images in those folders. Didn't work. My reading comprehension skills obviously need upgrading, because in the instructions, it clearly says "drawable." Then, I made the mistake of thinking that these "mipmap" folders needed to be changed to "drawable" folders (in the place of "mipmap"). So if anyone did that, backtrack, and instead, add the drawable-<qualifier> folders in addition to the "mipmap" ones. And then make sure to recompile the app.
To get the image to show on the screen, put the image in a view:
return (
<View
style={styles.container}>
<Image source={require('image!bg-splash')} style={styles.bg} />
</View>
);
And add these styles to the view
var styles = StyleSheet.create({
container: {
flex: 1,
},
I am developing an app for android with QT/QML. To switch between screens I use this pageloader:
Rectangle {
id: mainApp
visible: true
width: 768
height: 1030
signal handlerLoader(string name, int index)
Loader {
id:pageLoader
source:"mainMenu.qml"
}
Connections {
target:pageLoader.item
onHandlerLoader:{pageLoader.source=name;
if(index===2)
window.source="NewWindow.qml";
}
}}
In a menu I have a button somewhere where another screen is loaded:
Button {
id: continueButton
width: 600
height: 150
text: "Continue with last template"
onClicked: handlerLoader("Template_water.qml",0)
}
This works, because Template_water.qml is in the qml.qrc file. But now I want to load in another file which is on the external storage on my android device: "/storage/emulated/0/Download/Template_water.qml". But it is not described in the qml.qrc file so it doesn't load. How can I solve this? (I want it to be able to add a qml file after deployment on the device.)
Try to provide scheme for your url like:
file:///storage/emulated/0/Download/Template_water.qml