Xamarin iOS - Refresh View coming back from another view - uiviewcontroller

I have a View 1 (UIViewController) which has a button to navigate to a new view - View 2 (UIViewController).
I would like to refresh View 1 when user clicks back button from View 2. UIViewController does not have ViewWillAppear to know the control is back on the view.
How to determine the control is passed on that view

You can override ViewDidAppear to detect that View 1 is visible again and refresh the view. Do not forget to call the base method too.
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear (animated);
//Refresh view here.
}

UIViewController does not have ViewWillAppear
You don't have the method ViewWillAppear on an UIViewController?
You could try to use the UINavigationControllerDelegate and specifically WillShowViewController

1)We can set it with a bool Value.
bool viewLoadedAgain = false;
2)Bool value gets 'true' when segue triggers:
public override void PrepareForSegue (UIStoryboardSegue segue, Foundation.NSObject sender)
{
base.PrepareForSegue (segue, sender);
if(segue.Identifier == "segueToSecondVC")
{
viewLoadedAgain = true;
}
}
3) Perform Refreshing ViewController View.
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
this.PerformSegue ("segueToSecondVC",this);
if(viewLoadedAgain == true)
{
//Use any code as per requirement
this.View.SetNeedsLayout ();
this.View.SetNeedsUpdateConstraints ();
this.View.ReloadInputViews ();
this.View.SetNeedsDisplay ();
}
}

Related

How to expand the view while zooming an image into ViewPager2

I was trying, with ViewPager2, to get default gallery-like experience of common Android SmartPhone, where you can zoom an image with pan and pinch controls along with the ability to navigate to another photo by swipe gestures.
I faced a problem in which when the zoomed image is swiped expecting it to get panned, instead of that, the ViewPager2 switched to another page.
ViewPager2 responds to the swipe event and causes page change and it doesn’t let zoomable view to respond to that event.
How do I solve the problem? Thanks.
The only solution I found is to use the old ViewPager with which it is possible to intercept events and if the photo is enlarged, it is possible to disable the page change and allow the management of the zoom.
First I defined a field, in a static class, to keep track of the state the photo is in:
public class Utilities {
....
static boolean isZoomed;
private Utilities () { }
static public void setIsZoomed (boolean z) {
isZoomed = z;
}
static public boolean getIsZoomed () {
return isZoomed;
}
....
}
Then in the custom class for managing the zoom I detect the status of the photo:
public class TouchImageView extends ImageView {
...
Utilities.setIsZoomed(normalizedScale != 1);
...
}
Finally, in the ViewPager custom class I disable or allow pagination based on the state of the photo:
public class CustomViewPager extends ViewPager {
public CustomViewPager (Context context) {
super(context);
}
public CustomViewPager (Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
try {
if (Utilities.getIsZoomed())
return false;
else
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException e) {
return false;
}
}
}

Unity, Calling a IEnumerator function from Button onClick

I tried to call a IEnumerator function from button click so I could yield return something, but I can't choose the function from the inspector's On Click() dropdown menu.
I tried to call the IEnumerator from another function and assign that function to the button, doesn't work!
And apparently I can't do yield return in a void function.
So could somebody please be so kind and teach me what should I do!?
Much appreciated!
There are a certain rules to hook a function to a unity event from the inspector.
1) The function must be public to be able to choose it from the inspector.
2) The return type must be void, so you won't be able to choose functions with any return type, and since your IEnumerator function returns an IEnumerator, you won't be able to choose it from the inspector.
3) The function parameters must match the event parameters unless the UnityEvent doesn't take any parameters like Button.onClick event (thanks #derHugo for correcting), for example the button onClick event doesn't take any parameters, so to choose a function for it from the inspector the function must look like
public void ChoosableTemplateForOnClickButton() { }
But you want to call an IEnumerator from the inspector, so what you can do is wrap it in a void function:
assuming your IEnumerator function looks like
public IEnumerator MyRoutine()
{
yield and enjoy...
}
wrap it in a void function:
public void RoutineWrap()
{
StartCoroutine(MyRoutine());
}
Now you can choose RoutineWrap from the inspector.
Alternative to this correct answer you can always also add the callback on runtime via script.
Still in Unity every Coroutine has to be started using StartCoroutine:
public Button button;
private void Awake()
{
button.onClick.AddListener(() => StartCoroutine(MyRoutine()));
}
private IEnumerator MyRoutine()
{
...
}

Best way to show a passcode screen everytime an app is launched/activated

