【问题标题】:Is it possible to have one Activity indicator for entire app?是否可以为整个应用程序设置一个活动指示器?
【发布时间】:2017-08-08 19:58:25
【问题描述】:

我在整个应用程序中都有活动指示器,但我发现这是重复的。我想知道是否可以定义一个活动指示器并在整个应用程序中使用它?

下面是我在应用程序中拥有的五个活动指标之一的代码。除了标签文字变化之外,每个人都完全一样。

<AbsoluteLayout x:Name="ActivityInd" IsVisible="False" BackgroundColor="Black" Opacity=".75" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
      <StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" VerticalOptions="Center" HorizontalOptions="Center">
          <ActivityIndicator x:Name="Activityblocker" Color="White"/>
          <Label Text="Processing Request" TextColor="White"/>
      </StackLayout>
</AbsoluteLayout>

如果可能,最好将其放置在哪里,以便可以从应用程序中的任何位置调用它?

编辑:

一切正常,并用我创建的控件替换了所有活动指示器。以下是代码,希望这可以帮助将来的人。

使用绑定控制 xaml

<?xml version="1.0" encoding="UTF-8"?>
<AbsoluteLayout xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            x:Class="Myapp.ActivityBlocker" 
            x:Name="ActivityIndAL" IsVisible="{Binding IsBusy, Source={x:Reference ActivityIndAL}}" BackgroundColor="Black" Opacity=".75" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1">
    <StackLayout AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" VerticalOptions="Center" HorizontalOptions="Center">
        <ActivityIndicator x:Name="Activityblocker" Color="White" IsEnabled="{Binding IsBusy, Source={x:Reference ActivityIndAL}}" IsRunning="{Binding IsBusy, Source={x:Reference ActivityIndAL}}"/>
        <Label Text="{Binding Text, Source={x:Reference ActivityIndAL}}" x:Name="ActivityIndLabel" TextColor="White"/>
    </StackLayout>
</AbsoluteLayout>

控制 xaml.cs

public partial class ActivityBlocker : AbsoluteLayout
    {
        public ActivityBlocker()
        {
            InitializeComponent();
        }

        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(ActivityBlocker));
        public static readonly BindableProperty Running = BindableProperty.Create(nameof(IsBusy), typeof(bool), typeof(ActivityBlocker), false);

        public string Text
        {
            get
            {
                return (string)GetValue(TextProperty);
            }
            set
            {
                SetValue(TextProperty, value);
            }
        }

        public bool IsBusy
        {
            get
            {
                return (bool)GetValue(Running);
            }
            set
            {
                SetValue(Running, value);
            }
        }

    }

如何使用该控件:您将xmlns:control="clr-namespace:MyApp" 添加到您要使用该控件的内容页面中。现在添加控件和文本。注意:IsBusy="False" 不是必需的,因为它在BindableProperty.Create 中的默认值为 false。通过这样做indicator.IsBusy = true;

,可以从后端代码访问和更改 IsBusy
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:control="clr-namespace:MyApp"
....
<ContentPage.Content>
        <AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<control:ActivityBlocker x:Name="indicator" Text="Processing Request" IsBusy="False"/>
        </AbsoluteLayout>
</ContentPage.Content>
....

【问题讨论】:

  • 可以创建自定义控件
  • @YuriS 这太完美了。不知道您可以在 Xamarin 中创建自定义控件。 this 帮助指南所说的我会做的差不多。正确的?如果是这样,我会试一试并在我得到一些工作后发布代码。谢谢。
  • 是的,这是一篇很棒的文章。他正在做 Grid 而不是 ContentView。如果你想要那个布局,你会做 AbsoluteLayout,但 Grid 也适合你。我还会质疑您是否需要在里面使用 StackLayout。您将创建例如 BusyText 的可绑定属性并将其绑定到您的标签文本
  • @YuriS 我已经在问题中添加了代码。随时给我任何反馈。我还尝试使用网格并删除堆栈布局,但我很难让活动指示器和标签居中。它一直在左上角,没有覆盖整个视图。

