See code below.
iPad 12.9 inch 2nd generation v12.1
Ti SDK 7.4.1GA
*+Scenario A+*
Launch App and leave in full screen.
- in Landscape - everything is fine. MasterView (on left) and DetailView (on right) are both what you'd expect.
- in Portrait - everything is fine. The MasterView (on left) is truly 'overlayed' as defined in my .xml. You can press my Label, 'Toggle Master View', and as expected the MasterView is truly on top and when toggle off you can see the DetailView behind it.
*+Scenario B+*
Launch App and then go into Split View (by dragging up the dock and opening any other app beside it) and divide the 2 apps 50/50 on the screen.
{color:red}- in Landscape - THIS is where the issue exists. When you toggle, you can see the Ti.Gesture 'orientationchange' detects correctly that the view is "Portrait" (due to split screen). This is expected (even though the device is really in landscape - it operates as Portrait as defined by the SplitWindow). HOWEVER, the Master/Detail 'SplitWindow' are not behaving correctly. Try to toggle the MasterView and you'll notice that the DetailView is not behind it. The MasterView is NOT being overlayed as defined.{color}
- in Portrait - everything is fine. The MasterView (on left) is truly 'overlayed' as expected and again you can press that toggle label to show the DetailView behind it.
XML:
<Alloy>
<SplitWindow backgroundColor="white" showMasterInPortrait="true" masterIsOverlayed="true" platform="ios" onOpen="onFirstLaunch">
<!--MASTER View-->
<NavigationWindow id="masterNavigationWindow" platform="ios">
<Window title="Menu" barColor="#e4e4e4" backgroundColor="#e4e4e4" tintColor="#0069aa" class="container" layout="vertical">
<Label text="Label Here" />
</Window>
</NavigationWindow>
<!--DETAIL View-->
<NavigationWindow id="detailNavigationWindow" platform="ios">
<Window title="SplitView Example" barColor="#ffffff" tintColor="#0069aa" class="container" layout="vertical" backgroundColor="#ff0000" >
<Label text="Toggle Master View" onClick="toggleMasterView" top="100" />
</Window>
</NavigationWindow>
</SplitWindow>
</Alloy>
JAVASCRIPT
function toggleMasterView(){
$.masterNavigationWindow.visible = !$.masterNavigationWindow.visible;
}
function onFirstLaunch(){
setTimeout(function() {
updateSplitViewUI(Ti.Gesture.portrait, Ti.Gesture.landscape);
}, 200);
}
/**
*
* @param {Bool} isPortrait
* @param {Bool} isLandscape
*/
function updateSplitViewUI(isPortrait, isLandscape){ //Ti.API.info("updateSplitView: (isPortrait:" + isPortrait + ",isLandscape:" + isLandscape + ")");
if (isLandscape) { //force show the Master Window in Landscape Mode
$.masterNavigationWindow.visible = true;
}
}
Ti.App.addEventListener('resumed', function(){
Ti.API.info("App Resumed");
Ti.Gesture.fireEvent('orientationchange');
});
Ti.App.addEventListener('paused', function(){
Ti.API.info("App Paused");
});
Ti.Gesture.addEventListener('orientationchange',function(e) {
updateSplitViewUI(e.source.portrait, e.source.landscape);
});
I was asked to attach a screenshot and/or explain how it impacts or block me. I chose Both. I am looking to extend an existing Titanium iPad app to support SplitView. In the process of planning to do that, and determine the amount of effort, I setup a simple playground app to test how it all works. While doing so, I used a simple inline YouTube Video Player to test the functionality. And in doing so (see attached screenshot), when in landscape orientation and split with another app - you can see that the MasterView takes up a significant portion of the left side of my app. Typically this is where masterIsOverlayed comes in and allows me to show/hide that as needed (just like the Native Apple Mail App) to regain that real estate. For a real-life example - Appcelerator did a write-up a while back on how I was using Titanium to drive our business. In your write-up you can see how much data is on that screen. Now imagine splitting that view in half (for 2 apps side by side) and then imagine losing another 20% of that because masterIsOverlayed isn't working correctly. https://www.appcelerator.com/blog/2015/08/how-amwins-brings-mobile-agility-to-auto-insurance/ Please let me know if you need further information. But at the end of the day - the masterIsOverlayed is not working natively as designed by Apple. (again - see Apple Mail app for an example) Thanks, Adam.
Even if you hid that MasterView entirely, or merged the stacked NavigationWindows, either would work better than taking up the space and not allowing the app to use it.
*Issue #1 (initial issue listed on this ticket)* * Image titled, "Simulator Screen Shot - iPad Pro (12.9-inch) (2nd generation) - 2018-12-14 at 12.04.02.png" shows how, when in Landscape Mode and using SplitView with another app, the left (MasterView) takes up a significant portion (~20%) of my app and even with masterIsOverlay defined it isn't being overlayed. *Issue #2* * Image titled, "image.png" shows another issue. If you are in Portrait Mode and NOT using SplitView, then when I set the left (MasterView) to visible=false, it DOES hide correctly....but then you can NOT click any of the leftNavButtons on the DetailView. I suspect this is because the left (MasterView) is obstructing the DetailView NavButtons with a hidden Window. We either need a way to click those NavButtons or some other method (than visible=false) to hide the MasterView Overlay.
*Issue #3* Look at the doc for SplitWindow - https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.SplitWindow In your example there is an eventListener 'visible' that, appears, should be fired when Master/Detail Views show/hide.....but it is not listed in 'Events' I could never get it to fire. Either there is some other defined method to show/hide a view that is not documented or if visible=true/false is the way to show/hide - then that listener is not firing.
I have done some more testing. If I go into SplitView with 2 apps side by side and I rotate the device multiple times from Portrait to Landscape and back/forth..... in Landscape (physical) orientation: Titanium reports "Landscape" but that is incorrect. When split with another app, the app should always behave as though it was Portrait, and because Titanium is not reporting that correctly, then in the class TiUIiOSSplitWindow.m - line #122
the top-level else gets executed, instead of the (isPortrait), and inside the else (ie. Landscape) there are no conditions for showMasterInPortrait & masterIsOveralyed. Which is to be expected if truly in Landscape and fullscreen. So, I *think* Issue #1 is due to the incorrect assumption that if it is NOT in Portrait mode (see code/line mentioned above) then it must be Landscape. I think Issue #1 needs an additional condition/check for when it is in Landscape Mode to look for SplitView. My suggestion would be to reverse the logic in lines 122-169 to something like:
I just dont know how enough about Objective-C to know how to determine isSplitView (that I added above)
ok. so I took a stab at it and I think I found the solution. In the file: TiUIiOSSplitWindow.m inside: - (void)layoutSubviewsForOrientation:(UIInterfaceOrientation)orientation Add this:
Then flip the logic to this:
Hold on.
Ti.Gesture
is supposed to provide the device's orientation, not the app's orientation. You already have the ability to detect the app's orientation. You can do so by comparing the window's width/height like the below.But
Ti.Gesture
is the only means of determining the device's orientation. This API is important for fixed-orientation apps (such as portrait-only) that want to rotate the UI themselves. This is typically how a camera app works. Perhaps my above comments might be unrelated to your specific issue, but I wanted to make it clear howTi.Gesture
orientation is supposed to work.I am most likely confusing the terminologies. on an iPad, rotate to landscape, and open apple mail app. you see a splitview. now slide up dock and open messages in split view. you'll instantly see the apple mail split view adjust and hide the MasterView - only showing the DetailView. if I use your event listener above - it only hides the MasterView and doesnt give the DetailView the entire width of the app. All I am trying to say is that, when using masteroverlay, then it should truly be overlayed meaning the detailview takes up the entire screen.
if you are saying I should use my own logic/eventlistener like you did above, then we need methods to show/hide the masterView and expand/restrict the detailview size accordingly. I dont see those in the docs.
We may be talking about 2 different things here. Sorry. I agree that the overlay should fill the window. _(I'm not an iOS developer here. I'll wait for someone on the iOS team to comment on this.)_ I just want to make it clear how
Ti.Gesture
orientation is supposed to work. It's an often misused feature. Let's forget about master overlay for the moment. If you hold the device "landscape" and put it into split-screen mode,Ti.Gesture
will still return "landscape" (this is the device orientation) even though the app is displayed "portrait". This would be the correct behavior. On an Android tablet, split-screen mode gets a bit more interesting since you can drag the split-bar, which would resize the 2 apps... and can resize them to such as degree that 1 app would be landscape and the other portrait. My point being that usingTi.Gesture
device orientation to layout content isn't the way to go. You have to look at the app window's size instead. (Probably not related to your master overlay issue, but wanted to make my point clear.)I agree Ti.Gesture is correct. I was referring to orientation in the context of the SplitView determination of 'portrait' vs 'landscape' and the fact that if in landscape and split view - then it should *behave* as though portrait (meaning the master view is overalayed. Sorry for the confusion but yes, I agree with you the Ti.Gesture API us devs use appears to be fine. I wasn't sure how to describe the window constraints within splitview, but maybe you explained it best with your event listener example.
Okay. I get what you're saying. Sorry if I added confusion to this. :)
Ha. No apology needed - I mis-used the terms.
[~amwinsauto] Thanks for raising the issue. Issue 1- In [document](https://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.iOS.SplitWindow) it is mentioned that- "The property masterIsOverlayed controls how the master is displayed in portrait mode. When masterIsOverlayed is set to true, the detailView occupies the full screen and and masterView is displayed overlayed on top to the left of the screen. When masterIsOverlayed is set to false, the available screen width is split between the masterView and detailView". Which means that masterIsOverlayed property is supported for portrait mode only. But I agree with you that masterIsOverlayed should be supported in landscape mode while using SplitView with another app. Issue 2- This is a bug. Need to look in this. Issue 3- 'visible' event is not supported in SDK. I am not sure why it is in document. Need to update document. Do you have any suggestion?
Classic app test case -
Issue #1 - I submitted a PR (attached to this ticket) that, from my testing, appears to provide masterIsOverlayed when in Landscape AND using SplitView with another App. Issue #2 - After more testing, it is not only the NavButtons that are not-clickable. When you hide the MasterView, anything on that "section" of the DetailView (that was initially covered by the MasterView when Overlayed) is completely unclickable.
Issue #2 is due to [masterViewWrapper](https://github.com/appcelerator/titanium_mobile/blob/3c757bf8b913c1957f164b47dbccfa5ab8b3f39b/iphone/Classes/TiUIiOSSplitWindow.m#L58). When we hide navigation window, masterViewWrapper is still there. Thats why that area is not clickable. In my view we should introduce a new property "masterViewVisible" in TiUIiOSSplitWindow, which will ensure show and hide of masterView. [~amwinsauto] [~jquick] any thought? Thanks!
Sounds like that should work.
PR (master) - https://github.com/appcelerator/titanium_mobile/pull/10559 PR (8_0_X) - https://github.com/appcelerator/titanium_mobile/pull/10595
PR merged
Verified the fix in SDK 8.0.0.v20190114160512 and 8.1.0.v20190115063333.'masterIsOverlayed' works as expected.