Intereting Posts
Android Gradle: динамическое изменение имени версии во время сборки Рисование маршрутов между несколькими точками на карте Задание таймера VS Использование диспетчера Alarm Manager в службе Android Метод удаления андроида волейбола, почему будет отправлять пустые параметры Правильный способ реализации onMeasure () и onLayout () в пользовательском AdapterView Изображение появляется при наклоне 90 градусов при загрузке с сервера на Android? Отключить кнопку меню? Как провести синтаксический анализ даты 2013-03-13T20: 59: 31 + 0000 Проект Phonegap cordova android «уже существует» или ошибка времени выполнения Как импортировать проект Android Studio из Git Используйте KeyPairGeneratorSpec для уровня API Android <18? Делает ли журнал замедлением производственное приложение для Android? Как распечатать журнал в файле android c ++? Отображение общего числа в виде текста для нескольких контактов с одним выводом в том же месте на карте в android Использование редактора общих настроек

TaskCompletionSource и отклонение причин, по которым не отображаются несколько настраиваемых alertdialogs

У меня возникла проблема, связанная с объектом TaskCompletionSource и функцией Dismiss предупреждения. Эта проблема не появляется в версии приложения IOS приложения

Когда приложение отправляет уведомление, два предупреждения с рабочей функциональностью будут отображаться, когда пользователь активирует приложение:

  1. Аутентификация
  2. Заполнение значения.

Однако, когда я вхожу в приложение, я получаю только проверку подлинности (потому что это предупреждение вызывается первым в приложении), и второе предупреждение никогда не появляется. Я уже пытался переопределить функцию Dismiss и установить для объекта ObjectCompletionSource значение null, но это заставляет одно и то же предупреждение появляться X раз до того, как приложение сработает. Есть ли способ повторить объект TaskCompletionSource, чтобы я мог видеть все предупреждения? Или какие модификации мне нужно сделать для функции Dismiss, чтобы объект TaskCompletion был завершен после отображения всех предупреждений?

Пример кода Android Fragment:

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; } 

Методы:

 await Authentication(); await UserCheck(); 

И код 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; } 

Solutions Collecting From Web of "TaskCompletionSource и отклонение причин, по которым не отображаются несколько настраиваемых alertdialogs"

Это похоже на проблему и / или проблему между потоками или просто не задание завершения задачи.

В версии IOS у вас есть

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

Не существует соответствующего tcs.SetResult(null); В версии для Android.

Также следует отметить асинхронный вызов, так как ожидание вызова SetResult будет блокировать основной поток без него.