Vytváření vlastních ovládacích prvků v Xamarin.Mac
Při práci s jazykem C# a .NET v aplikaci Xamarin.Mac máte přístup ke stejným uživatelským ovládacím prvkům, které vývojář pracuje v Objective-Caplikaci Swift a Xcode. Vzhledem k tomu, že se Xamarin.Mac integruje přímo s Xcode, můžete pomocí Tvůrce rozhraní Xcode vytvářet a udržovat uživatelské ovládací prvky (nebo je volitelně vytvářet přímo v kódu jazyka C#).
I když macOS nabízí celou řadu integrovaných uživatelských ovládacích prvků, možná budete muset vytvořit vlastní ovládací prvek, který poskytuje funkce, které nejsou předdefinované nebo odpovídají vlastnímu motivu uživatelského rozhraní (například hernímu rozhraní).
V tomto článku se podíváme na základy vytváření opakovaně použitelného vlastního ovládacího prvku uživatelského rozhraní v aplikaci Xamarin.Mac. Důrazně doporučujeme, abyste si nejprve prošli článek Hello, Mac , konkrétně úvod do Xcode a Tvůrce rozhraní a výstupy a akce , protože se zabývá klíčovými koncepty a technikami, které budeme používat v tomto článku.
Možná se také budete chtít podívat na oddíly v dokumentu Interní dokumenty Xamarin.Mac pro zveřejnění tříd a metod Objective-Cjazyka C#. Vysvětluje také, které Register
příkazy a Export
které se používají k připojení tříd jazyka C# k Objective-C objektům a prvkům uživatelského rozhraní.
Úvod do vlastních ovládacích prvků
Jak je uvedeno výše, může docházet k tomu, že potřebujete vytvořit opakovaně použitelný vlastní ovládací prvek uživatelského rozhraní, který poskytuje jedinečné funkce uživatelského rozhraní vaší aplikace Xamarin.Mac nebo vytvořit vlastní motiv uživatelského rozhraní (například herní rozhraní).
V těchto situacích můžete snadno dědit NSControl
a vytvořit vlastní nástroj, který se dá přidat do uživatelského rozhraní aplikace prostřednictvím kódu jazyka C# nebo prostřednictvím Tvůrce rozhraní Xcode. Děděním z NSControl
vlastního ovládacího prvku se automaticky zobrazí všechny standardní funkce, které má integrovaný ovládací prvek uživatelského rozhraní (například NSButton
).
Pokud váš vlastní ovládací prvek uživatelského rozhraní jenom zobrazuje informace (například vlastní grafování a grafický nástroj), můžete chtít dědit místo NSView
NSControl
.
Bez ohledu na to, která základní třída se používá, je základní postup vytvoření vlastního ovládacího prvku stejný.
V tomto článku vytvoříte vlastní komponentu Flip Switch, která poskytuje jedinečný motiv uživatelského rozhraní a příklad vytvoření plně funkčního vlastního ovládacího prvku uživatelského rozhraní.
Sestavení vlastního ovládacího prvku
Vzhledem k tomu, že vlastní ovládací prvek, který vytváříme, bude reagovat na vstup uživatele (kliknutí levým tlačítkem myši), budeme dědit z NSControl
. Tímto způsobem bude mít náš vlastní ovládací prvek automaticky všechny standardní funkce, které má integrovaný ovládací prvek uživatelského rozhraní a odpovídá jako standardní ovládací prvek macOS.
V Visual Studio pro Mac otevřete projekt Xamarin.Mac, pro který chcete vytvořit vlastní ovládací prvek uživatelského rozhraní (nebo vytvořit nový). Přidejte novou třídu a zavolejte ji NSFlipSwitch
:
Dále upravte NSFlipSwitch.cs
třídu a udělejte ji takto:
using Foundation;
using System;
using System.CodeDom.Compiler;
using AppKit;
using CoreGraphics;
namespace MacCustomControl
{
[Register("NSFlipSwitch")]
public class NSFlipSwitch : NSControl
{
#region Private Variables
private bool _value = false;
#endregion
#region Computed Properties
public bool Value {
get { return _value; }
set {
// Save value and force a redraw
_value = value;
NeedsDisplay = true;
}
}
#endregion
#region Constructors
public NSFlipSwitch ()
{
// Init
Initialize();
}
public NSFlipSwitch (IntPtr handle) : base (handle)
{
// Init
Initialize();
}
[Export ("initWithFrame:")]
public NSFlipSwitch (CGRect frameRect) : base(frameRect) {
// Init
Initialize();
}
private void Initialize() {
this.WantsLayer = true;
this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
}
#endregion
#region Draw Methods
public override void DrawRect (CGRect dirtyRect)
{
base.DrawRect (dirtyRect);
// Use Core Graphic routines to draw our UI
...
}
#endregion
#region Private Methods
private void FlipSwitchState() {
// Update state
Value = !Value;
}
#endregion
}
}
První věc, kterou si můžete všimnout vlastní třídy v tom, že dědíme a NSControl
používáme příkaz Register k zveřejnění této třídy Objective-C a Xcode Interface Builderu:
[Register("NSFlipSwitch")]
public class NSFlipSwitch : NSControl
V následujících částech se podrobněji podíváme na zbytek výše uvedeného kódu.
Sledování stavu ovládacího prvku
Vzhledem k tomu, že náš vlastní ovládací prvek je přepínač, potřebujeme způsob, jak sledovat stav zapnuto/vypnuto přepínače. Zpracováváme to následujícím kódem v NSFlipSwitch
:
private bool _value = false;
...
public bool Value {
get { return _value; }
set {
// Save value and force a redraw
_value = value;
NeedsDisplay = true;
}
}
Když se stav přepínače změní, potřebujeme způsob, jak aktualizovat uživatelské rozhraní. Děláme to vynucením ovládacího prvku překreslit jeho uživatelské rozhraní pomocí NeedsDisplay = true
.
Pokud náš ovládací prvek vyžadoval více toho, že jeden stav zapnuto/vypnuto (například přepínač s více stavy se 3 pozicemi), mohli jsme k sledování stavu použít výčt . V našem příkladu se provede jednoduchá logická hodnota .
Přidali jsme také pomocnou metodu pro prohození stavu přepínače mezi zapnutým a vypnutým:
private void FlipSwitchState() {
// Update state
Value = !Value;
}
Později tuto pomocnou třídu rozšíříme, abychom volajícímu informovali o změně stavu přepínačů.
Kreslení rozhraní ovládacího prvku
K vykreslení uživatelského rozhraní vlastního ovládacího prvku za běhu použijeme rutiny kreslení grafického objektu Core Graphic. Než to uděláme, musíme pro kontrolu zapnout vrstvy. Provedeme to pomocí následující privátní metody:
private void Initialize() {
this.WantsLayer = true;
this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
}
Tato metoda se volá z každého konstruktoru ovládacího prvku, aby se zajistilo, že je ovládací prvek správně nakonfigurovaný. Příklad:
public NSFlipSwitch (IntPtr handle) : base (handle)
{
// Init
Initialize();
}
Dále potřebujeme přepsat metodu DrawRect
a přidat základní grafické rutiny pro vykreslení ovládacího prvku:
public override void DrawRect (CGRect dirtyRect)
{
base.DrawRect (dirtyRect);
// Use Core Graphic routines to draw our UI
...
}
Vizuální reprezentaci ovládacího prvku upravíme, když se změní jeho stav (například přechod z zapnuto na vypnuto). Kdykoli se stav změní, můžeme pomocí NeedsDisplay = true
příkazu vynutit překreslení ovládacího prvku pro nový stav.
Reagování na vstup uživatele
Do vlastního ovládacího prvku můžeme přidat uživatelský vstup dvěma základními způsoby: Přepsat rutiny zpracování myši nebo rozpoznávání gest. Kterou metodu použijeme, bude založená na funkcích vyžadovaných naší kontrolou.
Důležité
U jakéhokoliv vlastního ovládacího prvku, který vytvoříte, byste měli použít buď metody přepsání, nebo rozpoznávání gest, ale ne obojí najednou, jak můžou vzájemně kolidovat.
Zpracování uživatelského vstupu pomocí metod přepsání
Objekty, které dědí z NSControl
(nebo NSView
) mají několik metod přepsání pro zpracování vstupu myši nebo klávesnice. V našem příkladu chceme překlopit stav přepínače mezi zapnutým a vypnutým , když uživatel klikne na ovládací prvek pomocí levého tlačítka myši. Do třídy můžeme přidat následující metody NSFlipSwitch
přepsání, které to zvládnou:
#region Mouse Handling Methods
// --------------------------------------------------------------------------------
// Handle mouse with Override Methods.
// NOTE: Use either this method or Gesture Recognizers, NOT both!
// --------------------------------------------------------------------------------
public override void MouseDown (NSEvent theEvent)
{
base.MouseDown (theEvent);
FlipSwitchState ();
}
public override void MouseDragged (NSEvent theEvent)
{
base.MouseDragged (theEvent);
}
public override void MouseUp (NSEvent theEvent)
{
base.MouseUp (theEvent);
}
public override void MouseMoved (NSEvent theEvent)
{
base.MouseMoved (theEvent);
}
## endregion
Ve výše uvedeném kódu voláme metodu FlipSwitchState
(definovanou výše), která překlopí stav zapnutí/vypnutí přepínače v MouseDown
metodě. To také vynutí překreslit ovládací prvek tak, aby odrážel aktuální stav.
Zpracování uživatelského vstupu pomocí rozpoznávání gest
Volitelně můžete pomocí rozpoznávání gest zpracovat uživatele, který pracuje s ovládacím prvku. Odeberte přepsání přidaná výše, upravte metodu Initialize
a udělejte ji takto:
private void Initialize() {
this.WantsLayer = true;
this.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
// --------------------------------------------------------------------------------
// Handle mouse with Gesture Recognizers.
// NOTE: Use either this method or the Override Methods, NOT both!
// --------------------------------------------------------------------------------
var click = new NSClickGestureRecognizer (() => {
FlipSwitchState();
});
AddGestureRecognizer (click);
}
Tady vytváříme novou NSClickGestureRecognizer
metodu a voláme metodu FlipSwitchState
, abychom změnili stav přepínače, když na něj uživatel klikne pomocí levého tlačítka myši. Metoda AddGestureRecognizer (click)
přidá do ovládacího prvku rozpoznávání gest.
To, kterou metodu používáme, opět závisí na tom, čeho se snažíme dosáhnout pomocí vlastního ovládacího prvku. Pokud potřebujeme přístup nízké úrovně k interakci uživatele, použijte metody přepsání. Pokud potřebujeme předdefinované funkce, například kliknutí myší, použijte rozpoznávání gest.
Reakce na události změny stavu
Když uživatel změní stav vlastního ovládacího prvku, potřebujeme způsob, jak reagovat na změnu stavu v kódu (například udělat něco po kliknutí na vlastní tlačítko).
Pokud chcete tuto funkci poskytnout, upravte NSFlipSwitch
třídu a přidejte následující kód:
#region Events
public event EventHandler ValueChanged;
internal void RaiseValueChanged() {
if (this.ValueChanged != null)
this.ValueChanged (this, EventArgs.Empty);
// Perform any action bound to the control from Interface Builder
// via an Action.
if (this.Action !=null)
NSApplication.SharedApplication.SendAction (this.Action, this.Target, this);
}
## endregion
Dále upravte metodu FlipSwitchState
a nastavte ji jako následující:
private void FlipSwitchState() {
// Update state
Value = !Value;
RaiseValueChanged ();
}
Nejprve poskytneme ValueChanged
událost, do které můžeme přidat obslužnou rutinu v kódu jazyka C#, abychom mohli provést akci, když uživatel změní stav přepínače.
Za druhé, protože náš vlastní ovládací prvek dědí z NSControl
, má automaticky akci , kterou lze přiřadit v Xcode Interface Builder. K volání této akce při změně stavu použijeme následující kód:
if (this.Action !=null)
NSApplication.SharedApplication.SendAction (this.Action, this.Target, this);
Nejprve zkontrolujeme, jestli je k ovládacímu prvku přiřazená akce . Dále zavoláme akci , pokud byla definována.
Použití vlastního ovládacího prvku
Pomocí plně definovaného vlastního ovládacího prvku ho můžeme přidat do uživatelského rozhraní aplikace Xamarin.Mac pomocí kódu jazyka C# nebo v Tvůrci rozhraní Xcode.
Pokud chcete přidat ovládací prvek pomocí Tvůrce rozhraní, nejprve proveďte čisté sestavení projektu Xamarin.Mac a poklikáním otevřete Main.storyboard
soubor v Tvůrci rozhraní pro úpravy:
V dalším kroku přetáhněte Custom View
návrh uživatelského rozhraní:
Pokud je vlastní zobrazení stále vybrané, přepněte na Kontrolu identit a změňte třídu zobrazení naNSFlipSwitch
:
Přepněte do Editoru asistentů a vytvořte výstup pro vlastní ovládací prvek (ujistěte se, že ho chcete svázat v ViewController.h
souboru a ne v .m
souboru):
Uložte změny, vraťte se do Visual Studio pro Mac a povolte synchronizaci změn. ViewController.cs
Upravte soubor a udělejte metodu ViewDidLoad
takto:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Do any additional setup after loading the view.
OptionTwo.ValueChanged += (sender, e) => {
// Display the state of the option switch
Console.WriteLine("Option Two: {0}", OptionTwo.Value);
};
}
Zde odpovíme na ValueChanged
událost, kterou jsme definovali výše ve NSFlipSwitch
třídě, a zapíšeme aktuální hodnotu , když uživatel klikne na ovládací prvek.
Volitelně se můžeme vrátit do Tvůrce rozhraní a definovat akci ovládacího prvku:
Znovu upravte ViewController.cs
soubor a přidejte následující metodu:
partial void OptionTwoFlipped (Foundation.NSObject sender) {
// Display the state of the option switch
Console.WriteLine("Option Two: {0}", OptionTwo.Value);
}
Důležité
V Tvůrci rozhraní byste měli použít buď událost , nebo definovat akci , ale neměli byste současně používat obě metody, nebo by mohly být v konfliktu s ostatními.
Shrnutí
Tento článek se podrobně podíval na vytvoření opakovaně použitelného vlastního ovládacího prvku uživatelského rozhraní v aplikaci Xamarin.Mac. Viděli jsme, jak nakreslit uživatelské rozhraní vlastních ovládacích prvků, dva hlavní způsoby reakce na vstup myši a uživatele a jak vystavit nový ovládací prvek akcím v Tvůrci rozhraní Xcode.