ReactNavigator -StackNavigator how to use diffrent animation with only specific screen - react-navigation

using
"react-navigation": "^4.0.10",
"react-navigation-stack": "^1.10.3",
import {
createStackNavigator, StackViewTransitionConfigs,
} from 'react-navigation-stack';
const HomeStackNavigator = createStackNavigator({
List:ListContainer,
Detail:DetailContainer,
Modal: {
screen: ModalContainer,
navigationOptions: {
...StackViewTransitionConfigs.ModalSlideFromBottomIOS,
},
},
}, {
mode: 'card',
headerMode: 'none',
defaultNavigationOptions: {
gestureEnabled: true,
...StackViewTransitionConfigs.SlideFromRightIOS,
},
});
All other screens open in the form of a card, and I want to open only one specific screen in modal form.
i tried
const HomeStackNavigator = createStackNavigator({
List:ListContainer,
Detail:DetailContainer,
},
}, {
mode: 'card',
headerMode: 'none',
defaultNavigationOptions: {
gestureEnabled: true,
...StackViewTransitionConfigs.SlideFromRightIOS,
},
});
const HomeStackNavigator2 = createStackNavigator({
Home:HomeStackNavigator,
Modal: {
screen: ModalContainer,
},
}, {
mode: 'modal',
headerMode: 'none',
});
The first code failed because all the arcs were opened in card format.
In the second code I tried, the screen I wanted was opened in modal form, but when I moved from modal to detail, the modal was closed.
In the first code, is it possible to open only the modal screen in modal form?

I solved it this way.
import {
createStackNavigator, StackViewTransitionConfigs, StackViewStyleInterpolator,
} from 'react-navigation-stack';
const transitionConfigs = (props) => {
const { scene } = props;
const { route } = scene;
const params = route.params || {};
const transition = params.transition || 'forHorizontal';
if (transition === 'forVertical') {
return StackViewTransitionConfigs.ModalSlideFromBottomIOS;
}
return StackViewTransitionConfigs.SlideFromRightIOS;
};
const HomeStackNavigator = createStackNavigator({
List:ListContainer,
Detail:DetailContainer,
Modal: {
screen: ModalContainer,
},
}, {
mode: 'card',
headerMode: 'none',
transitionConfig:transitionConfigs,
});
Change animation by sending trasition:'forVertical' to params when navigate.

Related

Nativescript angular keep app playing in background

[nativescript] How do I keep a native script - angular app running in the background in IOS. I have a button that opens the in-app browser and there I have a webpage that plays music, I'd like the music to carry on playing when the user leaves the application.
here is my component.ts
export class BrowseComponent implements OnInit {
openLink = async () => {
try {
const url = ''
if (await InAppBrowser.isAvailable()) {
const result = await InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'done',
preferredBarTintColor: '#3e00be',
preferredControlTintColor: 'white',
readerMode: false,
animated: true,
modalPresentationStyle: 'fullScreen',
modalTransitionStyle: 'crossDissolve',
modalEnabled: true,
enableBarCollapsing: false,
// Android Properties
showTitle: true,
toolbarColor: '#3e00be',
secondaryToolbarColor: 'white',
enableUrlBarHiding: true,
enableDefaultShare: true,
forceCloseOnRedirection: false,
// Specify full animation resource identifier(package:anim/name)
// or only resource name(in case of animation bundled with app).
animations: {
startEnter: 'slide_in_right',
startExit: 'slide_out_left',
endEnter: 'slide_in_left',
endExit: 'slide_out_right'
},
headers: {
'my-custom-header': 'my custom header value'
}
})
// alert({
// title: 'Response',
// message: JSON.stringify(result),
// okButtonText: 'Ok'
// })
}
else {
MyDelegate.prototype.applicationDidEnterBackground = function (application: UIApplication) {
console.log('App is running in background');openUrl(url);
AVAudioSession.sharedInstance().setCategoryWithOptionsError(
AVAudioSessionCategoryPlayAndRecord,
AVAudioSessionCategoryOptions.DefaultToSpeaker
);
};
}
}
catch(error) {
// alert({
// title: 'Error',
// message: error.message,
// okButtonText: 'Ok'
// })
}
}
}

