2017-05-28 43 views
10

Mam problem związany z obiektem TaskCompletionSource i funkcją Dismiss alertu. Problem ten nie występuje w wersji IOS aplikacjiTaskCompletionSource i dismiss powoduje, że wiele niestandardowych alertów nie pojawia się

Gdy aplikacja wysyła powiadomienie, dwa alarmy z funkcją pracy pojawi się, gdy użytkownik uruchamia aplikację:

  1. Authentication
  2. Wypełnianie wartość.

Jednakże, kiedy wchodzę do aplikacji, widzę tylko uwierzytelnianie (ponieważ ten alarm jest wywoływany jako pierwszy w aplikacji), a drugi alert nigdy się nie wyświetla. Próbowałem już przesłonić funkcję Dismiss i ustawić wynik obiektu TaskCompletionSource na wartość null, ale powoduje to pojawienie się tego samego alertu X razy, zanim aplikacja ulegnie awarii. Czy istnieje sposób powtarzania obiektu TaskCompletionSource, aby wyświetlić wszystkie alerty? Lub jakie modyfikacje muszę wykonać w funkcji Odrzuć, aby po zakończeniu wyświetlania wszystkich alertów zadanie TaskCompletionSource zostało zakończone?

Android Fragment Przykład Kod:

public static readonly int AlertWidth = Device.Idiom == TargetIdiom.Phone ? 270 : 320; 

    class AlertDialogFragment : DialogFragment 
    { 
     public string Title; 
     public string Body; 
     public View Content; 
     public List<AlertButton> Buttons; 
     public TaskCompletionSource<object> tsc; 


     public Dialog AndroidCustomAlert(Activity activ) 
     { 
      Android.Views.LayoutInflater inflater = Android.Views.LayoutInflater.From(activ); 
      Android.Views.View view = inflater.Inflate(Resource.Layout.AlertDialogLayout, null); 

      AlertDialog.Builder builder = new AlertDialog.Builder(activ); 
      builder.SetView(view); 
      Android.Widget.TextView title = view.FindViewById<Android.Widget.TextView>(Resource.Id.Login); 
      title.Text = Title; 

      Android.Widget.TextView body = view.FindViewById<Android.Widget.TextView>(Resource.Id.pincodeText); 
      body.Text = Body; 
      body.MovementMethod = new Android.Text.Method.ScrollingMovementMethod(); 

      Android.Widget.EditText pincode = view.FindViewById<Android.Widget.EditText>(Resource.Id.pincodeEditText); 
      Android.Widget.Button btnPositive = view.FindViewById<Android.Widget.Button>(Resource.Id.btnLoginLL); 
      Android.Widget.Button btnNegative = view.FindViewById<Android.Widget.Button>(Resource.Id.btnClearLL); 
      Android.Widget.Button btnNeutral = view.FindViewById<Android.Widget.Button>(Resource.Id.btnNeutral); 

      if (Title.Contains("Time")) 
      { 
       Android.Views.View secondView = inflater.Inflate(Resource.Layout.TimePickerLayout, null); 
       builder.SetView(secondView); 

       btnPositive = secondView.FindViewById<Android.Widget.Button>(Resource.Id.btnLoginLL); 
       btnNegative = secondView.FindViewById<Android.Widget.Button>(Resource.Id.btnClearLL); 
       var tp = secondView.FindViewById<Android.Widget.TimePicker>(Resource.Id.timePicker1); 
       tp.SetIs24HourView((Java.Lang.Boolean)true); 
       //Positive button feedback 
       btnPositive.Text = Buttons.Last().Text; 
       btnPositive.Click += delegate 
       { 
        var car = (Xamarin.Forms.TimePicker)Content; 
        var ts = new TimeSpan(tp.Hour, tp.Minute, 0); 
        car.Time = ts; 

        CommandsForButtons(Buttons.Last()); 
       }; 

       //Negative button feedback 
       btnNegative.Text = Buttons.First().Text; 
       btnNegative.Click += delegate 
       { 

        CommandsForButtons(Buttons.First()); 
       }; 
      } 
      else if (Title.Contains("How are you")) 
      { 
       btnPositive.Visibility = Android.Views.ViewStates.Gone; 
       btnNegative.Visibility = Android.Views.ViewStates.Gone; 
       btnNeutral.Visibility = Android.Views.ViewStates.Visible; 
       pincode.Visibility = Android.Views.ViewStates.Gone; 

       var happySlider = view.FindViewById<Android.Widget.SeekBar>(Resource.Id.happinessSlider); 
       happySlider.SetProgress(5, false); 
       happySlider.Visibility = Android.Views.ViewStates.Visible; 
       btnNeutral.Text = Buttons.First().Text; 
       btnNeutral.Click += delegate 
       { 
        var car = (StackLayout)Content; 

        var layoutView = (Xamarin.Forms.AbsoluteLayout)car.Children[1]; 
        var slider = (Slider)layoutView.Children[1]; 

        var totalHappyValue = happySlider.Progress/10; 
        slider.Value = totalHappyValue; 

        CommandsForButtons(Buttons.First()); 
       }; 
      } 
      else 
      { 

       //Checks if there are no buttons, and if there aren't any, creates a neutral one 
       if (Buttons == null || Buttons.Count == 0) 
       { 
        btnPositive.Visibility = Android.Views.ViewStates.Gone; 
        btnNegative.Visibility = Android.Views.ViewStates.Gone; 
        btnNeutral.Visibility = Android.Views.ViewStates.Visible; 
        pincode.Visibility = Android.Views.ViewStates.Gone; 

        Buttons = new List<AlertButton> { 
       new AlertButton { 
        Text = "Oké", 
        IsPreferred = true, 
        Action =() => false 
        } 
       }; 
        btnNeutral.Text = Buttons.First().Text; 
        btnNeutral.Click += delegate 
        { 

         CommandsForButtons(Buttons.First()); 
        }; 
       } 

       if (Content == null) 
       { 
        pincode.Visibility = Android.Views.ViewStates.Gone; 
       } 

       //Positive button feedback 
       btnPositive.Text = Buttons.Last().Text; 
       btnPositive.Click += delegate 
       { 
        var test = (StackLayout)Content; 

        if (test != null) 
        { 
         var car = (Entry)test.Children[0]; 
         car.Text = pincode.Text; 
        } 

        CommandsForButtons(Buttons.Last()); 
       }; 

       //Negative button feedback 
       btnNegative.Text = Buttons.First().Text; 
       btnNegative.Click += delegate 
       { 

        CommandsForButtons(Buttons.First()); 
       }; 
      } 
      return builder.Create(); 
     } 

     public void CommandsForButtons(AlertButton button) 
     { 
      Func<Task> dismiss = null; 
      var command = new Command(async() => 
      { 
       var ab = button; 
       var cont = true; 
       if (ab.Action != null) 
        cont = ab.Action(); 
       if (ab.ActionAsync != null) 
       { 
        cont = cont && await ab.ActionAsync(); 
       } 
       if (!cont) 
       { 
        await dismiss(); 
       } 
      }); 

      dismiss = async() => 
      { 
       dismiss = async() => { }; 
       await Task.Run(() => 
       { 
        Dismiss(); 
        tsc.SetResult(null); 
       }); 

       Log.Debug("TSC", tsc.Task.Status.ToString()); 

      }; 

      command.Execute(this); 
     } 

     public override Dialog OnCreateDialog(Bundle savedInstanceState) 
     { 
      var test = AndroidCustomAlert(Activity); 
      test.SetCanceledOnTouchOutside(false); 
      return test; 
     } 

     public override void Dismiss() 
     { 
      base.Dismiss(); 

     } 
    } 

    public async Task Show(string title, string body, View content, List<AlertButton> buttons) 
    { 

     var tcs = new TaskCompletionSource<object>(); 

     var adf = new AlertDialogFragment 
     { 
      Title = title, 
      Body = body, 
      Content = content, 
      Buttons = buttons, 
      tsc = tcs 
     }; 
     var FragmentManager = ((Activity)Forms.Context).FragmentManager; 
     FragmentTransaction ft = FragmentManager.BeginTransaction(); 

     //Remove fragment else it will crash as it is already added to backstack 
     Fragment prev = FragmentManager.FindFragmentByTag("alert"); 
     if (prev != null) 
     { 
      ft.Remove(prev); 
     } 

     ft.AddToBackStack(null); 
     adf.Show(ft, "alert"); 
     await tcs.Task; 
    } 

