UWP xamarin 中的自定义渲染器

Posted

技术标签:

【中文标题】UWP xamarin 中的自定义渲染器【英文标题】:Custom renderer in UWP xamarin 【发布时间】:2020-03-16 05:20:15 【问题描述】:

我有在ios xamarin 表单上工作的自定义渲染代码,但我想要UWP 类似,

using System;
using MobileAssessment.Interface;
using MobileAssessment.iOS;
using MobileAssessment.Pages;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using iOSPlatform = Xamarin.Forms.Platform.iOS.Platform;


[assembly: Xamarin.Forms.Dependency(typeof(ILoadingPageServiceiOS))]
namespace MobileAssessment.iOS

    public class ILoadingPageServiceiOS : ILodingPageService
    
        private UIView _nativeView;
        private bool _isInitialized;


        public void ShowLoadingPage()
        
            // check if the user has set the page or not
            if (!_isInitialized)
                InitLoadingPage(new LoadingIndicatorPage());  // set the default page

            // showing the native loading page
            UIApplication.SharedApplication.KeyWindow.AddSubview(_nativeView);
        

        public void HideLoadingPage()
        
            _nativeView.RemoveFromSuperview();
        

        public void InitLoadingPage(ContentPage loadingIndicatorPage = null)
        
            // check if the page parameter is available
            if (loadingIndicatorPage != null)
            
                // build the loading page with native base
                loadingIndicatorPage.Parent = Xamarin.Forms.Application.Current.MainPage;

                loadingIndicatorPage.Layout(new Rectangle(0, 0,
                    Xamarin.Forms.Application.Current.MainPage.Width,
                    Xamarin.Forms.Application.Current.MainPage.Height));
                var renderer = loadingIndicatorPage.GetOrCreateRenderer();
                 _nativeView = renderer.NativeView;
                _nativeView.BackgroundColor = UIColor.Black;
                _nativeView.Alpha = (System.nfloat)0.7;
                _isInitialized = true;
            
        

    


    internal static class PlatformExtension
    
        public static IVisualElementRenderer GetOrCreateRenderer(this VisualElement bindable)
        
            var renderer = iOSPlatform.GetRenderer(bindable);
            if (renderer == null)
            
                renderer = iOSPlatform.CreateRenderer(bindable);
                iOSPlatform.SetRenderer(bindable, renderer);
            
            return renderer;
        
    

我已经为 UWP 尝试了以下代码,

using System;
using MobileAssessment.Interface;
using MobileAssessment.UWP;
using MobileAssessment.Pages;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
using uwpPlatform = Xamarin.Forms.Platform.UWP.Platform;

[assembly: Xamarin.Forms.Dependency(typeof(ILoadingPageServiceRenderer))]
namespace MobileAssessment.UWP

    public class ILoadingPageServiceRenderer : ILodingPageService
    
        private View _nativeView;
        private bool _isInitialized;


        public void ShowLoadingPage()
        
            // check if the user has set the page or not
            if (!_isInitialized)
                InitLoadingPage(new LoadingIndicatorPage());  // set the default page

            // showing the native loading page
            Application.SharedApplication.KeyWindow.AddSubview(_nativeView);
        

        public void HideLoadingPage()
        
            _nativeView.RemoveFromSuperview();
        

        public void InitLoadingPage(ContentPage loadingIndicatorPage = null)
        
            // check if the page parameter is available
            if (loadingIndicatorPage != null)
            
                // build the loading page with native base
                loadingIndicatorPage.Parent = Xamarin.Forms.Application.Current.MainPage;

                loadingIndicatorPage.Layout(new Rectangle(0, 0,
                    Xamarin.Forms.Application.Current.MainPage.Width,
                    Xamarin.Forms.Application.Current.MainPage.Height));
                var renderer = loadingIndicatorPage.GetOrCreateRenderer();
                 _nativeView = renderer.NativeView;
                _nativeView.BackgroundColor = Color.Black;
                _nativeView.Alpha = (System.nfloat)0.7;
                _isInitialized = true;
            
        

    


    internal static class PlatformExtension
    
        public static IVisualElementRenderer GetOrCreateRenderer(this VisualElement bindable)
        
            var renderer = uwpPlatform.GetRenderer(bindable);
            if (renderer == null)
            
                renderer = iOSPlatform.CreateRenderer(bindable);
                uwpPlatform.SetRenderer(bindable, renderer);
            
            return renderer;
        
    

上面的活动指示器代码实际上来自https://github.com/UdaraAlwis/Xamarin-Playground/tree/master/XFLoadingPageService

但是论坛没有为 UWP 共享相同的解决方案,所以我为 windows 创建了我的代码。