React Navigation: setParams in Nested Navigator

In my React Native application, I use React Navigation.
It's an app that enables the user to search an underlying database, i.e. for names. The GIF below illustrates the navigation.
From the landing screen, Go to search button is pressed (Main Stack Navigator) --> The Header appears, which is alright.
On the second screen, there is a bottomTabNavigator, where names is chosen (in names, there is a second StackNavigator nested).
This leads to the third screen. Here, three cards are shown. With the help of the second StackNavigator, clicking on Mehr opens a details screen.
What I want to achieve is that the Header of the first StackNavigator (that one at the top) disappears as soon as the user opens the details screen.
You see a button there because in the first step, I wanted to let the Header disappear on button click.
The below code works if it is implemented in a screen that is derived from the first StackNavigator directly. But because I am inside a nested navigator, it does not work anymore.
Here is the code:
App.tsx:
imports ...
class RootComponent extends React.Component {
render() {
const image = require('./assets/images/corrieBackground3.png');
console.log('calling the store', this.props.resultValue); // undefined
return (
<View style={styles.container}>
<LandingPage />
</View>
);
}
}
const RootStack = createStackNavigator(
{
LandingPage: {
screen: RootComponent,
navigationOptions: {
header: null,
},
},
SearchScreen: {
screen: SearchScreen,
navigationOptions: {
title: 'I SHOULD DISAPPEAR',
},
},
},
{
initialRouteName: 'LandingPage',
},
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
TwoTabs.tsx (for the 2nd screen):
imports ...
const SearchBarStack = createStackNavigator(
{
SearchBar: {
screen: SearchBar,
navigationOptions: {
header: null,
},
},
Details: {
screen: Details,
navigationOptions: {
title: 'I am here, above header disapear',
},
},
},
{
initialRouteName: 'SearchBar',
},
);
const TabNavigator = createBottomTabNavigator(
{
One: {
screen: SearchCriteria,
navigationOptions: {
tabBarLabel: 'criteria',
},
},
Two: {
screen: SearchBarStack,
navigationOptions: {
tabBarLabel: 'names',
},
},
},
);
const TabLayout = createAppContainer(TabNavigator);
type Props = {};
const TwoTabsHorizontal: React.FC<Props> = ({}) => {
return (
<View>
<TabLayout />
</View>
);
};
export default TwoTabs;
SearchBar.tsx (3rd screens skeleton):
import ...
type Props = {};
const SearchBar: React.FC<Props> = () => {
// logic to perform database query
return (
<View>
<ScrollView>
... logic
<SearchResult></SearchResult> // component that renders 3 cards
</ScrollView>
</View>
);
};
export default SearchBar;
Card.tsx (card rendered by SearchResult):
imports ...
type Props = {
title: string;
navigation: any;
};
const Card: React.FC<Props> = ({title, navigation}) => {
return (
<Content>
<Card>
<CardItem>
<Right>
<Button
transparent
onPress={() => navigation.navigate('Details')}>
<Text>Mehr</Text>
</Button>
</Right>
</CardItem>
</Card>
</Content>
);
};
export default withNavigation(Card);
And finally, the Details screen together with its Content. Here, the Header from the first StackNavigator should be hidden.
imports ...
type Props = {};
const Details: React.FC<Props> = ({}) => {
return (
<View>
<Content></Content>
</View>
);
};
export default Details;
imports ...
type Props = {
navigation: any;
};
class Content extends React.Component {
state = {
showHeader: false,
};
static navigationOptions = ({navigation}) => {
const {params} = navigation.state;
return params;
};
hideHeader = (hide: boolean) => {
this.props.navigation.setParams({
headerShown: !hide,
});
console.log('props ', this.props.navigation);
};
render() {
return (
<View>
<View>
</View>
<Button
title={'Press me and the header will disappear!'}
onPress={() => {
this.setState({showHeader: !this.state.showHeader}, () =>
this.hideHeader(this.state.showHeader),
);
}}
/>
</View>
);
}
}
export default withNavigation(CardExtended);
Maybe someone has an idea?

tabBarOnPress stopped working react-navigation 3.3.2

After upgrading to react-navigation 3.3.2 the tabBarOnPress no longer fires. Code snippet below. Any ideas?
const Tabs = createBottomTabNavigator(
{
HomeStack,
WallStack,
MemeStack,
},
{
navigationOptions: ({navigation}) => ({
tabBarOnPress: () => {
console.log('tab pressed');
}
})
}
);
export default DrawerNav = createDrawerNavigator({
Tabs: Tabs
},{
drawerBackgroundColor: Colors.grayDark,
contentComponent: Sidebar
})
tabBarOnPress is working, but I'm using it like this. You need to pass it as a property of each stack. (don't forget to call the defaultHandler to keep the default behavior:
const DashboardStack = createStackNavigator(
{
Dashboard,
}
);
DashboardStack.navigationOptions = {
tabBarOnPress({ navigation, defaultHandler }) {
// do something
defaultHandler();
},
};
const ProfileStack = createStackNavigator(
{
Profile,
AccountInfo,
Membership,
Browser,
ConnectedAccounts,
}
);
ProfileStack.navigationOptions = {
tabBarOnPress({ navigation, defaultHandler }) {
// do something
defaultHandler();
},
};
const SpendingStack = createStackNavigator(
{
Budget,
Transactions,
}
);
SpendingStack.navigationOptions = {
tabBarOnPress({ navigation, defaultHandler }) {
// do something
defaultHandler();
},
};
export default createBottomTabNavigator(
{
SpendingStack,
DashboardStack,
ProfileStack,
}
);

Resetting the navigation stack when changing tab (StackNavigators nested in TabNavigator)

I have two StackNavigator. Movies:
const MoviesStackNavigator = createStackNavigator({
Movies: Movies,
MovieDetails: MovieDetails,
},{
initialRouteName: 'Movies',
})
and actors:
const ActorsStackNavigator = createStackNavigator({
Actors: Actors,
ActorDetails: ActorDetails,
},{
initialRouteName: 'Actors',
})
I am using them inside a TabNavigator:
const RootTabs = createBottomTabNavigator({
Movies: {
screen: MoviesStackNavigator,
navigationOptions: {
tabBarLabel: 'Movies'
}
},
Actors: {
screen: ActorsStackNavigator,
navigationOptions: {
tabBarLabel: 'Actors'
}
},
})
When the user changes tab, I want him to arrive to the root component of that tab (Movies or Actors), not to a stacked component (MoviesDetails or ActorsDetails). In other word, when a user quits a tab, the StackNavigator in that tab should be resetted to the root component.
My first approach was to use StackActions.reset when initializing the root component in a tab to try to reset the other tab (that the user just quit) but the library prevents interacting between navigators, at least in that way.
So, any ideas?
My solution was to use tabBarOnPress:
const RootTabs = createBottomTabNavigator({
Movies: {
screen: MoviesStackNavigator,
navigationOptions: {
tabBarLabel: 'Movies',
tabBarOnPress: ({navigation, defaultHandler}: any) => {
navigation.navigate('Actors')
defaultHandler()
},
}
},
Actors: {
screen: ActorsStackNavigator,
navigationOptions: {
tabBarLabel: 'Actors',
tabBarOnPress: ({navigation, defaultHandler}: any) => {
navigation.navigate('Movies')
defaultHandler()
},
}
},
})

infinite scrolling using AgGridReact

I'm trying to achieve infinite scrolling using ag grid react component, but it doesn't seems to be working.
here is my implementation :
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid/dist/styles/ag-grid.css';
import 'ag-grid/dist/styles/ag-theme-balham.css';
class TasksGridContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
gridOptions: {
//virtual row model
rowModelType: 'infinite',
paginationPageSize: 100,
cacheOverflowSize: 2,
maxConcurrentDatasourceRequests: 2,
infiniteInitialRowCount: 1,
maxBlocksInCache: 2,
components: {
loadingRenderer: function(params) {
console.log('loadingCellRenderer', params);
if (params.value !== undefined) {
return params.value;
} else {
return '<img src="https://raw.githubusercontent.com/ag-grid/ag-grid-docs/master/src/images/loading.gif">';
}
}
},
defaultColDef: {
editable: false,
enableRowGroup: true,
enablePivot: true,
enableValue: true
}
}
};
}
componentDidMount() {
this.props.actions.getAssignedTasks();
this.props.actions.getTeamTasks();
}
componentWillReceiveProps(newProps) {
if (this.props.taskView.taskGrid.listOfTasks.length > 0) {
this.setState({
loading: false ,
gridOptions: {
datasource: this.props.taskView.taskGrid.listOfTasks
}
});
}
}
render() {
return (
<div id="tasks-grid-container">
<div style={Style.agGrid} id="myGrid" className="ag-theme-balham">
<AgGridReact
columnDefs={this.props.taskView.taskGrid.myTaskColumns}
rowData={this.props.taskView.taskGrid.listOfTasks}
gridOptions={this.state.gridOptions}>
</AgGridReact>
</div>
</div>
);
}
}
TasksGridContainer.propTypes = {
listOfTasks: PropTypes.array,
actions: PropTypes.object
};
const mapStateToProps = ({ taskView }) => {
return {
taskView: {
taskGrid: {
listOfTasks: taskView.taskGrid.listOfTasks,
myTaskColumns: taskView.taskGrid.myTaskColumns,
teamTaskColumns: taskView.taskGrid.teamTaskColumns
}
}
}
};
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators(taskGridActions, dispatch)
};
}
module.exports = connect(mapStateToProps, mapDispatchToProps)(TasksGridContainer);
columnDefs are being set once props.taskView.taskGrid.myTaskColumns is available.
a sample columndef:
[
{
cellRenderer: "loadingRenderer", checkboxSelection: true, field: "action", headerCheckboxSelection: true, headerCheckboxSelectionFilteredOnly: true, headerName: "Action"
},
{
"activity"headerName: "Activity Name"
}
]
Although grid is loading fine, but when i scroll it should call "loadingRenderer" component. But,I'm not able to see any loading gif when i scroll.
Am i doing something wrong in implementation?
Actual issue was not calling the the props properly and was not having onGridReady function to use gridAPi.
I modified the code and it starts working:
<AgGridReact
components={this.state.components}
enableColResize={true}
rowBuffer={this.state.rowBuffer}
debug={true}
rowSelection={this.state.rowSelection}
rowDeselection={true}
rowModelType={this.state.rowModelType}
paginationPageSize={this.state.paginationPageSize}
cacheOverflowSize={this.state.cacheOverflowSize}
maxConcurrentDatasourceRequests={this.state.maxConcurrentDatasourceRequests}
infiniteInitialRowCount={this.state.infiniteInitialRowCount}
maxBlocksInCache={this.state.maxBlocksInCache}
columnDefs={this.props.columns}
rowData={this.props.rowData}
onGridReady={this.onGridReady}
>
</AgGridReact>
state :
this.state = {
components: {
loadingRenderer: function(params) {
if (params.value !== undefined) {
return params.data.action;
} else {
return '<img src="https://raw.githubusercontent.com/ag-grid/ag-grid-docs/master/src/images/loading.gif">';
}
}
},
rowBuffer: 0,
rowSelection: "multiple",
rowModelType: "infinite",
paginationPageSize: 100,
cacheOverflowSize: 2,
maxConcurrentDatasourceRequests: 2,
infiniteInitialRowCount: 1,
maxBlocksInCache: 2
};
onGridReady function :
onGridReady = (params, data = []) => {
this.gridApi = params;
this.gridColumnApi = params.columnApi;
this.updateData(params,data);
}

Resources