Added secure field (and examples) on iOS.
This commit is contained in:
Родитель
829cf20dfd
Коммит
041e8c29f1
|
@ -25,6 +25,9 @@ namespace HotUI.Samples {
|
|||
new MenuItem("ListPage1", ()=> new ListPage()),
|
||||
new MenuItem("ListPage2", ()=> new ListPage2()),
|
||||
new MenuItem("Insane Diff", ()=> new InsaneDiffPage()),
|
||||
new MenuItem("SecureFieldSample1", ()=> new SecureFieldSample1()),
|
||||
new MenuItem("SecureFieldSample2", ()=> new SecureFieldSample2()),
|
||||
new MenuItem("SecureFieldSample3", ()=> new SecureFieldSample3()),
|
||||
new MenuItem("SwiftUI Tutorial Section 1", ()=> new Section1()),
|
||||
new MenuItem("SwiftUI Tutorial Section 2", ()=> new Section2()),
|
||||
new MenuItem("SwiftUI Tutorial Section 3", ()=> new Section3()),
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
|
||||
struct ContentView : View {
|
||||
@State private var password: String = ""
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
SecureField("Enter a password", text: $password)
|
||||
Text("You entered: \(password)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
namespace HotUI.Samples
|
||||
{
|
||||
public class SecureFieldSample1 : View
|
||||
{
|
||||
/*[State]
|
||||
readonly MyBindingObject state;*/
|
||||
|
||||
readonly State<string> password = new State<string>("");
|
||||
|
||||
public SecureFieldSample1()
|
||||
{
|
||||
Body = () => new VStack
|
||||
{
|
||||
new SecureField("Enter a password", newValue => password.Value = newValue),
|
||||
new Text(() => $"{password.Value}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
|
||||
struct ContentView : View {
|
||||
@State private var password: String = ""
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
SecureField("Enter a password", text: $password)
|
||||
Text("You entered: \(password)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
namespace HotUI.Samples
|
||||
{
|
||||
public class SecureFieldSample2 : View
|
||||
{
|
||||
readonly State<string> password = new State<string>("");
|
||||
|
||||
public SecureFieldSample2()
|
||||
{
|
||||
Body = () => new VStack
|
||||
{
|
||||
new SecureField("Enter a password", value => password.Value = value),
|
||||
new Text(password.Value)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
|
||||
struct ContentView : View {
|
||||
@State private var password: String = ""
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
SecureField("Enter a password", text: $password)
|
||||
Text("You entered: \(password)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
namespace HotUI.Samples
|
||||
{
|
||||
public class SecureFieldSample3 : View
|
||||
{
|
||||
readonly State<string> password = new State<string>("");
|
||||
|
||||
public SecureFieldSample3()
|
||||
{
|
||||
Body = () => new VStack
|
||||
{
|
||||
new SecureField("Enter a password", password),
|
||||
new Text(password)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/*
|
||||
|
||||
struct ContentView : View {
|
||||
@State private var password: String = ""
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
SecureField("Enter a password", text: $password)
|
||||
Text("You entered: \(password)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
namespace HotUI.Samples
|
||||
{
|
||||
public class SecureFieldSample4 : View
|
||||
{
|
||||
readonly State<string> password = "";
|
||||
|
||||
public SecureFieldSample4()
|
||||
{
|
||||
Body = () => new VStack
|
||||
{
|
||||
new SecureField("Enter a password", password),
|
||||
new Text(password)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using UIKit;
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable ClassNeverInstantiated.Global
|
||||
|
||||
namespace HotUI.iOS
|
||||
{
|
||||
public class SecureFieldHandler : AbstractHandler<SecureField, UITextField>
|
||||
{
|
||||
public static readonly PropertyMapper<SecureField> Mapper = new PropertyMapper<SecureField>(ViewHandler.Mapper)
|
||||
{
|
||||
[nameof(SecureField.Text)] = MapTextProperty,
|
||||
[nameof(SecureField.Placeholder)] = MapPlaceholderProperty
|
||||
};
|
||||
|
||||
public SecureFieldHandler() : base(Mapper)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected override UITextField CreateView()
|
||||
{
|
||||
var textField = new UITextField();
|
||||
textField.SecureTextEntry = true;
|
||||
textField.EditingDidEnd += EntryHandler_EditingDidEnd;
|
||||
|
||||
textField.ShouldReturn = s =>
|
||||
{
|
||||
textField.ResignFirstResponder();
|
||||
return true;
|
||||
};
|
||||
|
||||
return textField;
|
||||
}
|
||||
|
||||
private void EntryHandler_EditingDidEnd(object sender, EventArgs e)
|
||||
{
|
||||
VirtualView?.OnCommit(TypedNativeView.Text);
|
||||
}
|
||||
|
||||
public static void MapTextProperty(IViewHandler viewHandler, SecureField virtualView)
|
||||
{
|
||||
var nativeView = (UITextField) viewHandler.NativeView;
|
||||
nativeView.Text = virtualView.Text;
|
||||
nativeView.SizeToFit();
|
||||
}
|
||||
|
||||
public static void MapPlaceholderProperty(IViewHandler viewHandler, SecureField virtualView)
|
||||
{
|
||||
var nativeView = (UITextField) viewHandler.NativeView;
|
||||
nativeView.Placeholder = virtualView.Placeholder;
|
||||
nativeView.SizeToFit();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@
|
|||
<Compile Include="Extensions\CoreGraphicsExtensions.cs" />
|
||||
<Compile Include="Handlers\AbstractLayoutHandler.cs" />
|
||||
<Compile Include="Handlers\HStackHandler.cs" />
|
||||
<Compile Include="Handlers\SecureFieldHandler.cs" />
|
||||
<Compile Include="Handlers\SpacerHandler.cs" />
|
||||
<Compile Include="Handlers\VStackHandler.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace HotUI.iOS {
|
|||
hasInit = true;
|
||||
Registrar.Handlers.Register<Button, ButtonHandler> ();
|
||||
Registrar.Handlers.Register<TextField, TextFieldHandler> ();
|
||||
Registrar.Handlers.Register<SecureField, SecureFieldHandler>();
|
||||
Registrar.Handlers.Register<Text, TextHandler> ();
|
||||
Registrar.Handlers.Register<Toggle, ToggleHandler>();
|
||||
Registrar.Handlers.Register<VStack, VStackHandler> ();
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
namespace HotUI {
|
||||
public class SecureField : View
|
||||
{
|
||||
public SecureField ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public SecureField (string placeholder, Action<string> onCommit = null) : base (true)
|
||||
{
|
||||
Placeholder = placeholder;
|
||||
OnCommit = onCommit;
|
||||
}
|
||||
|
||||
public SecureField (string text = null, string placeholder = null, Action<string> onCommit = null) : base (true)
|
||||
{
|
||||
Text = text;
|
||||
Placeholder = placeholder;
|
||||
OnCommit = onCommit;
|
||||
}
|
||||
|
||||
public SecureField (Func<string> builder, string placeholder = null, Action<string> onCommit = null )
|
||||
{
|
||||
TextBinding = builder;
|
||||
Placeholder = placeholder;
|
||||
OnCommit = onCommit;
|
||||
}
|
||||
|
||||
string text;
|
||||
public string Text {
|
||||
get => text;
|
||||
private set => this.SetValue (State, ref text, value, ViewPropertyChanged);
|
||||
}
|
||||
|
||||
public Func<string> TextBinding { get; private set; }
|
||||
protected override void WillUpdateView ()
|
||||
{
|
||||
base.WillUpdateView ();
|
||||
if (TextBinding != null) {
|
||||
State.StartProperty ();
|
||||
var text = TextBinding.Invoke ();
|
||||
var props = State.EndProperty ();
|
||||
var propCount = props.Length;
|
||||
if (propCount > 0) {
|
||||
State.BindingState.AddViewProperty (props, (s,o)=> Text = TextBinding.Invoke());
|
||||
}
|
||||
Text = text;
|
||||
}
|
||||
}
|
||||
|
||||
string placeholder;
|
||||
public string Placeholder {
|
||||
get => placeholder;
|
||||
set => this.SetValue (State, ref placeholder, value, ViewPropertyChanged);
|
||||
}
|
||||
|
||||
public Action<string> OnCommit { get; set; }
|
||||
}
|
||||
}
|
|
@ -17,14 +17,19 @@ namespace HotUI {
|
|||
Value = value;
|
||||
}
|
||||
public State ()
|
||||
{
|
||||
{
|
||||
|
||||
}
|
||||
public T Value {
|
||||
get => GetProperty<T> ();
|
||||
set => SetProperty (value);
|
||||
}
|
||||
|
||||
public static implicit operator T(State<T> state) => state.Value;
|
||||
public static implicit operator Action<T>(State<T> state) => value => state.Value = value;
|
||||
public static implicit operator State<T>(T value) => new State<T>(value);
|
||||
}
|
||||
|
||||
public class StateBuilder : IDisposable {
|
||||
static List<State> currentStates = new List<State> ();
|
||||
public static State CurrentState => currentStates.LastOrDefault ();
|
||||
|
|
Загрузка…
Ссылка в новой задаче