2
votes

I am trying to work out how to show the "up" arrow in Xamarin.Forms without a pushing a page onto the stack. I.E. I just want to perform an action when the back button is pressed. I am completely stuck on this so any help would be appreciated.

I have tried creating a custom renderer which handles a view property called DisplayHomeAsBack. Which in the renderer calls the following:

FormsAppCompatActivity context = ((FormsAppCompatActivity)Forms.Context);
Android.Support.V7.App.ActionBar actionBar = context.SupportActionBar;
if (actionBar != null)
{
  actionBar.SetDisplayHomeAsUpEnabled(element.DisplayHomeAsBack);
}

Unfortunately it seems this does absolutely nothing, even though all online tutorials and stackoverflow question for android suggest this method.

The plan is that I can then use the "OnBackButtonPressed" override in MasterDetailPage, which should allow me to perform this action. Unfortunately displaying the back button has been the larger hurdle so far!

Any idea of a better way to do this or how I can get the current mechanism to work?

EDIT

I have created a project and uploaded it to this question on the Xamarin support forums, if it helps. http://forums.xamarin.com/discussion/comment/186330#Comment_186330

2
I think it will depend on where you are trying to override the back button icon. Sounds like you are trying to override the back button icon on a MasterDetailPage which I assume is in a NavigationPage? Also, is this MasterDetailPage the first page in the navigation stack or do you have to click through other pages to get to it? Finally, you just want to change the action that is performed when you click it as opposed to changing what the button actually looks like correct?hvaughan3
I guess I am just using statics (in the above code), so I didn't think it mattered, but I may have missed something. You are correct, I have a MasterDetailPage, which has a NavigationPage as its detail. The MasterDetailPage is the main page of the application. To give you an idea of what I am trying to do, I bring up an internal view, and I want the view to disappear with the press of a back button (so icon and behaviour need to change). I am happy to do this any other way if it works.Blueberry
Have you tried overriding OnOptionItemsSelected in MainActivity? You could figure out which menu item Id to check for, then use the MessagingCenter to signal that it is time to do your custom action and return false in OnOptionItemsSelected to signify that you are handling it yourself. If that does not work then you may have to override the default back button and implement your own.hvaughan3
But that won't change the icon to a back?Blueberry
Ok so you do want to change the way the icon looks. Then I think you will need to override OnCreateOptionsMenu to change the way the icon looks as well as acts when clicked. When I have a chance I can post an answer with what my OnCreateOptionsMenu looks like though, I am adding a custom icon and not just trying to re-add the arrow so it might be a little different. I guess you could also just push a new page onto the screen but it would look the exact same only it had your custom view showing... then you would get the back button and it would functionhvaughan3

2 Answers

1
votes

Sorry to keep you waiting so long!

Warning that I did not actually run this code and changed it from my own so I would be surprised if it worked perfectly without some changes.

So below should add a back button where there was not one before (so like when there is not really a page to go back to) and then we will add a custom action to perform when it gets pressed.

I would suggest you push a new page onto the stack without using animation so it is transparent to the user and also makes all of this much simpler, but if you absolutely do not want to do that, the below method should work.

MainActivity:

//Use this to subscribe to the event which will create the back button
public override bool OnCreateOptionsMenu(IMenu menu) {

    if(menu != null && App.AppMasterPage != null) { //You will need this to make sure you are on your MasterDetailPage, just store a global reference to it in the App class or where ever

        Xamarin.Forms.MessagingCenter.Unsubscribe<string>(this, "CreateBackButton");
        Xamarin.Forms.MessagingCenter.Subscribe<string>(this, "CreateBackButton", stringWeWillNotUse => { //Use this to subscribe to the event that creates the back button, then when you want the back button to show you just run Xamarin.Forms.MessagingCenter.Send<string>(this, "CreateBackButton")

            ActionBar.DisplayOptions = ActionBarDisplayOptions.ShowTitle | ActionBarDisplayOptions.ShowHome | ActionBarDisplayOptions.UseLogo | ActionBarDisplayOptions.HomeAsUp; //You may need to play with these options to get it working but the important one is 'HomeAsUp' which should add the back button
        });
    } else {
        Xamarin.Forms.MessagingCenter.Unsubscribe<string>(this, "CreateBackButton");
    }

    return base.OnCreateOptionsMenu(menu);
}

Now the next step is do do a custom action when it is pressed. I think you can either override OnBackPressed() or OnOptionsItemSelected() in MainActivity or maybe you can override the MasterDetailPage method. I am not sure.

Which ever one works for you, inside of that override, I would simply check to see if you are on your App.AppMasterPage like we did above, and if so, send a MessagingCenter message which your App.AppMasterPage has already subscribed to in order for it to handle the custom action.

If you get stuck let me know!

0
votes

I know it sounds like a bit of a hack, but the best "solution" I have found so far is to add a page behind the current page (behind the root) so it is not visible. Then when the user presses the back button, handle it by removing that page.