Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make a full screen modal ? #688

Closed
kocyigityunus opened this issue Apr 5, 2015 · 30 comments
Closed

How to make a full screen modal ? #688

kocyigityunus opened this issue Apr 5, 2015 · 30 comments
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@kocyigityunus
Copy link

i am trying to make a full screen modal in a at the root of the app like in the UIExplorer Example. but when i want to close the modal, it's always starting with the "InitialComponent" of the

what i solve this :
1 ) instead of showing it on the root i set styles " position : absolute, top, right = 0 etc. ". but this didn't work.

screen shot 2015-04-05 at 20 51 21

2 ) instead of returning an NavigatorIOS element in render. i tried to create a NavigatorIOS element with React.createElement and passing it to render method. but i couldn't get state of the parent.

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  NavigatorIOS,
  StyleSheet,
  View,
} = React;

var styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
  },
  modal: {
    //flex: 1,
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    top: 0
  }
});

var FirstScreen = require('./FirstScreen');

var blabla = function( obj, modal ){
  console.log("obj : ", obj);
  console.log( "setState : ", obj.setState );
  // set state is always undefined
  obj.setState({ openModal: modal });
};

var DenemeApp = React.createClass({
  getInitialState: function() {
    return {
      openModal: (null: ?React.Component),
      modalOpened : true,
    };
  },
  closeModal : function() {
    this.setState( { modalOpened : false, } );
  },
  render: function() {
    if (this.state.openModal) {
      var Modal = this.state.openModal;
      return (
        <Modal
          onModalExit={() => {
            this.setState({ openModal: null, });
          }}
        />
      );
    }
    console.log( myNavigatorIOS )
    return myNavigatorIOS
  }
});

var myNavigatorIOS = React.createElement( NavigatorIOS,
  {style:styles.container,
    initialRoute : {
      title: 'FirstScreen',
      component: FirstScreen,
      passProps: {
        onModalRequested: (modal) => {
          blabla( DenemeApp, modal );
          //this.setState({ openModal: modal, });
        },
      }
    }
  }
);


AppRegistry.registerComponent('DenemeApp', () => DenemeApp);
module.exports = DenemeApp;

i think that must be a better way

@brentvatne
Copy link
Collaborator

@kocyigityunus - have a look at react-native-modal and let me know if that doesn't answer your question, I'll be happy to answer!

@kocyigityunus
Copy link
Author

i allready looked at it.

when i tried to use it in or with compoenent. NavigatorIOS is being top of the my view with following style. this style is just like you use in modal.

container: {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: 'transparent',
    alignItems: 'center',
    justifyContent: 'center',
}

as you can see in the photo. Navigator bar on top.

screen shot 2015-04-05 at 21 59 19

@brentvatne
Copy link
Collaborator

@vjeux - any insight into how we can absolute position a component to overlay NavigatorIOS?

@vjeux
Copy link
Contributor

vjeux commented Apr 5, 2015

Yeah, this is unfortunate, internally we had to implement the modal component in objective-c, so that it can be on-top of NavigatorIOS and the status bar. cc @sahrens who built it

@brentvatne
Copy link
Collaborator

That makes sense, I'll have a go at fixing that. Thanks @vjeux

@brentvatne
Copy link
Collaborator

Having a bit of a hard time figuring out the right away to do this, any tips @sahrens?

@kocyigityunus
Copy link
Author

maybe this can help : https://github.com/Kureev/react-native-navbar

@jordwalke
Copy link

We have tons of full screen modals with custom animations with the JS implemented navigator. (See the F8 app for an example). Would that work for you?

@brentvatne
Copy link
Collaborator

@jordwalke - that makes sense - I like the JS navigator personally, I was just thinking that it would be useful for others who choose to use NavigatorIOS for my react-native-modal library to just work well with it.

@Kureev
Copy link
Contributor

Kureev commented Apr 5, 2015

@kocyigityunus it'll help, if you'll migrate from NavigatorIOS to basic Navigator. You'll be able to build your own view with navbar and position it however you want. Then, you'll just need to make an overlay and implement your modal (or use very nice react-native-modal as has been mentioned before). Let me know if you'll have any issues with that.

@sahrens
Copy link
Contributor

sahrens commented Apr 5, 2015

One thing you can do is to expose a native API to create a new UIWindow and render the modal content views into that. One way to do this is with a custom native modal component that creates the UIWindow in reactAddSubview and stuffs the view into their instead of as a subview of it's self like it would be default.

What happens if you put your react-native-modal component outside of (e.g. as a sibling to) the NavigatorIOS component?

On Apr 5, 2015, at 2:33 PM, Alexey notifications@github.com wrote:

@kocyigityunus it'll help, if you'll migrate from NavigatorIOS to basic Navigator. You'll be able to build your own view with navbar and position it however you want. Then, you'll just need to make an overlay and implement your modal (or use very nice react-native-modal as has been mentioned before). Let me know if you'll have any issues with that.


Reply to this email directly or view it on GitHub.

@sahrens
Copy link
Contributor

sahrens commented Apr 5, 2015

Ignore my last paragraph - I missed your example using the react-native-modal.

@brentvatne
Copy link
Collaborator

@sahrens - that's a neat idea re: overriding reactAddSubview to create a UIWindow - I'm going to give that a try

@fraserxu
Copy link

fraserxu commented Apr 6, 2015

