Xamarin.Forms PCL/SAP 自定义渲染,支持paintcode 3

Posted

技术标签:

【中文标题】Xamarin.Forms PCL/SAP 自定义渲染,支持paintcode 3【英文标题】:Xamarin.Forms PCL/SAP Custom renders with paintcode 3 support 【发布时间】:2017-02-24 17:51:49 【问题描述】:

伙计们!我有一个非常好的问题,我正在使用 Paintcode 3 并且正在 Xamarin.Forms(PCL/SAP) 项目中工作。我现在正在运行一个示例项目,并且我在 paintcode 3 中有一个自定义绘图。但是,我知道paintcode 应该可以与 c# Xamarin 一起使用。但是,我在想我可以在我的 xamarin.forms 项目中创建一个自定义渲染器,然后提取一个自定义paintcode 3 绘图,创建一个渲染并将其粘贴在那里。在我发布任何代码之前我的问题是这种方法之前是否已经完成或有人尝试过这个?

到目前为止,这是我的代码非常简单的东西:

我的主页:

   public class MainPageCS :ContentPage

    public MainPageCS()
    

        // The root page of your application

        Title = "PCTest";
        Padding = new Thickness(0, 20, 0, 0);

        Content = new TestView
        


            // draw object will go here once i render it.

            BackgroundColor = Color.Blue,
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center

        ;

    


Test 视图继承自 Xamarin.forms 视图的简单内容页面。

 public class TestView : View

    public TestView()
    
    

现在看起来很简单,但是,这就是它变得令人毛骨悚然的地方 这是我创建的绘画代码项目。这是图像。 PaintCodeProjectImage

现在,这是生成该图像的代码。 TestChatBox.cs

namespace PaintCodeStyleKitTest

[Register("TestChatBox")]
public class TestChatBox : NSObject


    //// Cache

    private static UIImage imageOfChatIcon;
    private static NSObject[] chatIconTargets;

    //// Initialization

    static TestChatBox()
    

        DrawChatIcon();
    

    //// Drawing Methods

    public static void DrawChatIcon()
    

        //// Oval 2 Drawing
        var oval2Path = new UIBezierPath();
        oval2Path.MoveTo(new CGPoint(105.65f, 43.5f));
        oval2Path.AddCurveToPoint(new CGPoint(55.59f, 56.97f), new CGPoint(87.51f, 43.64f), new CGPoint(69.43f, 48.13f));
        oval2Path.AddCurveToPoint(new CGPoint(35.44f, 96.92f), new CGPoint(38.57f, 67.85f), new CGPoint(31.85f, 82.81f));
        UIColor.Gray.SetStroke();
        oval2Path.LineWidth = 9.0f;
        oval2Path.LineCapStyle = CGLineCap.Round;
        oval2Path.Stroke();


        //// Bezier 2 Drawing
        var bezier2Path = new UIBezierPath();
        bezier2Path.MoveTo(new CGPoint(166.1f, 48.28f));
        bezier2Path.AddCurveToPoint(new CGPoint(166.1f, 131.72f), new CGPoint(199.3f, 71.32f), new CGPoint(199.3f, 108.68f));
        bezier2Path.AddCurveToPoint(new CGPoint(89.68f, 147.91f), new CGPoint(145.34f, 146.13f), new CGPoint(116.5f, 151.53f));
        bezier2Path.AddCurveToPoint(new CGPoint(43.5f, 169.5f), new CGPoint(71.56f, 159.66f), new CGPoint(43.5f, 169.5f));
        bezier2Path.AddCurveToPoint(new CGPoint(58.33f, 138.86f), new CGPoint(43.5f, 169.5f), new CGPoint(53.16f, 153.11f));
        bezier2Path.AddCurveToPoint(new CGPoint(45.9f, 131.72f), new CGPoint(53.95f, 136.8f), new CGPoint(49.78f, 134.42f));
        bezier2Path.AddCurveToPoint(new CGPoint(45.9f, 48.28f), new CGPoint(12.7f, 108.68f), new CGPoint(12.7f, 71.32f));
        bezier2Path.AddCurveToPoint(new CGPoint(166.1f, 48.28f), new CGPoint(79.09f, 25.24f), new CGPoint(132.91f, 25.24f));
        bezier2Path.ClosePath();
        UIColor.Red.SetStroke();
        bezier2Path.LineWidth = 9.0f;
        bezier2Path.Stroke();
    

    //// Generated Images

    public static UIImage ImageOfChatIcon
    
        get
        
            if (imageOfChatIcon != null)
                return imageOfChatIcon;

            UIGraphics.BeginImageContextWithOptions(new CGSize(210.0f, 190.0f), false, 0);
            TestChatBox.DrawChatIcon();
            imageOfChatIcon = UIGraphics.GetImageFromCurrentImageContext();
            UIGraphics.EndImageContext();

            return imageOfChatIcon;
        
    

    //// Customization Infrastructure

    [Outlet]
    public NSObject[] ChatIconTargets
    
        get  return chatIconTargets; 
        set
        
            chatIconTargets = value;
            foreach (NSObject target in value)
            
                target.PerformSelector(new ObjCRuntime.Selector("setImage:"), ImageOfChatIcon, 0);
            
        
    