【问题讨论】:

【参考方案1】:

如果您正在寻找“全屏加载”样式,您还可以使用 ControlTemplate 并将其绑定到特定页面。

你可以这样做:

<Color x:Key="AccentColor">#ABDEBE</Color>

<ControlTemplate x:Key="FullScreenLoadingTemplate">
    <AbsoluteLayout>

        <ContentPresenter
            AbsoluteLayout.LayoutFlags="All"
            AbsoluteLayout.LayoutBounds="0, 0, 1, 1" />

        <ContentView
            AbsoluteLayout.LayoutFlags="All"
            AbsoluteLayout.LayoutBounds="0, 0, 1, 1"
            BackgroundColor="#80FFFFFF"
            IsVisible="TemplateBinding BindingContext.IsBusy">

            <ActivityIndicator
                HorizontalOptions="Center"
                IsRunning="TemplateBinding BindingContext.IsBusy"
                VerticalOptions="Center"
                Color="StaticResource AccentColor" />

        </ContentView>

    </AbsoluteLayout>
</ControlTemplate>

和页面绑定:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:d="http://xamarin.com/schemas/2014/forms/design"

         ControlTemplate="StaticResource FullScreenLoadingTemplate"
         Title="Binding Title"
         IsBusy="Binding IsBusy"
         x:Class="TestApp.Mobile.Pages.TestPage">... </ContentPage>

【讨论】:

不,我不想在每个屏幕上实现指示器。我想将指标创建为一项服务,并在我需要时在应用程序中使用它。基本上对于 iOS 实现,它在主应用程序 UIWindow 中添加(作为 UIView 的指示符)。但我不知道 UWP。【参考方案2】:

毕竟我未能为 Window 平台编写相同的代码。所以我使用 Rg.Plugins.Popup.Pages 插件制作了解决方案。

应用全局加载器指示器 xaml 文件

<?xml version="1.0" encoding="UTF-8"?>
<pages:PopupPage  xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
                  xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:telerikPrimitives="clr-namespace:Telerik.XamarinForms.Primitives;assembly=Telerik.XamarinForms.Primitives"
                  x:Class="MobileAssessment.Pages.AppGlobalLoader">
    <ContentPage.Content>
        <telerikPrimitives:RadBusyIndicator x:Name="BusyIndicator"
                                        VerticalOptions="FillAndExpand" 
                                       HorizontalOptions="FillAndExpand" 
                                       AnimationContentHeightRequest="100"
                                       AnimationContentWidthRequest="100"
                                       AnimationType="Animation8"
                                       AnimationContentColor="Teal"
                                       IsBusy="True"
                                       BackgroundColor="Black"
                                       Opacity="0.7">
        <telerikPrimitives:RadBusyIndicator.Content>
             <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" Opacity="0.7">
             </StackLayout>
               </telerikPrimitives:RadBusyIndicator.Content>
            </telerikPrimitives:RadBusyIndicator>
    </ContentPage.Content>

</pages:PopupPage>

应用全局加载器cs文件

using System;
using System.Collections.Generic;
using Rg.Plugins.Popup.Pages;
using Xamarin.Forms;

namespace MyApp.Pages

    public partial class AppGlobalLoader : PopupPage
    
        public AppGlobalLoader()
        
            InitializeComponent();
        
    

我在基础导航器类中创建了两个方法显示和隐藏弹出窗口,

public async Task showLoader()

    isPopupOpen = true;
    AppGlobalLoader theAppGlobalLoader = new AppGlobalLoader();            
    await _Navigation?.PushPopupAsync(theAppGlobalLoader);


public async Task hideLoader()

    if (isPopupOpen)
    
        await _Navigation?.PopPopupAsync(true);
    

现在我在长时间运行的任务中使用上述方法,

async Task ExecuteAndSave()
    
        if (ValidateFields())
        
            await base.showLoader();

            //Your long ruuning task dealing with server and saving stuff in database
            await base.hideLoader();
            await App.Current.MainPage.DisplayAlert("Successful", "Created", "Ok");
            await ExecuteBackCommand();
        
    

【讨论】:

以上是关于UWP xamarin 中的自定义渲染器的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 中的 FontAwesome 形成 UWP

使用 Xamarin Forms 在 UWP 中自定义进度条颜色

Xamarin 表单:UWP 和 Windows 8.1 中的自定义字体

[xamarin][uwp][custom renderer] 自定义渲染器 pcl 库未在发布模式下加载

将 UWP 标头模板中的图标与 xamarin.forms 一起使用

如何在 xamarin.UWP 中的 Viewcell 项目选择上设置自己的颜色?