标签: xamarin xamarin.forms


【解决方案1】:

这是覆盖整个页面吗?如果是这样,您可以使用 DependencyService 显示/隐藏加载指示器您必须下载适用于 Android/iOS 的 NuGet 包:AndHUD/BTProgressHUD,如下所示:

using XXXX.Helpers;

namespace XXXX
{
    public interface IHudService
    {
        /// <summary>
        /// Shows hud in the secreen
        /// </summary>
        /// <param name="ProgressText">Set progress</param>
        void ShowHud(string ProgressText = StaticData.Loading);

        /// <summary>
        /// Hides hud.
        /// </summary>
        void HideHud();

        /// <summary>
        /// Set text.
        /// </summary>
        /// <param name="Text">Set text to hub.</param>
        void SetText(string Text);

        /// <summary>
        /// Set progress.
        /// </summary>
        /// <param name="Progress">Set progress.</param>
        /// <param name="ProgressText">Set Text.</param>
        void SetProgress(double Progress, string ProgressText = "");
    }
}

安卓:

using AndroidHUD;
using Android.Views;
using Xamarin.Forms;
using XXXX.Droid;
using XXXX.DependencyServices;
using XXXX.Helpers;

[assembly: Dependency(typeof(DroidHudService))]

namespace XXXX.Droid
{
    public class DroidHudService : IHudService
    {

        #region IHudManager implementation

        bool isHudVisible;

        public void ShowHud(string ProgressText = StaticData.Loading)
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                AndHUD.Shared.Show(Forms.Context, ProgressText, maskType: MaskType.Black);
                isHudVisible = true;

            });
        }

        public void HideHud()
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                AndHUD.Shared.Dismiss(Forms.Context);
                isHudVisible = false;
            });
        }

        public void SetProgress(double Progress, string ProgressText = "")
        {
            if (!isHudVisible)
                return;
            Device.BeginInvokeOnMainThread(() =>
            {
                int progress = (int)(Progress * 100);
                AndHUD.Shared.Show(Forms.Context, ProgressText + progress + "%", progress, MaskType.Black);
            });
        }
        public void SetText(string Text)
        {
            if (!isHudVisible)
                return;
            Device.BeginInvokeOnMainThread(() =>
            {
                AndHUD.Shared.Show(Forms.Context, Text, maskType: MaskType.Black);
            });
        }

        Android.Views.View CustomLoadingView(string ProgressText)
        {
            Android.Views.View loadingView = new Android.Views.View(Forms.Context);

            return loadingView;
        }

        #endregion
    }

}

iOS

using System;
using BigTed;
using CoreAnimation;
using CoreGraphics;
using XXXX.DependencyServices;
using XXXX.Helpers;
using XXXX.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;

[assembly: Dependency(typeof(IosHudService))]

namespace XXXX.iOS
{
    /// <summary>
    /// Manages loading indicators in the app.
    /// </summary>
    public class IosHudService : IHudService
    {

        UIView _load;

        bool isHudVisible;

        #region IHudManager implementation

        /// <summary>
        /// Show loading indicator.
        /// </summary>
        /// <param name="ProgressText">Progress to set.</param>
        public void ShowHud(string ProgressText = StaticData.Loading)
        {
            isHudVisible = true;
            SetText(ProgressText);
        }