I am working on a Windows Phone 8 App which should be protected with a passcode. What is the best way to show the passcode screen everytime the app is lauchend or activated?
I think the central point of action shoule be the App.xaml.cs with its Launch and Activation event handlers. But how exactly can I show the passcode screen?
The problem is, that one never know which pages will be displayed when the app launches or is reactivated. It is either the main page or any other page which was last displayed when the app was deactivated.
I tried to intercept the navigation to the first page, cancel it and show the passcode page instead:
// App.xaml.cs
private void InitializePhoneApplication() {
...
RootFrame.Navigating += HandleFirstNavigation;
...
}
private void HandleFirstNavigation(object sender, NavigatingCancelEventArgs e) {
RootFrame.Navigating -= HandleFirstNavigation;
e.Cancel = true;
RootFrame.Dispatcher.BeginInvoke(new Action(this.OpenPasscodePage));
}
private void OpenPasscodePage() {
RootFrame.Navigate(PasscodePageUri);
}
This works, but only when the app lauchend. When the app reactivated (dormant or tombstoned) the e.Cancel is irgnored. Although the navigation to the passcode page is called the original page is shown.
Moving the navigation the the passcode page from Navigating to Navigated does not worth either:
private void InitializePhoneApplication() {
...
RootFrame.Navigated += PasscodePageAfterFirstNavigation;
...
}
private void PasscodePageAfterFirstNavigation(object sender, EventArgs e) {
RootFrame.Navigated-= PasscodePageAfterFirstNavigation;
RootFrame.Navigate(PasscodePageUri);
}
This seems to be some kind of race condition: Sometimes the passcode page is shown, sometimes the original page. Even if the passcode pages comes up this looks bad because one first see the original page for the fraction of a second before the app navigates further to the passcode page.
Both solution do not work. Any idea what is the right way to implement this?
EDIT: Meanwhile I tried a third solution which does not work either. This solution uses the Uri Mapper:
App.xaml.cs
public bool PasscodeWasConfirmed; private void Application_Launching(object sender, LaunchingEventArgs e) {
...
PasscodeWasConfirmed = false;
...
}
private void Application_Activated(object sender, ActivatedEventArgs e) {
...
PasscodeWasConfirmed = false;
...
}
public Uri InitialPageUri;
public bool ShouldRedirectToPasscodePage(Uri uri) {
if (PasswordWasConfirmend == false) {
InitialPageUri = uri;
return true;
}
return false;
}
UriMapper
public class AppUriMapper : UriMapperBase {
public override Uri MapUri(Uri uri) {
App app = (Application.Current as App);
if (app != null) {
if (app.ShouldRedirectToPasscodePage(uri))
return PasscodeQueryPage.PageUri;
}
// default
return uri;
}
}
PasscodePage
public partial class PasscodePage : PhoneApplicationPage {
...
private void PasscodeConfirmed() {
App app = (Application.Current as App);
app.PasscodeWasConfirmed = true;
NavigationService.Navigate(app.InitialPageUri);
}
}
The Logic is working without any problem, but the app does not navigate to InitialPageUri after the passcode was confirmed. The Uri Mapper is called and correctly and returns the InitialPageUri (no redirect any more). But no navigation happens...
There are no errors, exceptions or debug output. simply nothing happes...
Biggest problem when using Uri Mapper:
When the app is reactivated from Dormant state there is no navigation which could be mapped or redirected...
(I've edited previous answer instead of adding a new one)
I've spend a little time trying to find a solution, and I don't see why your code doesn't run.
In my case it's enough if I do such a change in App.xaml:
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
App.RootFrame.Navigate(new Uri("/passPage.xaml", UriKind.RelativeOrAbsolute));
}
This works on my example which is under the link http://sdrv.ms/1ajH40E
But - I cannot prevent user from seeing last screen when he holds back buton and is chosing to which app return, and then for a blink he can see the last page before leaving the app. I don't know if it is possible to change this behaviour after clicking MS Button:
windows phone change deactivated app image
Second edit
Ok - maybe I've found solution why it sometiems work and sometimes not in your code. After pressing the Start or Search buton the App can go to two cases: Tombstone and non-tombsone. After return different events happen. Code above works with Tombstone case but not with non-tombstone. To work it with the second you need to add (because page is not initialized again) - (of course it can be different solution):
bool afterActivation = false;
private void Application_Activated(object sender, ActivatedEventArgs e)
{
afterActivation = true;
}
private void CheckForResetNavigation(object sender, NavigationEventArgs e)
{
// If the app has received a 'reset' navigation, then we need to check
// on the next navigation to see if the page stack should be reset
if (e.NavigationMode == NavigationMode.Reset)
RootFrame.Navigated += ClearBackStackAfterReset;
if (afterActivation)
{
afterActivation = false;
App.RootFrame.Navigate(new Uri("/passPage.xaml", UriKind.RelativeOrAbsolute));
}
}
Please also ensure of your debug properties in VS: Project->Properties->Debug->Tombstone upon deactiovation checkbox.
You can also find some information here (if you haven't seen it before):
http://blogs.msdn.com/b/ptorr/archive/2010/12/11/how-to-correctly-handle-application-deactivation-and-reactivation.aspx

WinRT How to check if the application was suspended?

I have done the LoadState and SaveState and all works fine.
I just want to check in the page's constructor if I came from suspension or not...
I can do a global bool variable and when I enter to the LoadState to change it's value:
bool suspended;
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
...
if (pageState != null)
{
suspended = true;
...
}
}
public MainPage()
{
this.InitializeComponent();
if (!suspended)
{
...
}
}
This works fine, but is there something build in? I think I can check it without global variable...
In App.xaml.cs OnLaunched(LaunchActivatedEventArgs args) event can provide you that details. You just have to pass args while navigating to particular page. args has property called PreviousExecutionState

How to refresh my UIVIewController using SetNeedsDisplay

I have a simple UIViewController (in monotouch), with a button on the UI. Now, my use case is simple - I want to reload the UIViewController whenever the button is clicked. On some threads i read that i just need to call SetNeedsDisplay for the UIView, but that doesn't seem to work for me. Here is my code snippet -
public partial class AbcScreen : UIViewController
{
....
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Declare and Add a button
Add(myBtn);
myBtn.TouchUpInside += (sender, ea) =>
{
Console.WriteLine("Touched the button");
View.SetNeedsDisplay();
};
}
}
I read some other threads, but nothing seems to help. Please help! Thanks!
Try with
this.ReloadInputViews();