Como usar controles personalizados com o iOS Designer

Aviso

O Designer do iOS foi preterido no Visual Studio 2019 versão 16.8 e no Visual Studio 2019 para Mac versão 8.8 e removido no Visual Studio 2019 versão 16.9 e Visual Studio para Mac versão 8.9. A maneira recomendada de criar interfaces de usuário do iOS é diretamente em um Mac executando o Xcode. Para obter mais informações, consulte Criando interfaces do usuário com Xcode.

Requisitos

O Designer do Xamarin para iOS está disponível no Visual Studio para Mac e no Visual Studio 2017 e posterior no Windows.

Este guia pressupõe uma familiaridade com o conteúdo abordado nos guias de Introdução.

Passo a passo

Importante

A partir do Xamarin.Studio 5.5, a maneira como os controles personalizados são criados é ligeiramente diferente das versões anteriores. Para criar um controle personalizado, a IComponent interface é necessária (com os métodos de implementação associados) ou a classe pode ser anotada com [DesignTimeVisible(true)]. O último método está sendo usado no exemplo passo a passo a seguir.

  1. Crie uma nova solução com base no modelo C# do Aplicativo > de Exibição Única do Aplicativo > iOS>, nomeie-a ScratchTickete continue por meio do assistente Novo Projeto:

    Criar uma nova solução

  2. Crie um novo arquivo de classe vazio chamado ScratchTicketView:

    Criar uma nova classe ScratchTicketView

  3. Adicione o seguinte código para a ScratchTicketView classe :

    using System;
    using System.ComponentModel;
    using CoreGraphics;
    using Foundation;
    using UIKit;
    
    namespace ScratchTicket
    {
        [Register("ScratchTicketView"), DesignTimeVisible(true)]
        public class ScratchTicketView : UIView
        {
            CGPath path;
            CGPoint initialPoint;
            CGPoint latestPoint;
            bool startNewPath = false;
            UIImage image;
    
            [Export("Image"), Browsable(true)]
            public UIImage Image
            {
                get { return image; }
                set
                {
                    image = value;
                    SetNeedsDisplay();
                }
            }
    
            public ScratchTicketView(IntPtr p)
                : base(p)
            {
                Initialize();
            }
    
            public ScratchTicketView()
            {
                Initialize();
            }
    
            void Initialize()
            {
                initialPoint = CGPoint.Empty;
                latestPoint = CGPoint.Empty;
                BackgroundColor = UIColor.Clear;
                Opaque = false;
                path = new CGPath();
                SetNeedsDisplay();
            }
    
            public override void TouchesBegan(NSSet touches, UIEvent evt)
            {
                base.TouchesBegan(touches, evt);
    
                var touch = touches.AnyObject as UITouch;
    
                if (touch != null)
                {
                    initialPoint = touch.LocationInView(this);
                }
            }
    
            public override void TouchesMoved(NSSet touches, UIEvent evt)
            {
                base.TouchesMoved(touches, evt);
    
                var touch = touches.AnyObject as UITouch;
    
                if (touch != null)
                {
                    latestPoint = touch.LocationInView(this);
                    SetNeedsDisplay();
                }
            }
    
            public override void TouchesEnded(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
                startNewPath = true;
            }
    
            public override void Draw(CGRect rect)
            {
                base.Draw(rect);
    
                using (var g = UIGraphics.GetCurrentContext())
                {
                    if (image != null)
                        g.SetFillColor((UIColor.FromPatternImage(image).CGColor));
                    else
                        g.SetFillColor(UIColor.LightGray.CGColor);
                    g.FillRect(rect);
    
                    if (!initialPoint.IsEmpty)
                    {
                        g.SetLineWidth(20);
                        g.SetBlendMode(CGBlendMode.Clear);
                        UIColor.Clear.SetColor();
    
                        if (path.IsEmpty || startNewPath)
                        {
                            path.AddLines(new CGPoint[] { initialPoint, latestPoint });
                            startNewPath = false;
                        }
                        else
                        {
                            path.AddLineToPoint(latestPoint);
                        }
    
                        g.SetLineCap(CGLineCap.Round);
                        g.AddPath(path);
                        g.DrawPath(CGPathDrawingMode.Stroke);
                    }
                }
            }
        }
    }
    
  4. Adicione os FillTexture.pngarquivos e Monkey.pngFillTexture2.png (disponíveis do GitHub) à pasta Recursos.

  5. Clique duas vezes no Main.storyboard arquivo para abri-lo no designer:

    O Designer do iOS

  6. Arraste/solte um Modo de Exibição de Imagem da Caixa de Ferramentas para o modo de exibição no storyboard.

    Um modo de exibição de imagem adicionado ao layout

  7. Selecione o Modo de Exibição de Imagem e altere sua propriedade Image para Monkey.png.

    Definindo a propriedade Image View Image como Monkey.png

  8. Como estamos usando classes de tamanho, precisaremos restringir essa exibição de imagem. Clique na imagem duas vezes para colocá-la no modo de restrição. Vamos restringi-lo ao centro clicando no identificador de fixação central e alinhando-o vertical e horizontalmente:

    Centralizando a imagem

  9. Para restringir a altura e a largura, clique nas alças de fixação de tamanho (as alças em forma de 'osso') e selecione largura e altura, respectivamente:

    Adicionando restrições

  10. Atualize o quadro com base nas restrições clicando no botão atualizar na barra de ferramentas:

    A barra de ferramentas Restrições

  11. Em seguida, compile o projeto para que a Exibição de tíquete de rascunho apareça em Componentes Personalizados na Caixa de Ferramentas:

    A caixa de ferramentas Componentes Personalizados

  12. Arraste e solte um Modo de Exibição de Tíquete Zero para que ele apareça sobre a imagem do macaco. Ajuste as alças de arrastar para que a Exibição de tíquete de rascunho cubra completamente o macaco, conforme mostrado abaixo:

    Um modo de exibição de tíquete de rascunho sobre o modo de exibição de imagem

  13. Restrinja o Modo de Exibição de Tíquete Zero ao Modo de Exibição de Imagem desenhando um retângulo delimitador para selecionar ambas as exibições. Selecione as opções para restringi-lo aos quadros Largura, Altura, Centro e Meio e atualizar quadros com base em restrições, conforme mostrado abaixo:

    Centralizando e adicionando restrições

  14. Execute o aplicativo e "risque" a imagem para revelar o macaco.

    Uma execução de aplicativo de exemplo

