Android Menu and Back Button not working

MJoehlMJoehl USMember ✭✭

Hi

I have an Xamarin.Forms project targeting Android, iOS and UWP.
In my Android-App, the hardware backbuttons of my phone are not working (back button and also the menu button).

Why is that? Did I forgot something?

Thanks

Answers

  • coolrjmcoolrjm INMember ✭✭✭

    What type of application are you creating. Is it a navigation application with multiple pages. Or is it a single page application. By default the hardware buttons are supposed to work as expected unless you write code to disable the functionality.

  • 15mgm1515mgm15 USMember ✭✭✭✭

    The back button should be working if you are using a NavigationPage on your project, the menu button does not do anything till you code something in it's event.

  • MJoehlMJoehl USMember ✭✭

    @15mgm15 said:
    The back button should be working if you are using a NavigationPage on your project, the menu button does not do anything till you code something in it's event.

    You're right... I found out, that the backbutton works as it should. But I detected a really strange behavior:
    When I go to my detailpage I can navigate back with my backbutton. But when I first press the menu-button (I have nothing special declared) then the backbutton also won't work anymore...

  • 15mgm1515mgm15 USMember ✭✭✭✭
    edited May 2016

    @MichaelJhl If you are using a ContentPage you can override this method:

    protected override bool OnBackButtonPressed()
    {
        return base.OnBackButtonPressed();
    }
    

    And then you can debug if this method is being called after you are pressing the Menu button, and if it is not the correct behaviour you can go native and inside your MainActivity of you Android project you can use this method:

    public override void OnBackPressed()
    {
        if (ImInMainPage)
        {
            Finish();
        }
        else
        {
            base.OnBackPressed();
        }
    
    }
    

    Hope this helps.

  • MJoehlMJoehl USMember ✭✭

    @15mgm15 No luck with this... both of the methods are not called when I first pressed the hardware-menu-button. I discovered that the material-theme can be the problem. In a newly created (empty) project without material theme, the menu button (and also the back-button) work as excpected.

    Also strange: In fact, the overflow-menu-button (3-dotted-icon) should only appear, when the device has no hardware-menu-button, but in my case -> it appears everytime.

    Also the Activity-Indicator didn't show up when I set IsBusy to true. But without the Material Theme, it Shows up (no oterh changes).

    Whats happen here? Maybe a bug?

  • 15mgm1515mgm15 USMember ✭✭✭✭

    @MichaelJhl it may be a bug! have you try with different Xamarin.Forms versions and different (previous) AppCompat v7 - v4 nuget packages? Have you tried real devices? Have you tried different emulators and Android version? Maybe this can help you to figure this out.

  • EddieMEddieM USMember ✭✭
    edited August 23

    I am on Forms version 2.3.4. Here is what I found out about this issue. Many seem to have this issue when using the FormsAppCompatActivity. I ran into this issue because my software back button was not working and I wanted to capture the back button click within OnOptionsItemSelected(https://stackoverflow.com/questions/30657344/how-to-handle-cancel-back-navigation-in-xamarin-forms). However, OnOptionsItemSelected was never called. For most of this comment I will be referencing the link at the bottom. In the link in Comment 2 is what you need to add to your MainActivity.cs file. However, your tool bar needs to be of type Android.Support.V7.Widget.Toolbar

    Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
    SetSupportActionBar(toolbar);
    

    Also, you need to check your layout file to be sure it is correct. If you are using the default then then should be in [ProjectName]/Resources/layout/Toolbar.axml. You don't have to use the same styling just make sure the element name is android.support.v7.widget.Toolbar and that the android:id matches the one you will be referencing from your OnCreate

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    

    Now in the link look at Comment 6. I had this same issue. Basically my toolbar was null and I would get an exception when going to any page that would show the software back button. The poster mentioned adding the code within the OnPostCreate function. However, I read somewhere else(Sorry can't find source). That it should go in the OnResume just to be safe and to be sure it is set.When I discuss the last issue it will make sense why OnResume would work better. Anyway, here is my OnResume function. Notice the null checking. We only want to set it if it is not null.

    protected override void OnResume() {
        base.OnResume();
    
        Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
        if (toolbar != null) {
            SetSupportActionBar(toolbar);
        }
    }
    

    Now with that code in place the issue was not solved for me. OnOptionsItemSelected was still not getting triggered on software back press. Look at Comment 11 in the link. What jerone said led me to think. In our application we are changing the MainPage a few times. Without looking at the code maybe the toolbar is tied directly to the stack. So here is the next thing I tried. For the sake of getting a working example together quickly I used the MessagingCenter. Someone else reading this may have a more efficient way of doing this. If so please post. So with that said I added to the bottom of my OnCreate function. Just after my attempt at setting the tool bar.

    MessagingCenter.Subscribe<object, bool>(this, "ReloadToolbar", (sender, reload) => {
        if (reload) {
            ReloadToolbar();
        }
    });
    

    Then inside of my MainActivity.cs I added this function.

    private void ReloadToolbar() {
        Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
        if (toolbar != null) {
            SetSupportActionBar(toolbar);
        }
    }
    

    Now after every call within my application where I would be setting MainPage to another object(page). I add my send call.

    MainPage = new NavigationPage(new SomePage());
    MessagingCenter.Send<object, bool>(this, "ReloadToolbar", true);
    

    My assumption was correct. After all of that. Now pressing the software back button will trigger the OnOptionsItemSelected. Hope, this helps.

    https://bugzilla.xamarin.com/show_bug.cgi?id=38189

  • EddieMEddieM USMember ✭✭

    Had one more issue here. Back is triggered but now when I am on my root detail page the hamburger menu send the itemId for back pressed. So it now too goes back instead of opening the menu.

  • MdNaushadMdNaushad INMember ✭✭

    @EddieM - I did the same as you suggested.
    But I am seeing two toolbars now. Any Idea how to avoid that?

  • ExLuzZziVoExLuzZziVo Member ✭✭
    edited October 19

    I have found the solution for this problem.
    1) There is no need for

    Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
    SetSupportActionBar(toolbar);
    

    in activity OnCreate method.
    2) Add this class, that iterates through your activity views and finds an object of type you like(we will need Android.Support.V7.Widget.Toolbar)

    public class IterateView
    {
            private readonly Android.Views.View _rootView;
            public IterateView(Activity activity)
            {
                _rootView = activity.Window.DecorView.FindViewById(Android.Resource.Id.Content);
            }
    
            public T GetView<T>() where T : class
            {
                return IterateViewChildren<T>(_rootView);
            }
    
            private static T IterateViewChildren<T>(Android.Views.View view) where T : class
            {
                if (view is ViewGroup vGroup)
                    {
                        for (var i = 0; i < vGroup.ChildCount; i++)
                        {
                            var vChild = vGroup.GetChildAt(i);
                                if (vChild is T)
                                {
                                    return vChild as T;
                                }
                                var foundChild = IterateViewChildren<T>(vChild);
                                if (foundChild != null)
                                    return foundChild;
                        }
                    }
                    return default(T);
            }
    }
    

    3) Modify @EddieM 's ReloadToolbar() like this

    if(!subscribed)
    {
        var tb = new IterateView(YourActivity).GetView<Android.Support.V7.Widget.Toolbar>();
        if (tb != null)
        {
            tb.NavigationClick += ((o, args) =>
            {
            //Do something on Back Button pressed
            });
            subscribed=true;
        }
    }
    

    4) ...
    5) Profit!

  • EddieMEddieM USMember ✭✭

    @ExLuzZziVo Haha I like to profit. Thanks. I will try this out later and let you know.

  • ExLuzZziVoExLuzZziVo Member ✭✭
    @EddieM My main problem was that

    Android.Support.V7.Widget.Toolbar toolbar = FindViewById(Resource.Id.toolbar);

    was always null wherever I was trying to access it. So I have found the way of alternative access to this toolbar.
Sign In or Register to comment.