现在,当我完成那个简单的图像时,上面是为我生成的paintcode。 通过阅读paintcode文档,生成的代码必须覆盖drawrect方法才能绘制图片,请参阅我的Test.cs

 using System;   
    using Xamarin.Forms;
    using CoreGraphics;
    using UIKit;
    using System.Drawing;
    using Foundation;
    using PaintCodeStyleKitTest;
    namespace PCTest
    
        public class Test : UIView
        
            public Test()
            
                TestChatBox.DrawChatIcon();
            

            public override void Draw(CGRect rect)
            

                base.Draw(rect);
                TestChatBox.DrawChatIcon();


            


        
    

这会覆盖 draw 方法并成功绘制图片,但是,当我尝试使用我的测试渲染器文件完成自定义渲染时。

    using System;
using Xamarin.Forms;
using PCTest;
using UIKit;
using Xamarin.Forms.Platform.ios;
using PaintCodeStyleKitTest;
using PCTest.iOS;
using Foundation;
using UIKit;
using CoreGraphics;

[assembly: ExportRenderer(typeof(TestView), typeof(TestRenderer))]
namespace PCTest.iOS

    public class TestRenderer : ViewRenderer<TestView, Test>
    
        Test txt;
        protected override void OnElementChanged(ElementChangedEventArgs <TestView> e )
            
                base.OnElementChanged(e);
        if (Control == null)
        
            //txt = new Test( tes);
            Test tests = new Test();

            SetNativeControl(new Test());

        
            if (e.OldElement != null)
            
                return;
            

        


 



我运行我的示例应用程序,但视图中没有任何内容。我想知道为什么。我试图应用一个简单的内容页面来查看我的示例视图是否会呈现,但是它没有呈现任何人都可以指出我在这方面的正确方向。关于我的处理方法,我做错了什么吗?请帮忙!

【问题讨论】:

【参考方案1】:

您没有为您的自定义控件分配任何尺寸,因此您的自定义UIViewFrame 永远不会被设置,因此它存在于0,0,大小为0,0

var test = new TestView

    WidthRequest = 200,
    HeightRequest = 200,
    BackgroundColor = Color.Blue,
    HorizontalOptions = LayoutOptions.Center,
    VerticalOptions = LayoutOptions.Center
;

【讨论】:

@SushiHangoverso 我在其他 cs 文件中的其他代码是否正确?我知道我没有正确初始化框架来渲染我的图片。我是否必须在我的 Test.cs 中提出您所说的建议,从 UIView 的哪个子类,或者我必须在我的 TestView 中对 View 的哪个子类进行更改? @Nijoel 这取决于,您当前的DrawChatIcon 是基于硬编码的尺寸,因此使用UIView 对帧大小进行硬编码可能是有意义的......我倾向于使用 PaintCode 的框架、约束和变量来制作调整到其容器大小的参数设计(即文本输入字段,其绘图可能会随着输入字段的字体大小的更改而垂直扩展而不是水平扩展......)它实际上取决于您的矢量的用例艺术将在 UI 中使用,因此您需要做多少工作... @Nijoel 在 Paintcode 中添加框架、约束、变量如果您从未在完成的 UI 控件中使用它,可能需要做很多工作......我有很多来自 Paintcode 的静态绘图,我只是放入控件的 Draw 方法,我就完成了。其他时候我将控件的内部大小连接到 Paintcode 绘图,其他时候我通过控件属性公开 Paintcode 变量,以便开发人员可以在设计时或在运行时以编程方式调整它们...... @Nijoel 是的,您的其他代码运行良好...只是没有设置框架... 使用 PaintCode 的框架约束和变量来进行理想的更改?我认为覆盖drawrect然后调用该方法就可以了,我可以有你草拟的示例代码,以便我可以进一步研究它吗?我使用paintcode将他们的草图模型集成到客户的应用程序中,因为没有这样的第3方工具可以针对特定的xamarin形式pcl或sap执行此操作,并且任何有帮助的东西,我很高兴你做出回应,引导我朝着一个好的方向前进!

以上是关于Xamarin.Forms PCL/SAP 自定义渲染,支持paintcode 3的主要内容,如果未能解决你的问题,请参考以下文章

在 Xamarin.Forms 中为 ContentPage 使用自定义基类

Xamarin.Forms MasterDetailPage 自定义渲染器

ReactiveUI 中的 Xamarin.Forms 控件是不是需要自定义绑定?

自定义控件的 Xamarin 数据绑定值计算为 Xamarin.Forms.Binding

Xamarin.Forms 中的 Droid 自定义选取器渲染器出错

Xamarin.forms 页面之间导航的自定义动画?