Xamarin.Forms로 범용적인 로딩 화면을 만들어보세요

17018 단어 XamarinC#Xamarin.Forms
Xamarin.Forms 하고 있어 조금(-_-;)이 되어 버리는 곳에 IsBusy 프로퍼티의 미묘한 느낌이 있을까 생각합니다.
다른 조작 할 수 버리고.

이런 게 하고 싶었어요.
alt

DisplayAlert 같은 느낌으로 사용할 수 있는 빙글빙글 돌리는 로딩 화면을 간단하게 만들 수 없을까라고 생각해 만들어 보았습니다.

먼저 PCL 프로젝트에서만 구현하려고했습니다.
화면을 마스킹하여 배경을 투명하게 구현하기 위해서는, 지금 표시하고 있는 페이지의 Content를 사용해 다른 페이지를 표시해 로딩의 Content와 원래의 Content를 겹친다고 하는 수법으로 구현하는 일 할 수 있었습니다만・・・・・・늦다.

XAML을 다시 그려 바인딩을 다시하기 때문에 매우 동작이 느려져 버렸습니다.

그래서 플랫폼마다 구현하기로 했습니다.
쉽게 만들고 싶었기 때문에 DependencyService에서 구현했습니다.

우선 PCL측은 이런 느낌.
    public interface ILoadingMessage
    {
        /// <summary>ローディングを開始する</summary>
        /// <param name="message"></param>
        void Show(string message);

        /// <summary>ローディングを終了する</summary>
        void Hide();

        /// <summary>状態</summary>
        bool IsShow { get; }
    }

Android는 ProgressDialog만 표시합니다.
    public class LoadingMessage : ILoadingMessage
    {
        private ProgressDialog progress;
        /// <summary>ローディングを開始する</summary>
        /// <param name="message"></param>
        public void Show(string message)
        {
            progress = new ProgressDialog(Forms.Context);
            progress.Indeterminate = true;
            progress.SetProgressStyle(ProgressDialogStyle.Spinner);
            progress.SetCancelable(false);
            progress.SetMessage(message);           
            progress.Show();
            ishow = true;
        }

        /// <summary>ローディングを終了する</summary>
        public void Hide()
        {
            progress?.Dismiss();
            ishow = false;
        }

        /// <summary>状態</summary>
        public bool IsShow => ishow;

        private bool ishow = false;
    }

iOS는 여기를 참고했습니다.
htps : //로 ゔぇぺぺr. 마린. 코 m / 레시 페 s / 이오 s / s 단지 rd_ 콘 트로 ls / 포포 ょ rs / ぢ sp ぁ y_ 아_ ぉ 아 ぢ g_ 메사게 /
    public class LoadingMessage : ILoadingMessage
    {
        private LoadingOverlay loadpop;
        /// <summary>ローディングを開始する</summary>
        /// <param name="message"></param>
        public void Show(string message)
        {            
            var window = UIApplication.SharedApplication.KeyWindow;
            var vc = window.RootViewController;
            while (vc.PresentedViewController != null)
            {
                vc = vc.PresentedViewController;                
            }

            var bounds = UIScreen.MainScreen.Bounds;
            loadpop = new LoadingOverlay(bounds, message);
            vc.Add(loadpop);
            ishow = true;
        }

        /// <summary>ローディングを終了する</summary>
        public void Hide()
        {
            loadpop.Hide();
            ishow = false;
        }

        /// <summary>状態</summary>
        public bool IsShow => ishow;

        private bool ishow = false;
    }

    public class LoadingOverlay : UIView
    {
        // control declarations
        UIActivityIndicatorView activitySpinner;
        UILabel loadingLabel;

        public LoadingOverlay(CGRect frame, string message) : base(frame)
        {
            // configurable bits
            BackgroundColor = UIColor.Black;
            Alpha = 0.75f;
            AutoresizingMask = UIViewAutoresizing.All;

            nfloat labelHeight = 22;
            nfloat labelWidth = Frame.Width - 20;

            // derive the center x and y
            nfloat centerX = Frame.Width / 2;
            nfloat centerY = Frame.Height / 2;

            // create the activity spinner, center it horizontall and put it 5 points above center x
            activitySpinner = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.WhiteLarge);
            activitySpinner.Frame = new CGRect(
                centerX - (activitySpinner.Frame.Width / 2),
                centerY - activitySpinner.Frame.Height - 20,
                activitySpinner.Frame.Width,
                activitySpinner.Frame.Height);
            activitySpinner.AutoresizingMask = UIViewAutoresizing.All;
            AddSubview(activitySpinner);
            activitySpinner.StartAnimating();

            // create and configure the "Loading Data" label
            loadingLabel = new UILabel(new CGRect(
                centerX - (labelWidth / 2),
                centerY + 20,
                labelWidth,
                labelHeight
                ));
            loadingLabel.BackgroundColor = UIColor.Clear;
            loadingLabel.TextColor = UIColor.White;
            loadingLabel.Text = message;
            loadingLabel.TextAlignment = UITextAlignment.Center;
            loadingLabel.AutoresizingMask = UIViewAutoresizing.All;
            AddSubview(loadingLabel);

        }

        /// <summary>
        /// Fades out the control and then removes it from the super view
        /// </summary>
        public void Hide()
        {
            UIView.Animate(
                0.5, // duration
                () => { Alpha = 0; },
                () => { RemoveFromSuperview(); }
            );
        }
    }

상당히 쾌적하게 동작해 좋지만, 유감스럽게도 이것만으로는 버튼 두번 눌러 대책은 되지 않으므로
그 근처는, 간단하게 실장할 수 있는 좋은 안이 없는지 생각중입니다.

그리고, 동작 thread에 관해서 고려하지 않고 만들고 있으므로 호출원이 UIThread 나오지 않는 경우에는 주의가 필요합니다.

좋은 웹페이지 즐겨찾기