IOS : CADisplay / UIScrollview and Navigation Controller - uinavigationcontroller

So I have managed to get my lovely GLKit 3D menu working with a UIScrollview and life is good until I push to another view controller and come back.
So completely smooth movement, move to next controller and come back. UIScrollview does not bounce or flow nicely?
CADisplay Link is init and nil'd every time the scrollview moves and stops and this seems to work fine up until I push to another controller and come back.
Randomly if I click on a item which causes the scrollview to move and fire off all the code, it then kicks back in to life. sadly if I try to fire this off on the view did appear it does not do the same thing.
- (void)startDisplayLinkIfNeeded
{
if (!self.displayLink)
{
self.displayLink = [CADisplayLink displayLinkWithTarget:self.view selector:#selector(display)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
}
- (void)stopDisplayLink
{
if (self.displayLink)
{
[self.displayLink removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[self.displayLink invalidate];
self.displayLink = nil;
}
}

So, after a whole day of trying to work out this issue, it comes down to
self.preferredFramesPerSecond = 60`
If I dynamically change this to around 15 to 20 depending on what I do, the whole problem goes away.

Related

How to implement an onboarding page with Prism.Forms?

I am developing a Xamarin.Forms app with Prism in which I'd like to incorporate an onboarding page (more specific a top user benefits page, following the Material Design guidelines).
The app itself is structured around a NavigationPage to which I navigate with
NavigationService.NavigateAsync("/NavigationRootPage/MainPage")
in my App(). On the first start I'd like to show the onboarding page instead and I am having quite some issues getting it right.
My first approach was to navigate to MainPage with
_navigationService.NavigateAsync("/NavigationRootPage/MainPage")
from my viewmodel, when the user clicks the Get Started! button. This kind of worked by is also kind of ugly, since this absolute navigation will destroy the oboarding page immediately and not animate the transition. Furthermore at the moment the oboarding page is destroyed, the MainPage will be built, which will take a small, but noticeable, amount of time. In effect the user will notice the MainPage being built up, which does not look smooth at all.
My second approach was to navigate in a relative fashion from my viewmodel.
_navigationService.NavigateAsync("NavigationRootPage/MainPage")
This works way smoother, with the transition animation and after the animation is done, the MainPage is already ready to go. But again there is a major drawback. You can navigate back to the onbaording page, which we dont't want neither. And - to my knowledge - there is no (clean) way to remove the page from the navigation stack, too. I tried calling PageUtility.DestroyPage on my onboarding page, but this only worsened things, since it seemed to keep the page, but destroy the viewmodel, resulting in my onboarding page being shown without data when pushing the back button.
My third approach did not work at all, although it seemed promising to me. In my App() I pushed my navigation page with the main page then then my onboarding page modal
NavigationService.NavigateAsync("/NavigationRootPage/MainPage");
NavigationService.NavigateAsync("OnboardingPage", useModalNavigation: true);
and then in my viewmodel
_navigationService.GoBackAsync(useModalNavigation: true)
but this approach
showed the header of the NavigationPage although the onbaording page was supposed to be shown as a modal
refused to GoBackAsync - when calling this method, nothing happens
waiting for the first call to NavigateAsync did not change anything either.
Some other things I've tried
Implemented INavigationOptions in my viewmodel with ClearNavigationStackOnNavigation being true
Tried setting Application.MainPage after my NavigationPage was shown, but to no avail
I would have believed that this was king of a common requirement when programming an app. Is there something I've missed? Or will I have to live with one of those drawbacks?
I think you are overthinking this. If you want to show your Onborading page first then just navigate to it first.
`NavigateAsync("NavigationPage/OnboardingPage");
Or if you want to have the MainPage in the stack, then start the app with a deeplink
`NavigateAsync("NavigationPage/MainPage/OnboardingPage");
If you don't want to show the navigation header, just hide it for the onboarding page.
Don't use an absolute navigation unless you want to completely reset the navigation stack (equivalent to MainPage = new MainPage()).
I have found a solution, which is not the most beautiful one (it is actually quite ugly) but working.
In my MainPages viewmodel I implemented INavigatingAware and navigated to my OnboardingPage modally
public async void OnNavigatingTo(NavigationParameters parameters)
{
await _navigationService.NavigateAsync("LandingPage", useModalNavigation: true);
}
However, removing the moal page with
this._navigationService.GoBackAsync(useModalNavigation: true);
does not work as expected. The modal is not removed (although it should work this way from looking at the code, but I did not manage to debug with Re# generated PDBs). Hence I had to go the ugly (non-MVVM) way and create an event handler for Button.Click and remove the modal manually
private void Button_OnClicked(object sender, EventArgs e)
{
this.Navigation.PopModalAsync();
}
This will return to my MainPage smoothly with an animation and my MainPageis already up and running without being built up while already visible.
Still, I'd appreciate an answer on how to do it the Prism way.

Xamarin Forms - ScrollView - ScrollToAsync to bottom not working as expected

I have a screen where it shows comment list using stack layout and scrollview. User can add one more comment and click submit would add one more comments at the end of this scroll view for Xamarin Forms - Android and iOS app. Requirement is to scroll this list up to show latest display comment element. For this, I have used below line of code but it does not scroll up till the last element but second last element. I observed it in IOS and Android both.
await scrollView.ScrollToAsync(stkMain, ScrollToPosition.End, true);
Below image would give more idea about it.
As shown in picture, stack Layout 3 is not visible on screen though I have used above code to scroll till end. I have to scroll up scroll view to see stack layout 3.
Expected behavior - scroll view should scroll till complete last element as displayed on screen. Kindly suggest If I am not doing it right.
One thing I forget to mention is, when I have create point at line having scrolToAsync method in debug mode. Break point hits that line and if I hit F5 would make last element visible. I am surprised to see it but it happens
Remember that the rendering methods often is asynchronous, and the code behind can run before the elements are available on the rendered screen. I know that it's not the best solution, but sometimes I used to force a 300ms delay before run any visual interaction.
Try wait a short time (like 100 or 200ms) after you add new comment elements and then try scroll to the last child of your stkMain, instead.
Something like this:
// Here goes your logic to add the new comment
await Task.Delay(100);
var lastChild = stkMain.Children.LastOrDefault();
if(lastChild != null)
scrollView.ScrollToAsync(lastChild, ScrollToPosition.MakeVisible, true);
If you want to scroll just to bottom try
Device.BeginInvokeOnMainThread(async () =>
{
// Update your children here, add more or remove.
// todo
if (Device.RuntimePlatform == Device.Android)
{
await scrollView.ScrollToAsync(0, stkMain.Height, true);
}
else
{
await Task.Delay(10); //UI will be updated by Xamarin
await scrollView.ScrollToAsync(stkMain, ScrollToPosition.End, true);
}
});

Using Navigation Controller in TabBar Controller Iphone 6+ IOS 8.3

I am recently facing an issue in my app on iphone 6+ IOS8.3. The issue is i am using uitabbarController in my app and each tab of tab bar controller contains a uinavigationController.
Now when i select the 6th/7th tab by going into More tab and then rotate the screen then black screen appears.
To test the scenario i made an saperate applictaion and make the same structure, i.e made 9 tabs and each tab contain navigation controller. All this is done on storyboard and no code was written.
Then i run the app and select the 6th tab and rotate the screen, the black screen appears. and when i rotate back to portrait then everything become fine again.
I am attaching the screen shots for further explanation.
So anyone able to tell why it turns into black screen? I am doing it wrong ? or That is a bug of IOS8.3 or something else?
I ran into the same issue today and since this question has not been answered yet, I'd like to present my simple solution.
In your UITabbarController subclass, subscribe to the rotation events:
[[NSNotificationCenter defaultCenter] addObserver:self //Add yourself as an observer
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
Add the following code to the rotation observer method:
- (void) orientationChanged:(NSNotification *)notification {
if (IS_IPHONE_6P) { // some magic to figure out if we're on iphone 6 plus
self.customizableViewControllers = #[]; // we don't want an edit button to appear
if (self.selectedIndex == 5 || self.selectedIndex == 6) { // the effect only happens to view controllers at index 5 and 6.
[self.moreNavigationController popToRootViewControllerAnimated:NO]; // pop the view controller from the moreNavigationViewController
self.selectedViewController = self.viewControllers[self.selectedIndex]; // set the selected view controller to be visible again.
}
}
}

How to reload Page in blackberry cascades QML

in my blackberry cascades app I have created a page using qml that loads data from backend after making an API call and works fine. But after I move to next page and come back I need to reload the data. i.e perform the onCreationCompleted operation again. Also the Qt.pageDef shows undefined after I come back so I guess if I could reload the page, it would work fine. I'm new to blackberry cascades, can anyone tell me what should I do to reload this page again and re-initialise Qt.pageDef?
Page {
id: homePage
Container {
id:contactListView
//Some code to create listview
onCreationCompleted:
{
Qt.pageDef = contactListView;
fetchInfo();
}
fetchInfo()
{
//make api call and fill listview
}
}
}
Obviously, there are some part of code missing as you show us a Page but you seem to push a new page from a NavigationPane.
Add this to your NavigationPane :
onPopTransitionEnded: {
fetchInfo()
}

Adobe Flex PopUpManager -- multiple instances of a TitleWindow opened

Setup: My Flex application is one consisting of several "subapps". Basically, the main application area is an ApplicationControlBar with buttons for each of the subapps. The rest of the area is a canvas where the subapps are displayed. Only one subapp is visible at a time. When switching between subapps, we do a canvas.removeAllChildren(), then canvas.addChild(subAppSwitchedTo). It's essentially a manual implementation of a ViewStack (the pros and cons of which are not the topic of this, so refrain from commenting on this).
Problem: In one of my subapps (let's say subapp "A"), I have a search function where results are displayed in a TitleWindow that gets popped up. Workflow is like enter search criteria, click search button, TitleWindow pops up with results (multiple selection datagrid), choose desired result(s), click OK, popup goes away (PopUpManager.removePopUp), and continue working. This all works fine. The problem is if I switch to a different subapp (say "B" -- where A gets removeAllChildren()'d and B gets added), then switch back to A and search again, when the results TitleWindow pops open, there will be TWO stacked on top of each other. If I continue to navigate away and back to A, every time I search, there will be an additional popup in the "stack" of popups (one for each time A gets addChild()'d).
Has anyone else experienced this? I'm not sure what to do about it and it's causing a serious usability bug in my application. Does this ring any bells to anyone? It's like I somehow need to flush the PopUpManager or something (even though I'm correctly calling removePopUp() to remove the TitleWindow). Please help!
EDIT
Flex SDK = 4.5.1
// Subapp "A"
if (!certificateSearchTitleWindow)
{
certificateSearchTitleWindow = new CertificateSearchTitleWindow;
certificateSearchTitleWindow.addEventListener("searchAccept", searchOKPopupHandler);
certificateSearchTitleWindow.addEventListener("searchCancel", searchClosePopupHandler);
}
PopUpManager.addPopUp(certificateSearchTitleWindow, this, true);
My guess is that the popup is removed from the main display list when you remove its parent (this in the PopUpManager.addPopup() method), but not from its parent display list. Why don't you listen, in your subapps, to the Event.REMOVED event, and then remove your popup ? That would be :
private var pp:CertificateSearchTitleWindow;
private function onCreationComplete():void
{
addEventListener(Event.REMOVED, onRemovede);
}
private function addPopUp():void
{
if (!pp) {
pp = new CertificateSearchTitleWindow();
PopUpManager.addPopUp(pp, this, true);
}
}
private function onRemoved(event:Event):void
{
if (pp) {
PopupManager.removePopUp(pp);
pp = null;
}
}
Thank you to those who gave suggestions. It turned out I was re-registering an eventListener over and over.
I am using a singleton to act as "shared memory" between the subapps. I was setting singleton.addEventListener(someType, listener) in subapp A's creationComplete callback. So everytime I navigated back to A, the creationComplete was running and re-adding this listener. After the search, the listener method (that opened the popup) was being called multiple times, i.e., as many times as the event had been added.
xref: http://forums.adobe.com/message/3941163

Resources