Would be great if @sahrens could share some code here!

@kocyigityunus
Copy link
Author

i tried to have a es6 way to do that. but i think NavigatorIOS component is not keeping it's state. i am constructing it only once but result is the same. as you can see :

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  NavigatorIOS,
  StyleSheet,
  View,
} = React;

var FirstScreen = require('./FirstScreen');

class DenemeApp extends React.Component{
  constructor(props){

    this.props = props;
    this.state = {
      openModal: (null: ?React.Component),
    }

    // only calling once
    console.log("trying to create own navigator!");

    this.props._ownNavigator = React.createElement( NavigatorIOS,
      {style:styles.container,
        initialRoute : {
          title: 'FirstScreen',
          component: FirstScreen,
          passProps: {
            onModalRequested: (modal) => {
              console.log("on modal requested called!");
              this.setState({ openModal: modal, });
            },
          }
        }
      }
    );

  }
  getInitialState() {
    // this method is not calling.
    //  this must be done in construtor
    console.log("get initial state called!");
    return { };
  }
  closeModal() {
    this.setState( { openModal : false, } );
  }
  render() {
    if (this.state.openModal) {
      var Modal = this.state.openModal;
      return (
        <Modal
          onModalExit={() => {
            console.log("will call openModal null!");
            this.setState({ openModal: null, });
          }}
        />
      );
    }
    // return the navigator object created on the constructor
    return this.props._ownNavigator;
  }
}

var styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'white',
  },
});

AppRegistry.registerComponent('DenemeApp', () => DenemeApp);
module.exports = DenemeApp;

@brentvatne
Copy link
Collaborator

@sahrens - this worked, but when I render the subviews in the new window they stop responding to any click events, and cmd+r no longer refreshes, any idea?

@ide
Copy link
Contributor

ide commented Apr 7, 2015

The window is probably affecting the responder chain. Is your modal window the key window?

@brentvatne
Copy link
Collaborator

@ide - I tried both with and without

    [_overlayWindow makeKeyAndVisible];
    _overlayWindow.userInteractionEnabled = YES;
    _overlayWindow.hidden = NO;

@brentvatne
Copy link
Collaborator

@ide - without being key, cmd+r works but presses won't.

@brentvatne
Copy link
Collaborator

@sahrens
Copy link
Contributor

sahrens commented Apr 7, 2015

Ah yes, you'll need to attach the RCTTouchHander to the modal...something like

[modalView addGestureRecognizer:[[RCTTouchHandler alloc] initWithBridge:_bridge]];

Sorry, I wish I had time to clean up what we have internally sooner, but it relies on some FB infra stuff :(

On Apr 6, 2015, at 8:51 PM, Brent Vatne notifications@github.com wrote:

https://gist.github.com/brentvatne/5115e83d02027869ca83


Reply to this email directly or view it on GitHub.

@brentvatne
Copy link
Collaborator

Thanks @sahrens 😄

Sorry, I wish I had time to clean up what we have internally sooner, but it relies on some FB infra stuff :(

No problem, this is an enjoyable learning exercise

@brentvatne
Copy link
Collaborator

@sahrens - so I have this mostly working, I just can't figure out how to properly dispose of the modal UIWindow and give touch control back to the main UIWindow. The only thing that I have found to work is _mainWindow.windowLevel = UIWindowLevelStatusBar; but that is undesirable of course because the main window's windowLevel should not need to change for this. Example repo is here and component is here

@brentvatne
Copy link
Collaborator

@sahrens - Got this working, the problem was that the component is initialized twice by React - once as a base component without props, and immediately after that once more and the props are applied. The problem was that I was creating the UIWindow in the init function so the first one, for the base, would just stay around indefinitely.

@kocyigityunus - You can use NavigatorIOS with react-native-modal now, just be sure to set the forceToFront prop to true on the modal so it will create it in a new UIWindow!

@brentvatne
Copy link
Collaborator

demo-layered

@jordwalke
Copy link

Awesome work!
Keep in mind that this approach will require reimplementing the same concept in Android, whereas the standard Navigator will not since the scenes are controlled in JS.

It's about tradeoffs, and the approach you've taken has benefits as well: I believe that if you embed a ReactNative container inside of a larger (non-ReactNative) app, your modal will still work well.

@kocyigityunus
Copy link
Author

congs @brentvatne great job.

@sahrens
Copy link
Contributor

sahrens commented Apr 9, 2015

The original motivation was to work with NavigatorIOS, right?

On Apr 9, 2015, at 10:42 AM, Jordan W notifications@github.com wrote:

Awesome work!
Keep in mind that this approach will require reimplementing the same concept in Android, whereas the standard Navigator will not since the scenes are controlled in JS.

It's about tradeoffs, and the approach you've taken has benefits as well: I believe that if you embed a ReactNative container inside of a larger (non-ReactNative) app, your modal will still work well.


Reply to this email directly or view it on GitHub.

@brentvatne
Copy link
Collaborator

@jordwalke - Agreed, definitely a matter of trade-offs here. Will definitely get the same thing working on Android when the time comes!

@sahrens - yup, but this could applicable to overlay any native component on UIWindowLevelStatusBar

@kocyigityunus - can we close this issue now?

@brentvatne
Copy link
Collaborator

Closing 😄

@facebook facebook locked as resolved and limited conversation to collaborators May 29, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 23, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

9 participants