Metody:

await Authentication(); 
await UserCheck(); 

i kod IOS:

public static readonly int AlertWidth = Device.Idiom == TargetIdiom.Phone ? 270 : 320; 

    public async Task Show(string title, string body, View content, List<AlertButton> buttons) 
    { 
     if (buttons == null || buttons.Count == 0) 
     { 
      buttons = new List<AlertButton> { 
       new AlertButton { 
        Text = "Oké", 
        IsPreferred = true, 
        Action =() => false 
       } 
      }; 
     } 

     Func<Task> dismiss = null; 

     var captionSize = (double)StyleKit.PhoneDarkLabelStyles.Caption.Setters.First(s => s.Property == Label.FontSizeProperty).Value; 
     var titleSize = (double)StyleKit.PhoneDarkLabelStyles.Title.Setters.First(s => s.Property == Label.FontSizeProperty).Value; 

     var top = new StackLayout { 
      Padding = new Thickness(15, 20, 15, 20), 
      Spacing = 3, 
      Children = { 
       new Label { 
        Text = title, 
        Style = StyleKit.PhoneDarkLabelStyles.Title, 
        FontSize = Math.Max(16, titleSize), 
        HorizontalTextAlignment = TextAlignment.Center 
       }, 
       new Label { 
        Text = body, 
        Style = StyleKit.PhoneDarkLabelStyles.Body, 
        //FontSize = , 
        FontSize = Math.Max(14, captionSize), 
        HorizontalTextAlignment = TextAlignment.Center 
       } , 
       new ContentView { 
        Padding = new Thickness(0,5,0,-10), 
        VerticalOptions = LayoutOptions.EndAndExpand, 
        Content = content 
       } 
      } 
     }; 

     var buttonViews = buttons.Select(ab => new Button { 
      FontSize = Math.Max(16, titleSize), 
      Text = ab.Text, 
      FontAttributes = ab.IsPreferred ? FontAttributes.Bold : FontAttributes.None, 
      TextColor = ab.IsDestructive ? Color.Red : Color.Default, 
      Command = new Command(async() => { 
       var cont = true; 
       if (ab.Action != null) 
        cont = ab.Action(); 
       if (ab.ActionAsync != null) 
        cont = cont && await ab.ActionAsync(); 
       if (!cont) 
        await dismiss(); 
      }) 
     }).ToList(); 

     var grid = new Grid { 
      RowDefinitions = { 
       new RowDefinition { Height = GridLength.Auto }, 
       new RowDefinition { Height = GridLength.Auto } 
      }, 
      ColumnSpacing = 0, 
      RowSpacing = 0 
     }; 
     buttons.ForEach(button => { 
      grid.ColumnDefinitions.Add(
       new ColumnDefinition { 
        Width = AlertWidth/buttonViews.Count 
       } 
      ); 
     }); 

     for (int i = 0; i < buttonViews.Count; i++) 
     { 
      grid.Children.Add(new BorderView { 
       BorderColor = Color.FromRgba(0,0,0,0.2), 
       Thickness = new Thickness(0, 1, (i + 1 < buttonViews.Count) ? 1 : 0, 0) 
      }, i, 1); 
      grid.Children.Add(buttonViews[i], i, 1); 
     } 
     grid.Children.Add(top, 0, buttons.Count, 0, 1); 

     var box = new Frame { 
      WidthRequest = AlertWidth, 
      BackgroundColor = Color.FromRgba(1,1,1,0.96), 
      Padding = 0, 
      Content = grid 
     }; 
     var outer = new AbsoluteLayout { 
      BackgroundColor = Color.FromRgba(0,0,0,0.65), 
      Opacity = 0, 
      Children = { box } 
     }; 
     AbsoluteLayout.SetLayoutFlags(box, AbsoluteLayoutFlags.PositionProportional); 
     AbsoluteLayout.SetLayoutBounds(box, 
      new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize)); 

     var page = new ContentPage { 
      Content = /* new ScrollView { Content = */ outer // } 
     }; 

     var tcs = new TaskCompletionSource<object>(); 

     var topVC = UIApplication.SharedApplication.KeyWindow.RootViewController; 
     while (topVC.PresentedViewController != null) { 
      topVC = topVC.PresentedViewController; 
     } 

     var vc = page.CreateViewController(); 
     topVC.Add(vc.View); 
     var innerView = vc.View.Subviews[0].Subviews[0]; 
     vc.View.RemoveFromSuperview(); 

     dismiss = async() => { 
      dismiss = async() => {}; 
      await outer.FadeTo(0, 50); 
      innerView.RemoveFromSuperview(); 
      tcs.SetResult(null); 
     }; 

     topVC.Add(innerView); 

     var kbh = new KeyboardHelper(); 
     kbh.KeyboardChanged += async (sender, e) => { 
      await box.TranslateTo(0, e.Visible ? (-e.Height/2f) : 0, 100, Easing.CubicInOut); 
     }; 

     await outer.FadeTo(1, 100); 

     await tcs.Task; 
    } 

Odpowiedz

1

To wygląda jak i/lub błąd pomiędzy gwintem lub po prostu nie ustawianie zakończenia zadania.

W wersji IOS masz

 dismiss = async() => { 
     dismiss = async() => {}; 
     await outer.FadeTo(0, 50); 
     innerView.RemoveFromSuperview(); 
     tcs.SetResult(null); 
    }; 

Nie ma dopasowanie tcs.SetResult(null); oświadczenie w wersji Androida.

Należy również zwrócić uwagę na wywołanie asynchroniczne, ponieważ oczekiwanie na wywołanie funkcji SetResult spowoduje zablokowanie głównego wątku bez niego.

+0

Więc zaktualizowałem swój post z Twoimi sugestiami. Dobrą wiadomością jest to, że powiadomienia pojawiają się po powiadomieniach! Jednak alerty pojawiają się dwa razy (np. Pierwsze uwierzytelnienie, następnie suwak i powtórzenie). Czy znasz sposób na rozwiązanie tego problemu. Dzięki za pomoc! –

+0

Czy możesz udostępnić bieżący kod? – CCondron

+0

Już zredagowałem moje pytanie z bieżącym kodem, czy to masz na myśli? –