Forum Xamarin.Forms

Bug in DisplayActionSheet, when user touches outside to cancel

MattCMattC CAMember, University
await DisplayActionSheet ("TEST ACTION SHEET", null, null, "Action A", "Action B");

Causes "index beyond bounds" exception when the user touches outside the popup area. Touching outside means cancel. To fix, provide a cancel text:

var userChoice = await DisplayActionSheet ("TEST ACTION SHEET", "Cancel", null, "Action A", "Action B");

But the "Cancel" text doesn't appear in the popup on iOS, which is fine, except I would prefer to test for null rather than userChoice=="Cancel".

(Also, it's not clear where bugs should be reported.)

Posts

  • RussellCollinghamRussellCollingham GBUniversity ✭✭

    bugs can be reported here https://bugzilla.xamarin.com/

  • CraigDunnCraigDunn USXamarin Team Xamurai

    @MattC which platform are you seeing the "Index beyond bounds" exception? And what version of Xamarin.Forms?

  • MattCMattC CAMember, University

    @CraigDunn‌ It is on iOS, 1.1.1.6206. Appearing in the simulator, and on the device. I updated the package just to be sure, and the behaviour is the same. Any idea why the Cancel button never appears, even if "Cancel" text is provided?

  • CraigDunnCraigDunn USXamarin Team Xamurai
    edited June 2014

    Weird, I asked because it appears for me (see attachment) using the exact line of code you posted (also using 1.1.1.6206)

    Also when I omit the "Cancel" it doesn't throw an exception either... but the user is forced to choose A or B (touching outside the action sheet doesn't dismiss it at all).

    Anything else special about your app - where you're calling it from? Are you working in XS or VS?

  • MattCMattC CAMember, University

    Yeah, it's odd. I'm using Xamarin Studio, latest beta. The action sheet shows up in the middle of the screen, rather than the bottom. "Destroy" is shown if I provide text for it, but never "Cancel". DisplayActionSheet is called from within an async delegate added as a Clicked handler for a Button, so nothing special I can think of.

    Here is the full stack trace I get when touching outside the action sheet, when the cancel text is null:

    MonoTouch.Foundation.MonoTouchException: Objective-C exception thrown.  Name: NSRangeException Reason: *** -[__NSArrayM objectAtIndex:]: index 4294967295 beyond bounds [0 .. 2]
      at at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:IntPtr_objc_msgSend_int (intptr,intptr,int)
      at MonoTouch.UIKit.UIActionSheet.ButtonTitle (Int32 index) [0x00008] in /Developer/MonoTouch/Source/monotouch/src/build/compat/UIKit/.pmcs-compat.UIActionSheet.g.cs:189
      at Xamarin.Forms.Platform.iOS.Platform+<>c__DisplayClassc.<.ctor>b__5 (System.Object o, MonoTouch.UIKit.UIButtonEventArgs args) [0x00000] in <filename unknown>:0
      at MonoTouch.UIKit.UIActionSheet+_UIActionSheetDelegate.Clicked (MonoTouch.UIKit.UIActionSheet actionSheet, Int32 buttonIndex) [0x00014] in /Developer/MonoTouch/Source/monotouch/src/build/compat/UIKit/.pmcs-compat.UIActionSheet.g.cs:500
      at at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
      at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/.pmcs-compat.UIApplication.cs:38
      at Net.TestApp.iOS.Application.Main (System.String[] args) [0x00008] in /Users/mattc/Dev/TestApp/TestApp.iOS/Main.cs:13
    
  • CraigDunnCraigDunn USXamarin Team Xamurai

    I'm on the alpha channel for Xamarin Studio and other updates, but otherwise I can't think of anything else different between our setups.

  • jakecox96jakecox96 USMember ✭✭

    I am having this exact problem on my app. Cancel button does not show on iOS, and clicking outside the action sheet causes this same exception. Using VS 2012 with Xamarin.Forms 1.2.2.6243.

    Were you able to resolve this issue?

  • CraigDunnCraigDunn USXamarin Team Xamurai

    @JakeLotpath‌ does the working with popups sample work for you?

    You'll need to share your code for us to be able to help any further.

  • jakecox96jakecox96 USMember ✭✭

    The working with popups sample runs, but the same problems occur. This is my code for what I am trying to achieve.

    var plans = new Dictionary<Guid, string>();
    var inspection = new ToolbarItem("New Inspection", null, async () =>
    {
    if (plans.Count == 0)
    {
    plans.Clear();
    var iPlans = ViewModel.InspectionPlans;
    foreach (var iPlan in iPlans)
    {
    plans.Add(iPlan.PlanId, iPlan.Name);
    }
    }
    var selectedPlan = await DisplayActionSheet("Select Inspection Plan", null, null, plans.Values.ToArray());
    if (selectedPlan == null) return;
    await Navigation.PushAsync(new NewInspection(plans.FindKeyByValue(selectedPlan)));
    });
    ToolbarItems.Add(inspection);

  • CraigDunnCraigDunn USXamarin Team Xamurai

    The working with popups sample runs, but the same problems occur.

    So you're saying that when you run our sample, clicking outside the action sheet crashes the app? Which platform/s?

    And out of curiosity, why are you not providing a Cancel option to the user in your action sheet?

  • jakecox96jakecox96 USMember ✭✭

    It is only on iOS simulator that it crashes the app. (Haven't tried a hard device)

    The plans list that I am dynamically creating at runtime, can be somewhat large (6 or more items), so I am trying to provide as much real estate on the phone as possible. Could the problem be related to setting 'Cancel' as null?

    But again, this only happens on iOS, it works fine without the 'Cancel' on Android.

  • CraigDunnCraigDunn USXamarin Team Xamurai

    I can't even reproduce it here - which iOS version are you testing on (iOS 7?).

  • jakecox96jakecox96 USMember ✭✭

    Yes, iOS 7.1.

    I'm just going to go with putting in the 'Cancel' argument and am checking for that or null upon before continuing on.

    var selectedPlan = await DisplayActionSheet("Select Inspection Plan", "Cancel", null, plans.Values.ToArray());
    if (selectedPlan == "Cancel" || selectedPlan == null) return;

    Thanks for your help.

  • DavidFergusonDavidFerguson USMember ✭✭
    edited June 2015

    @CraigDunn I am able to reproduce the missing cancel button using the sample application from the xamarin-forms-samples repo on github. It only happens when I run the simulator as an iPad. It shows fine when the simulator is ran as an iPhone. It doesn't crash, though.

    Is this expected behavior?

  • binkman71binkman71 USMember ✭✭

    @DavidFerguson

    From Apple documentation: "When presenting an action sheet on an iPad, there are times when you should not include a cancel button. If you are presenting just the action sheet, the system displays the action sheet inside a popover without using an animation. Because taps outside the popover dismiss the action sheet without selecting an item, this results in a default way to cancel the sheet. Including a cancel button would therefore only cause confusion."

  • DavidFergusonDavidFerguson USMember ✭✭

    @binkman71 Thanks. I thought that might be the case, but I wasn't sure.

  • satya.7655satya.7655 USMember

    how can i navigate to a particular page by choosing the action sheet options ?plz any one can help me with a sample code ......

  • DavidFergusonDavidFerguson USMember ✭✭

    @satya.7655 The way I do this is by checking the return of the action sheet and navigating to the appropriate page based on that.

    myButton.Clicked += async (sender, e) => {

            var action = await DisplayActionSheet(MenuTitle, CancelTitle, _viewModel.MyDeleteCommand.CanExecute(null) ? DeleteTitle : null, AvailableActionButtons.ToArray());
    
            switch (action)
            {
                case DeleteTitle:
                    _viewModel.MyDeleteCommand.Execute(null);
                    break;
    

    This is in my MainPage.xaml.cs file. I'm using MVVM Light, so I have my view model set up with commands which will perform the navigation.

  • Junior.4184Junior.4184 USMember ✭✭

    HI guys,

    I am still having this issue on android.

    var action = await App.Current.MainPage.DisplayActionSheet(t.SiteName + "\n" + t.AddressLine1, "Cancel", null, "Continue" , "Open");

    Assembly Xamarin.Forms.Core, Version=1.5.0.0,

    10-26 15:51:06.018 E/AndroidRuntime(30953): FATAL EXCEPTION: main
    10-26 15:51:06.018 E/AndroidRuntime(30953): Process: Opus_3.Opus_3, PID: 30953
    10-26 15:51:06.018 E/AndroidRuntime(30953): java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    10-26 15:51:06.018 E/AndroidRuntime(30953): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
    10-26 15:51:06.018 E/AndroidRuntime(30953): Caused by: java.lang.reflect.InvocationTargetException
    10-26 15:51:06.018 E/AndroidRuntime(30953): at java.lang.reflect.Method.invoke(Native Method)
    10-26 15:51:06.018 E/AndroidRuntime(30953): at java.lang.reflect.Method.invoke(Method.java:372)
    10-26 15:51:06.018 E/AndroidRuntime(30953): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
    10-26 15:51:06.018 E/AndroidRuntime(30953): ... 1 more
    10-26 15:51:06.018 E/AndroidRuntime(30953): Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
    10-26 15:51:06.018 E/AndroidRuntime(30953): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000b] in /Users/builder/data/lanes/2185/53fce373/source/mono/mcs/class/corlib/System.Runtime.ExceptionServices/ExceptionDispatchInfo.cs:61
    10-26 15:51:06.018 E/AndroidRuntime(30953): at System.Runtime.CompilerServices.AsyncMethodBuilderCore.m__0 (object) [0x00000] in /Users/builder/data/lanes/2185/53fce373/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1006
    10-26 15:51:06.018 E/AndroidRuntime(30953): at Android.App.SyncContext/c__AnonStorey0.<>m__0 () [0x00000] in /Users/builder/data/lanes/2185/53fce373/source/monodroid/src/Mono.Android/src/Android.App/SyncContext.cs:18
    10-26 15:51:06.018 E/AndroidRuntime(30953): at Java.Lang.Thread/RunnableImplementor.Run () [0x0000b] in /Users/builder/data/lanes/2185/53fce373/source/monodroid/src/Mono.Android/src/Java.Lang/Thread.cs:36
    10-26 15:51:06.018 E/AndroidRuntime(30953): at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) [0x00009] in /Users/builder/data/lanes/2185/53fce373/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Java.Lang.IRunnable.cs:71
    10-26 15:51:06.018 E/AndroidRuntime(30953): at (wrapper dynamic-method) object.5852cedf-083a-4aa5-baf3-542f1eecac48 (intptr,intptr)

  • Junior.4184Junior.4184 USMember ✭✭

    Hi Guys,

    I got it working by adding the IF statement to check whther the result is null or not

     var action = await App.Current.MainPage.DisplayActionSheet(t.SiteName + "\n" + t.AddressLine1, "Cancel", null,  "Continue" , "Open");
    
    
     if (action != null)
                            {
        //Do something
        }
        else
    {
        //do nothing when user touches outside to cancel
        } 
    
  • SatyaRamAntharvediSatyaRamAntharvedi USMember
    edited November 2016

    just add try catch... for outside touch

    try{
    actonsheet code
    }
    catch(Exception exp)
    {
    return;
    }

  • rio_riyario_riya INMember ✭✭

    Anyone please tell me, how to dismiss this DisplayActionSheet popup before its open the next page or next popup.
    quick please, all suggest

  • HarshitaHarshita INMember ✭✭✭✭

    How to use Display Action Sheet,Here is full guide:

Sign In or Register to comment.