        /// <summary>
        /// Hide loading indicator.
        /// </summary>
        public void HideHud()
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                BTProgressHUD.Dismiss();
                if (_load != null)
                    _load.Hidden = true;
                isHudVisible = false;
            });
        }


        /// <summary>
        /// Method to change Progress Text and show custom loader with Challenge Logo
        /// </summary>
        /// <param name="ProgressText">Progress text.</param>
        public void SetProgress(double Progress, string ProgressText = "")
        {
            int progress = (int)(Progress * 100);
            string text = ProgressText + progress + "%";
            SetText(text);
        }

        /// <summary>
        /// Set text to loading indicator.
        /// </summary>
        /// <param name="text">Text to display.</param>
        public void SetText(string text)
        {
            if (!isHudVisible)
                return;
            Device.BeginInvokeOnMainThread(() =>
            {
                BTProgressHUD.Show(status: text, maskType: ProgressHUD.MaskType.Black);

                try
                {
                    //if (_load == null) {
                    //  _load = CustomLoadingView (text);
                    //  ProgressHUD.Shared.AddSubview (_load);
                    //}
                    lblTitle.Text = text;

                    UIView[] subView = ProgressHUD.Shared.Subviews;
                    for (int i = 0; i < subView.Length; i++)
                    {
                        subView[i].Hidden = true;
                    }
                    _load.Hidden = false;
                    ProgressHUD.Shared.BringSubviewToFront(_load);
                }
                catch (Exception ex)
                {
                    #if DEBUG
                    Console.WriteLine("IosHudService.cs - SetText() " + ex.Message);
                    #endif
                }
            });
        }

        UILabel lblTitle;
        /// <summary>
        /// Customs the loading view.
        /// </summary>
        /// <returns>The loading view.</returns>
        /// <param name="ProgressText">Progress text.</param>
        UIView CustomLoadingView(string ProgressText)
        {
            UIView loadingView = new UIView();
            loadingView.Frame = new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height);

            UIImageView imgBg = new UIImageView();
            imgBg.Image = UIImage.FromFile("load_bg.png");
            imgBg.Frame = new CGRect((loadingView.Frame.Width / 2) - 65, (loadingView.Frame.Height / 2) - 70, 130, 140);
            loadingView.Add(imgBg);

            UIImageView someImageView = new UIImageView();
            someImageView.Frame = new CGRect((loadingView.Frame.Width / 2) - 40, (loadingView.Frame.Height / 2) - 50, 75, 75);
            someImageView.AnimationImages = new UIImage[]
            {
                UIImage.FromBundle("spinner.png"),
            };
            someImageView.AnimationRepeatCount = nint.MaxValue; // Repeat forever.
            someImageView.AnimationDuration = 1.0; // Every 1s.
            someImageView.StartAnimating();


            CABasicAnimation rotationAnimation = new CABasicAnimation();
            rotationAnimation.KeyPath = "transform.rotation.z";
            rotationAnimation.To = new NSNumber(Math.PI * 2);
            rotationAnimation.Duration = 1;
            rotationAnimation.Cumulative = true;
            rotationAnimation.RepeatCount = float.PositiveInfinity;
            someImageView.Layer.AddAnimation(rotationAnimation, "rotationAnimation");
            loadingView.Add(someImageView);


            lblTitle = new UILabel();
            lblTitle.Text = ProgressText;
            lblTitle.Frame = new CGRect(imgBg.Frame.X, someImageView.Frame.Y + someImageView.Frame.Height + 15, 130, 20);
            lblTitle.TextAlignment = UITextAlignment.Center;
            lblTitle.TextColor = UIColor.White;
            lblTitle.AdjustsFontSizeToFitWidth = true;
            loadingView.Add(lblTitle);
            return loadingView;
        }

        #endregion
    }

}

当您需要显示或隐藏它时,您可以使用:

public static void ShowLoadingIndicator(string progressText = "Loading...")
{
    Device.BeginInvokeOnMainThread(() =>
    {
        DependencyService.Get<IHudService>().ShowHud(progressText);
    });
}

public static void HideLoadingIndicator()
{
    Device.BeginInvokeOnMainThread(() =>
    {
        DependencyService.Get<IHudService>().HideHud();
    });
}

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-12
    • 2014-07-24
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 2010-11-05
    • 2011-03-07
    • 1970-01-01
    相关资源
    最近更新 更多