I have a simple App with two views. As soon as the first view is loaded I'm performing a Touch ID sensor authentication (see also this question):
func testTouchID()
{
if touchIDContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error:&touchIDError)
{
touchIDContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: {
(success: Bool, error: NSError?) -> Void in
if success
{
self.performSegueWithIdentifier("showSecondView", sender: self)
return;
} else {
With this code the segue is performed, but the second view just appears for a moment and then the App goes back to the first view.
It seems that the code inside canEvalutePolicy is not finished, so the navigation controller push the first view.
I tried several things like:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
NSOperationQueue.mainQueue().addOperationWithBlock
And also a combinations of these method, but I'm not able to perform the segue to the second view and stay in the second view.
Can anyone help?
Thanks and best,
Guido
I was able to solve this issue. The problem was the navigation controller.
My solution: the first view is not anymore embedded in a navigation controller, it just have a segue to a second view.
Then the second view is embedded in a navigation controller (along with others views) in order to have the navigation behaviour between views that I want.
Important is to use dispatch_async in order to "load" the navigation controller as soon as the user authenticates:
if success {
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("xxx", sender: self)
Without dispatch_async the second view appears but the navigation logic of the navigation controller is missing for around 15 seconds.
Related
I'm using a leanback BrowseFragment to implement a simple android tv app. I have two PageRows which are backed by custom fragments. When I switch between the two in the browse navigation area, the content side of the screen goes blank briefly before the new fragment's views appear. How can I fade from one view to the other without a delay in between?
I see some references to "entrance transition" in the docs which I think is what I need, but I can't find any examples of what to do in those callbacks.
https://developer.android.com/reference/android/support/v17/leanback/app/BrowseFragment.MainFragmentAdapter.html#setEntranceTransitionState(boolean)
I tried to implement setEntranceTransitionState on my PageRow Fragment's MainFragmentAdapter, but it is never invoked:
class GuideFragment: Fragment(), BrowseFragment.MainFragmentAdapterProvider {
val fragmentAdapter = object: BrowseFragment.MainFragmentAdapter<GuideFragment>(this) {
override fun setEntranceTransitionState(state: Boolean) {
Log.v("TEST", "setEntrance($state)")
fragment.setEntranceTransitionState(state)
}
}
override fun getMainFragmentAdapter() = fragmentAdapter
}
There is no way to do this when using BrowseSupportFragment.
If you look at the implementation of swapToMainFragment(), you'll see that while scrolling the content is set to an empty fragment. When SCROLL_STATE_IDLE is reached, a regular fragment transaction is used to replace the child fragment with the new content.
leanback has a lot of limitations, It is better to fork the official code and create your own repo and modify it; we did the same in our app.
I'm trying to solve a view placement bug that has arisen as of iOS 9. I am instantiating a view controller from a xib file (non-autolayout) and then pushing this onto my UINavigationController.
The problem is that when the view controller's viewWillAppear method is called, its frame has not yet been adjusted to the navigation controller's size and is still what was set in the xib file. It doesn't get set properly now until viewDidAppear.
This is completely screwing up my code. Does anyone know precisely what has changed that is causing this and what is the best way to handle it? I don't want to wait until viewDidAppear because this will look bad and make for a poor user experience.
I am also looking for the best fix.
My temporary one is to call the code that was in "viewDidAppear" in "viewDidLayoutSubviews". That way, my code will get called as soon as the frames are set.
But, make sure to add a boolean or something so that your code doesn't get called every time viewDidLayoutSubviews is called
-(void)viewDidLayoutSubviews{
if (didLayoutSubviews == NO){
didLayoutSubviews = YES;
// perform code that was in viewWillAppear
}
}
I occurred this issue too,
try to uncheck option "Resize View From NIB" from storyboard
Try moving the layout code from viewWillAppear to viewWillLayoutSubviews.
A little bit updated NickProvost's answer:
private var loadViewToken: dispatch_once_t = 0
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
dispatch_once(&loadViewToken) { [weak self] in
if let wSelf = self {
wSelf.setupView()
}
}
}
Lets say the first page in the app is the login page and then it takes me to do the main menu screen, is there a way to get rid of the back button in the main menu navigation bar, like get rid of the login page stack?
thank you
In Xamarin.Forms 1.3 and greater you can use
NavigationPage.SetHasBackButton(this, false);
In Xaml you can add:
<ContentPage ....NameSpaces etc....
NavigationPage.HasBackButton="False"
Title="MyPage">
</ContentPage>
You can avoid having the Back button if you replace the Navigation.PushAsync(page) to Navigation.PushModalAsync(page) in your login page's code. Post some code if this somehow doesn't apply
This has to do with how navigation works in the underlying OS (at least in iOS that's the case) - there is a Navigation Controller which serves for pages to transition between each other and have a trace of previous screen so the user can go back.
There are 2 ways to get rid of back button:
1) You can remove navigation bar from Xaml using Xamarin.Forms using below code
NavigationPage.SetHasNavigationBar (this, false);
Where this stands for current page / form instance.
2) Follow below mentioned steps
Navigate to login page when the app is loaded with Normal ContentPage instance of Login Page
Navigate to Main page from Login page using PushModalAsync and provide the main page instance as NavigationPage
And then from all the other pages, you can use PushAsync and it'll let you navigate to all the pages without any error.
Hope this helps!
By using CustomRenderer, you call this function in ViewWillAppear in your customized view controller
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
this.ParentViewController.NavigationItem.SetHidesBackButton (true, false);
//remember to use ParentViewController to reference to the NavigationViewController (if your contentPage is direct under a navigation controller. I don't know why but Xamarin must have a bug with SetHidesBackButton. If you call with this.NavigationItem.SetHidesBackButton(...), it should not work.
... other implements here ...
}
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
For some unknown reason I cannot push a view, I will try to explain the best I can but i have alot of complicated views going on, And it would be a nightmare to explain but say I have the following method.
-(void)showDetailView{
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
[self.navigationController pushViewController:detailView animated:YES];
[detailView release];
}
Which works and would push the detail view onto the stack, this is on my main view and my main thread.
So in the table view i have a cell with a Subview that then takes its view from another view controller. In that view controller I have more subviews, and say when a user clicks a subview a method is called. Which in turn will call this method on the mainView.
So one would believe that then a new view should get pushed. And the code runs, no errors occur but the view is not changed/switched.
I have tried various method of pushing a view inside the view controller that is it called from. and then just calling a method which is directly connected to the navigation controller to push the views.
A few things to add.
1. I have a IBAaction button that pushes a view (that works fine)
2. I assume its because im through so many views but I'm assuming that if you call push view controller it will push whatever view you pass it.
3. I have checked when the method is called from the main view self.navigationcontroller does not = null.
But if the navigation controller is called through the method call it = null.
So is there anyway to restore the null value of a navigation controller?
Im a little confused on why i cant simply call a method to push a view
Thanks
Its ok I have sorted it now
In terms of how i solved accessing the superior superview to my view is
An ID tag to the views superview which is the cell that my subview is in
id CellController = [self.view.superview.superview nextResponder];
[CellController performSelector:#selector(showDetailView:) withObject:Link];
Then calling a method in my cell which then in turn access its superview
id mainController = [self.view.superview.superview nextResponder];
[mainController performSelector:#selector(showDetailView:) withObject:Link];
Which then the main still retains its navigation controller and then in the show detail method in the main passes the link and pushes the new view.
Basically the total superview of a subview can be no higher then wherever it was created. So the subview in my cell could never access and run anything through my mainView properly, i could stuff but it never performed how it should be. So accessing its highest level superview and then getting that to access its superview as the cell is in my main view then I could run methods correctly.
Hope this makes sense only getting my head around it all.
Thanks to -> How does one access a super's view controller?
For the Id tag bit, not used Id in this way so another things learnt
I just had nearly the same problem today. If the navigation bar is hidden when you push a view, you may have a nil navigation controller. I resolve the problem like this :
self.navigationController.navigationBarHidden = NO; // So the navigation controller is not nil
[self.navigationController pushViewController:articleInfoController animated:YES];