I am new in react-native. I have problems wiht implementing orientation for ios. I am trying to use react native orientation. I have read the documentation but can't do it anyway. Please don't answer with methods like "lockToPortrait(),lockToLandscape() or getOrientation(function(err, orientation)", I have already read this. Can anyone just respond with a piece of working code, it will be enough for me.
Thanks
var Orientation = require('react-native-orientation');
class YourApp extends Component {
componentDidMount() {
Orientation.lockToPortrait();
}
render() {
<MainComponent />
}
}
AppRegistry.registerComponent('YourApp', () => YourApp);
Worked for me just fine.
import React, {PureComponent} from 'react';
import {
View,
Text,
Dimensions
} from 'react-native';
import Orientation from 'react-native-orientation';
const {
width: deviceScreenWidth,
height: deviceScreenHeight
} = Dimensions.get('window');
let aspectRatio = deviceScreenWidth / deviceScreenHeight;
export default class Home extends PureComponent {
constructor(props) {
super(props);
}
render() {
return (
<View style={style.homeMainContainer}>
<Text>Atif dont let this screen rotate</Text>
</View>
)
}// end of render
componentDidMount() {
if (deviceScreenWidth > deviceScreenHeight) {
Orientation.lockToLandscape();
} else {
Orientation.lockToPortrait();
}
// this unlocks any previous locks to all Orientations
// Orientation.unlockAllOrientations();
Orientation.addOrientationListener(this._orientationDidChange);
}
_orientationDidChange = (orientation) => {
if (orientation === 'LANDSCAPE') {
// do something with landscape layout
} else {
// do something with portrait layout
}
}
};
This example is to figure out the the device is the tablet or mobile, if it is tablet it will lock the screen as landscape and if it is mobile then it will lock the screen as portrait.
This is the library as package first you have to install the package link : https://www.npmjs.com/package/react-native-orientation
Adding this since none of the above mentioned that this can be done in react native, without importing a library with Dimensions.addEventListener.
Here is an example of a class that can be initiated to remove and add the StatusBar in your app.
import { Dimensions } from "react-native";
class OrientationChanger {
constructor() {
this.update();
Dimensions.addEventListener("change", () => {
this.updateOrientation();
});
}
update() {
if (Dimensions.get("window").width < Dimensions.get("window").height) {
StatusBar.setHidden(false); // "portrait"
} else {
StatusBar.setHidden(true); // "landscape"
}
}
}
export default OrientationChanger;
Related
[React Native]
Can anyone help to elaborate what should that kind of menu called? When onclick, it slided up. Please also introduce what are other menu's available in react native? (Must work for both android and iOS)
Example
It is share dialog and you can easily implement it in React Native
Try this code
import React, {Component} from 'react';
import {Share, Button} from 'react-native';
class ShareExample extends Component {
onShare = async () => {
try {
const result = await Share.share({
message:
'React Native | A framework for building native apps using React',
});
if (result.action === Share.sharedAction) {
if (result.activityType) {
// shared with activity type of result.activityType
} else {
// shared
}
} else if (result.action === Share.dismissedAction) {
// dismissed
}
} catch (error) {
alert(error.message);
}
};
render() {
return <Button onPress={this.onShare} title="Share" />;
}
}
React Native Modal
1-
react-native-modal
2-
react-native-modalbox
I have developed an store app, my boss wants a feature that from wordpress panel select predefined layout to change the whole design and choose which category to be first or .... .
I have created all designs and components that needed, but I do not know how to change app layout that I recieved from api, is there any code or help for that. This change is not about color , its about changing whole home page app layout
Sorry for my english
Here is a simple example that you could implement.
You'll need to create custom complete components for each layout for the homepage.
Then you'll need to call the Wordpress API to get the layout name that needs to be displayed.
import React, { PureComponent } from 'react';
import { AppRegistry } from 'react-native';
import Layout1 from './components/Home/Layout1';
import Layout2 from './components/Home/Layout2';
import Layout3 from './components/Home/Layout3';
import Layout4 from './components/Home/Layout4';
import Loading from './components/Loading';
class HomePage extends PureComponent {
constructor(props) {
super(props);
this.state = {
layout: null
};
}
async componentDidMount() {
const response = await fetch('https://example.com/wp-json/whatever-api-endpoint')
.then(r => r.json());
this.setState({
layout: response
});
}
getContentElement = () => {
switch (this.state.layout) {
case 'layout_1': return <Layout1 />;
case 'layout_2': return <Layout2 />;
case 'layout_3': return <Layout3 />;
case 'layout_4': return <Layout4 />;
default: return <Loading />
}
};
render() {
const contentElement = this.getContentElement();
return (
<View>
{contentElement}
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => HomePage);
I installed the react-navigation package in react-native
I have implemented tab navigation and one of them is implemented in webview format.
My problem is that if I press the back physical button on Android, I go from the app itself to the previous tab, not back from the webview.
I've already applied the back button for the webview on the internet, but I have not done that.
I tried to display the onNavigationStateChange log when debugging, but it was not updated when url was moved after it was loaded at first startup. Here is the code I implemented:
import React from "react";
import {BackHandler} from "react-native";
import {WebView} from "react-native-webview";
class SermonScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = {
header: null
};
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
_onNavigationStateChange(navState) {
console.log(navState);
this.setState({
canGoBack: navState.canGoBack
});
}
handleBackButton = () => {
console.log(this.state);
if (this.state.canGoBack === true) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<WebView
source={{uri: 'https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos' }}
ref={(webView) => this.webView = webView}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
/>
);
}
}
export default SermonScreen;
Following the official webview documnentation you could try to do this: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes
In general you were almost there, however the way the YT navigation works made it impossible to be caught via the onNavigationStateChange, that's why we inject a JS code that intercepts these hash changes and posts a message to the parent component, we then catch it inside the onMessage handler and set the state variable properly. Copying the injectedJavaScript and onMessage properties to your example should solve your problem.
I prepared a component for you that seems to do what is needed:
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React, { Fragment } from "react";
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
BackHandler,
StatusBar
} from "react-native";
import { WebView } from "react-native-webview";
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions
} from "react-native/Libraries/NewAppScreen";
class App extends React.Component {
constructor(props) {
super(props);
this.startingUrl =
"https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos";
this.handleBackButton = this.handleBackButton.bind(this);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
console.log(this.state);
const { canGoBack } = this.state;
if (canGoBack) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<Fragment>
<WebView
source={{ uri: this.startingUrl }}
style={{ marginTop: 20 }}
ref={webView => (this.webView = webView)}
injectedJavaScript={`
(function() {
function wrap(fn) {
return function wrapper() {
var res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
window.addEventListener('popstate', function() {
window.ReactNativeWebView.postMessage('navigationStateChange');
});
})();
true;
`}
onMessage={({ nativeEvent: state }) => {
if (state.data === "navigationStateChange") {
// Navigation state updated, can check state.canGoBack, etc.
this.setState({
canGoBack: state.canGoBack
});
}
}}
/>
</Fragment>
);
}
}
export default App;
The response above was perfect. I set the state true for canGoBack though; I was getting a null error, so:
constructor(props) {
super(props);
this.startingUrl = "https://app.vethorcardpag.com.br/GIF/login/0/";
this.state = {
canGoBack : true
}
this.handleBackButton = this.handleBackButton.bind(this);
}
Here is a simple solution using the magic of React's State.
Hope this helps.
import React, { useRef, useState } from 'react'
export default function Component () {
// This is used to save the reference of your webview, so you can control it
const webViewRef = useRef(null);
// This state saves whether your WebView can go back
const [webViewcanGoBack, setWebViewcanGoBack] = useState(false);
const goBack = () => {
// Getting the webview reference
const webView = webViewRef.current
if (webViewcanGoBack)
// Do stuff here if your webview can go back
else
// Do stuff here if your webview can't go back
}
return (
<WebView
source={{ uri: `Your URL` }}
ref={webViewRef}
javaScriptEnabled={true}
onLoadProgress={({ nativeEvent }) => {
// This function is called everytime your web view loads a page
// and here we change the state of can go back
setWebViewcanGoBack(nativeEvent.canGoBack)
}}
/>
)
}
Original answer
https://stackoverflow.com/a/74500469/7823800
I experience the lag during transition animation when Navigator goes to below scene ShiftEdit. Animation starts immediately but it stops for a millisecond. InteractionManager is used to postpone rendering of four picker components. Every picker component has list of items that is built from an array. There is lots of items. Is it possible that this is calculated even when picker component isn't rendered yet in ShiftEdit and this is the reason of the lag? Could you help me please?
'use strict'
import React, {View, Text, StyleSheet, InteractionManager, TouchableOpacity} from 'react-native';
import { connect } from 'react-redux';
import Spinner from 'react-native-spinkit';
import StyleCommon from '../styles';
import TimePicker from '../components/time-picker';
import ColorPicker from '../components/color-picker';
import LabelPicker from '../components/label-picker';
class ShiftEdit extends React.Component {
constructor(props) {
super(props);
this.state = {
isReady: false,
shiftId: '',
startHour: '',
endHour: '',
color: '',
}
}
componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.setState({isReady: true});
});
}
onChangeItem = (label, val) => {
let data = {};
data[label] = val;
this.setState(data);
}
renderPlaceholder() {
return (
<View style={styles.container}>
<Text>Loading...</Text>
</View>
)
}
render() {
if (!this.state.isReady) {
return this.renderPlaceholder();
}
return (
<View style={{flex:1, flexDirection: 'column'}}>
<TimePicker label={'Start hour'} value={this.state.startHour} onChange={this.onChangeItem.bind(this, 'startHour')} />
<TimePicker label={'End hour'} value={this.state.endHour} onChange={this.onChangeItem.bind(this, 'endHour')} />
<ColorPicker label={'Color'} value={this.state.color} onChange={this.onChangeItem.bind(this, 'color')} />
<LabelPicker label={'Shift ID'} value={this.state.shiftId} onChange={this.onChangeItem.bind(this, 'shiftId')} />
</View>
)
}
};
I tried to control animation registration as Chris suggested but it still the same:
onPress = () => {
let handle = InteractionManager.createInteractionHandle();
this.props.navigator.push({component: 'shiftedit'});
InteractionManager.clearInteractionHandle(handle);
}
Actually this is the only solution that works for me now:
componentDidMount() {
// InteractionManager.runAfterInteractions(() => {
// this.setState({isReady: true});
// })
setTimeout(() => {
this.setState({isReady: true});
}, 75);
}
but I'd rather use InteractionManager...
Here's a wild guess as I've no experience with InteractionManager directly. But after looking over the Interaction Manager Docs I noticed that there's a way to register animations. So, my guess is that the Navigator's animations haven't been properly registered. So maybe try something like this...
var handle = InteractionManager.createInteractionHandle();
// run your navigator.push() here... (`runAfterInteractions` tasks are queued)
// later, on animation completion:
InteractionManager.clearInteractionHandle(handle);
// queued tasks run if all handles were cleared
Hope that helps!
Also, keep in mind that if you're running the React Native Debugger while testing your app, React Native animations will appear jittery on Android.
That's been my experience.
https://github.com/jhen0409/react-native-debugger
How can I disable rotation only for specific views (e.g: when using Navigator) and not for the entire app?
The question here already addresses disabling rotation for the entire app
With the react-native-orientation package, it's possible to lock the orientation to portrait/landscape. The package and documentation can be found here: https://github.com/yamill/react-native-orientation
Remember; you should not put your locking inside the rendering of scenes (nor the renderScene method). Since the Navigator re-renders all the scenes in the route stack, this would probably cause weird side effects for you. Rather, the locking/unlocking should be put in the code that interacts with the route stack (ie. calls the push/pop methods).
If your case is about more specific control over orientations of different screens in StackNavigator (something like Portrait -> LandscapeLeft -> LandscapeRight -> Portrait, and all the way back), here is a may-not-that-pretty solution:
packages needed: react-navigation, react-native-orientation;
define base screens as follow:
// baseScreen.js
import React, { Component } from "react";
import Orientation from "react-native-orientation";
export class PortraitScreen extends Component {
constructor(props) {
super(props);
this._willFocusSubscription = this.props.navigation.addListener("willFocus", payload => {
// lock to portrait when this screen is about to appear
Orientation.lockToPortrait();
})
}
componentWillUnmount() {
// remove subscription when unmount
this._willFocusSubscription.remove();
}
}
export class LandscapeScreen extends Component {
constructor(props) {
super(props);
this._willFocusSubscription = this.props.navigation.addListener("willFocus", payload => {
// lock to landscape
Orientation.lockToLandscape();
})
}
componentWillUnmount() {
// remove subscription either
this._willFocusSubscription.remove();
}
}
define concrete screens which extends abovementioned base screen(s):
// moduleScreens.js
import React from "react";
import { Button, View } from "react-native";
import { PortraitScreen, LandscapeScreen } from "/path/to/baseScreen";
export class VideoDescScreen extends PortraitScreen {
render() {
return (
<View>
<Button
title="watch video"
onPress={() => this.props.navigation.navigate("VideoPlayer")}
/>
</View>
)
}
}
export class VideoPlayerScreen extends LandscapeScreen {
render() {
return <View>...</View>
}
}
create route like this:
// route.js
import React from "react";
import { createStackNavigator } from "react-navigation";
import { VideoDescScreen, VideoPlayerScreen } from "/path/to/moduleScreens";
const stack = createStackNavigator(
{
VideoDesc: {
screen: VideoDescScreen
},
VideoPlayer: {
screen: VideoPlayerScreen
}
}
)
How it works? According to doc, we observe event willFocus when screen is initialized, and each time this screen is about to appear (focused) in navigation, we lock device to our desired orientation, works for both PUSH(to) and POP(back from) behaviors.
Hope it helps.