前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MAUI中构建跨平台原生控件实现

MAUI中构建跨平台原生控件实现

作者头像
JusterZhu
发布2022-12-07 20:08:52
7840
发布2022-12-07 20:08:52
举报
文章被收录于专栏:JusterZhu

以下文章来源于CodeShare ,作者痕迹gg

简介

MAUI中使用Handler体系来处理不同平台的原生控件实现, 即对应的, 如果我们想要创建控件, 只需要创建基于不同平台的Handler即可。 那么下面主要教大家如何通过创建Handler(事件处理程序)来构建自己的控件。

开始

下面, 将通过创建一个进度条控件案例, 来演示如何在MAUI项目中创建平台控件并且使用它。 假设控件包含基础的三项功能, 进度条颜色(Foreground)、进度条当前值(Value)、进度条模式(Indeterminate) 1.第一步(声明控件类) 首先, 创建MyProgressBar类, 定义对应的依赖属性

代码语言:javascript
复制
internal class MyProgressBar : View
    {
        public static readonly BindableProperty ForegroundProperty =
            BindableProperty.Create(nameof(Foreground),
                typeof(Color),
                typeof(MyProgressBar),
                Colors.Transparent);

        public static readonly BindableProperty ValueProperty =
           BindableProperty.Create(nameof(Value),
               typeof(double),
               typeof(MyProgressBar),
               0.0);

        public static readonly BindableProperty IndeterminateProperty =
           BindableProperty.Create(nameof(Indeterminate),
               typeof(bool),
               typeof(MyProgressBar),
               false);

        public Color Foreground
        {
            get { return (Color)GetValue(ForegroundProperty); }
            set { SetValue(ForegroundProperty, value); }
        }
         
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        public bool Indeterminate
        {
            get { return (bool)GetValue(IndeterminateProperty); }
            set { SetValue(IndeterminateProperty, value); }
        }
    }

2.第二步(创建标准处理程序) 有了控件的标准属性定义之后, 接下来就是定义标准的Handler处理程序, 其中包含控件属性映射器及构造函数, 如下所示:

代码语言:javascript
复制
   partial class MyProgressBarHandler
    {
        public static PropertyMapper<MyProgressBar, MyProgressBarHandler> HorizontalProgressBarMapper = new
        (ViewHandler.ViewMapper)
        {
            [nameof(MyProgressBar.Value)] = MapValue,
            [nameof(MyProgressBar.Foreground)] = MapForeground, 
            [nameof(MyProgressBar.Indeterminate)]= MapIndeterminate
        };

        public MyProgressBarHandler(PropertyMapper mapper)
            : base(mapper)
        {

        }

        public MyProgressBarHandler() : base(HorizontalProgressBarMapper)
        {

        }
    }

3.第三步(创建平台处理程序) 在属性映射器中, 我们可以很轻松看见对应了三个属性的事件处理程序, 但是目前并没有定义它, 这意味着你需要在不同平台下分别实现对应的 三个事件处理程序, 所以很快阿, 赶紧在Platforms > Android > Controls 下定义了一个MyProgressBarHandler, 如下所示:

接着继承于ViewHandler并且与原生安卓ProgressBar关联。

代码语言:javascript
复制
using Android.Widget;

partial class MyProgressBarHandler :
        ViewHandler<MyProgressBar, ProgressBar>
    { 

    }

重写CreateNativeView(这是创建本地控件最开始的地方)

代码语言:javascript
复制
protected override ProgressBar CreateNativeView()
        {
            return new ProgressBar(Context, null,  Android.Resource.Attribute.ProgressBarStyleHorizontal)
            {
                Indeterminate = true,
                Max = 10000,
            }; 
        }

紧接着, 实现三个事件处理程序方法, MapValue、MapForeground、MapIndeterminate

代码语言:javascript
复制
        static void MapValue(MyProgressBarHandler handler, MyProgressBar view)
        {
            var nativeView= handler?.NativeView;
            nativeView.Progress = (int)(view.Value * Max);
        }

        static void MapForeground(MyProgressBarHandler handler, MyProgressBar view)
        {
            UpdateForeground(handler?.NativeView, view.Foreground);

            static void UpdateForeground(ProgressBar nativeProgressBar, Color color)
            {
                if (color == null)
                {
                    (nativeProgressBar.Indeterminate ? nativeProgressBar.IndeterminateDrawable :
                        nativeProgressBar.ProgressDrawable)?.ClearColorFilter();
                }
                else
                {
                    var tintList = ColorStateList.ValueOf(color.ToNative());

                    if (nativeProgressBar.Indeterminate)
                        nativeProgressBar.IndeterminateTintList = tintList;
                    else
                        nativeProgressBar.ProgressTintList = tintList;
                }
            }
        }

        static void MapIndeterminate(MyProgressBarHandler handler, MyProgressBar view)
        {
           var nativeView= handler?.NativeView;
            nativeView.Indeterminate = view.Indeterminate;
        }

4. 对应的实现iOS平台的Handler事件处理程序, 与上步骤相同, 对于事件的处理细节则对应不同平台的逻辑处理。

代码语言:javascript
复制
partial class MyProgressBarHandler :
        ViewHandler<MyProgressBar, UIProgressView>
    {
        protected override UIProgressView CreateNativeView()
{
            return new UIProgressView(UIProgressViewStyle.Default);
        }
         
        static void MapValue(MyProgressBarHandler handler, MyProgressBar view)
{
            var nativeView = handler.NativeView;
            nativeView.Progress = (float)view.Value;
        }

        static void MapForeground(MyProgressBarHandler handler, MyProgressBar view)
{
            var nativeView = handler.NativeView;
            nativeView.ProgressTintColor = view.Foreground?.ToNative();
        } 

        static void MapIndeterminate(MyProgressBarHandler handler, MyProgressBar view)
{
            //...
        }
    } 

5.打开MauiProgram文件, 添加AddHandler

代码语言:javascript
复制
public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder.UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                })
                .ConfigureMauiHandlers(handler =>
                {
                  handler.AddHandler(typeof(MyProgressBar), typeof(MyProgressBarHandler));
                });  
            return builder.Build();
        }

6.界面中,分别声明MAUI原生控件与自定义控件

代码语言:javascript
复制
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MAUIRender.MainPage"
             xmlns:my="clr-namespace:MAUIRender" 
             xmlns:ctor="clr-namespace:MAUIRender.Controls" 
             BackgroundColor="{DynamicResource SecondaryColor}">
    <Grid>
        <StackLayout>
            <ProgressBar   
                Progress="30" ProgressColor="Red"/>
            
            <ctor:MyProgressBar 
                Indeterminate="True"
                Value="600"  Foreground="Green" />
        </StackLayout>
    </Grid>
</ContentPage>

运行实际效果:

总结

通过利用Handler来处理不同平台控件的行为, 与控件本身解耦并且更加容器支持更多的平台。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JusterZhu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 开始
  • 总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档