Adicionando propriedades de Design-Time

O designer também inclui suporte de tempo de design para controles personalizados de tipo de propriedade numérico, enumeração, cadeia de caracteres, bool, CGSize, UIColor e UIImage. Para demonstrar, vamos adicionar uma propriedade ao ScratchTicketView para definir a imagem que está "riscado".

Adicione o seguinte código à ScratchTicketView classe para a propriedade :

[Export("Image"), Browsable(true)]
public UIImage Image
{
    get { return image; }
    set {
            image = value;
              SetNeedsDisplay ();
        }
}

Talvez também queiramos adicionar uma marcar nula ao Draw método , da seguinte forma:

public override void Draw(CGRect rect)
{
    base.Draw(rect);

    using (var g = UIGraphics.GetCurrentContext())
    {
        if (image != null)
            g.SetFillColor ((UIColor.FromPatternImage (image).CGColor));
        else
            g.SetFillColor (UIColor.LightGray.CGColor);

        g.FillRect(rect);

        if (!initialPoint.IsEmpty)
        {
             g.SetLineWidth(20);
             g.SetBlendMode(CGBlendMode.Clear);
             UIColor.Clear.SetColor();

             if (path.IsEmpty || startNewPath)
             {
                 path.AddLines(new CGPoint[] { initialPoint, latestPoint });
                 startNewPath = false;
             }
             else
             {
                 path.AddLineToPoint(latestPoint);
             }

             g.SetLineCap(CGLineCap.Round);
             g.AddPath(path);
             g.DrawPath(CGPathDrawingMode.Stroke);
        }
    }
}

Incluir um ExportAttribute e um BrowsableAttribute com o argumento definido como true resulta na propriedade que está sendo exibida no painel Propriedade do designer. Alterar a propriedade para outra imagem incluída no projeto, como FillTexture2.png, resulta na atualização do controle em tempo de design, conforme mostrado abaixo:

Editando propriedades de Tempo de Design

Resumo

Neste artigo, explicamos como criar um controle personalizado, bem como consumi-lo em um aplicativo iOS usando o designer do iOS. Vimos como criar e criar o controle para disponibilizá-lo para um aplicativo na Caixa de Ferramentas do designer. Além disso, analisamos como implementar o controle de modo que ele seja renderizado corretamente em tempo de design e runtime, bem como como expor propriedades de controle personalizadas no designer.