【问题标题】:DisplayAlert With changing Text xamarin formsDisplayAlert 更改文本 xamarin 表单
【发布时间】:2017-09-20 13:10:44
【问题描述】:

我有一个要求,我必须在 DisplayAlert 上显示下载状态。但是要异步更改文本。

如何做到这一点?

  DisplayAlert("Download Info", "Downloading.....", "Ok");

我想显示状态...

  • 已连接到服务器
  • 正在下载
  • 下载完成

【问题讨论】:

  • 您可能需要编写自己的自定义 DisplayAlert 才能做到这一点

标签: xamarin xamarin.ios xamarin.forms


【解决方案1】:

这是一个简单的“动态警报”,用于表单和 iOS,使用 UIAlertControllerAndroid,使用 DialogFragmentXamarin.Forms 依赖服务:

依赖接口:

public interface IDynamicAlert
{
    void Show(string title, string message);
    void Update(string message);
    void Dismiss();
}

iOS IDynamicAlert 依赖实现:

public class DynamicAlert : IDynamicAlert
{
    UIAlertController alert;

    public void Show(string title, string message)
    {
        if (alert != null) throw new Exception("DynamicAlert already showing");
        alert = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);
        var rootVC = UIApplication.SharedApplication.Windows[0].RootViewController;
        rootVC.PresentViewController(alert, true, () =>
        {
        });
    }

    public void Update(string message)
    {
        if (alert == null) throw new Exception("DynamicAlert is not showing, call Show first");
        alert.Message = message;
    }

    public void Dismiss()
    {
        if (alert == null) throw new Exception("DynamicAlert is not showing, call Show first");
        alert.DismissViewController(true, () =>
        {
            alert.Dispose();
            alert = null;
        });
    }
}

示例用法:

var alert = DependencyService.Get<IDynamicAlert>();
if (alert != null)
{
    alert.Show("StackOverflow", "Starting your request...");
    await Task.Delay(2000); // Do some work...
    alert.Update("Your request is processing...");
    await Task.Delay(2000); // Do some work...
    alert.Update("Your request is complete...");
    await Task.Delay(750);
    alert.Dismiss();
}
else
{
    throw new Exception("IDynamicAlert Dependency not found");
}

输出:

安卓版本:

android 版本由几个部分组成,一个DialogFragment 子类和一个使用自定义DialogFragmentIDynamicAlert 实现。

Android DialogFragment 子类:

public class DynamicAlertDialogFragment : DialogFragment
{
    AlertDialog alertDialog;
    readonly Context context;

    public static DynamicAlertDialogFragment Instance(Context context, string title, string message)
    {
        var fragment = new DynamicAlertDialogFragment(context);
        Bundle bundle = new Bundle();
        bundle.PutString("title", title);
        bundle.PutString("message", message);
        fragment.Arguments = bundle;
        return fragment;
    }

    public DynamicAlertDialogFragment(Context context)
    {
        this.context = context;
    }

    public override Dialog OnCreateDialog(Bundle savedInstanceState)
    {
        var title = Arguments.GetString("title");
        var message = Arguments.GetString("message");
        alertDialog = new AlertDialog.Builder(context)
                    .SetIcon(Android.Resource.Drawable.IcDialogInfo)
                    .SetTitle(title)
                    .SetMessage(message)
                    .Create();
        return alertDialog;
    }

    public void SetMessage(string message)
    {
        (context as Activity).RunOnUiThread(() => { alertDialog.SetMessage(message);});
    }
}

AndroidIDynamicAlert依赖实现:

public class DynamicAlert : IDynamicAlert
{
    const string FRAGMENT_TAG = "DynamicAlert_Fragment";
    DynamicAlertDialogFragment fragment;
    static FormsAppCompatActivity currentActivity;
    public static FormsAppCompatActivity CurrentActivity { set { currentActivity = value; } }

    public void Show(string title, string message)
    {
        if (currentActivity == null) throw new Exception("DynamicAlert.CurrentActivity needs assigned");
        var fragMgr = currentActivity.FragmentManager;
        var fragTransaction = fragMgr.BeginTransaction();
        var previous = fragMgr.FindFragmentByTag(FRAGMENT_TAG);
        if (previous != null)
        {
            fragTransaction.Remove(previous);
        }
        fragTransaction.DisallowAddToBackStack();
        fragment = DynamicAlertDialogFragment.Instance(currentActivity, title, message);
        fragment.Show(fragMgr, FRAGMENT_TAG);
    }

    public void Update(string message)
    {
        if (fragment == null) throw new Exception("DynamicAlert is not showing, call Show first");
        fragment.SetMessage(message);
    }

    public void Dismiss()
    {
        if (fragment == null) throw new Exception("DynamicAlert is not showing, call Show first");
        fragment.Dismiss();
        fragment.Dispose();
        fragment = null;
    }
}

Android 初始化/使用:

DialogFragment 中创建AlertDialog 时,我们需要访问当前的Activity,而在使用Xamarin.Forms 时,通常是MainActivity,它是FormsAppCompatActivity 的子类。因此,您需要在 MainActivity.OnCreate 子类中使用 Activity 初始化 DynamicAlert.CurrentActivity 静态属性:

例子:

protected override void OnCreate(Bundle bundle)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;
    base.OnCreate(bundle);

    ////////////
    DynamicAlert.CurrentActivity = this;
    ////////////

    global::Xamarin.Forms.Forms.Init(this, bundle);
    LoadApplication(new App());

}

Android 输出:

【讨论】:

  • 谢谢你,这太完美了。你能给我一个提示,我们如何在 Android 中做到这一点?
  • @NewbieIOS 您可以使用 DialogFragment 并通过依赖服务使其与 Xamarin.Forms 一起使用。我可以稍后发布一个示例,因为我已经在 Form 项目中使用了一段时间。
  • 你节省了我很多时间。太感谢了。欣赏它。
  • 不要忘记向依赖服务注册您的实现。 "[assembly: Dependency(typeof(DynamicAlert))]" 在每个实现的命名空间之上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-14
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 2019-04-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多