Nu am mai scris de ceva vreme pe blog si nu pot spune ca din lipsa de timp, ci pur si simplu din lipsa de organizare a lui.
Acest articol este despre programare mobile, folosind Xamarin-ul cu Visual Studio 2019, pentru ca este cross platform: intr-o proportie destul de mare, scriem codul o singura data pentru toate sistemele de operare mobile (noi vom merge pe iOs si Android).
Spun intr-o proportie destul de mare, deoarce sunt anumite parti care trebuie scrise separate, pentru fiecare OS.
Vom scrie codul care ne da posibilitatea sa vedem cee ace am scris intr-un textbox tip parola.
In primul rand cream un nou proiect -> MyProject. Acesta va avea in final 3 proiecte: MyProject, MyProject.Android si MyProject.iOS.
Apoi vom crea un folder nou (Effects) in toate cele 3 proiecte din solutia noastra. In fiecare din cele 3 foldere, vom crea o noua clasa cu numele ShowHidePassEffects.
Incepem cu clasa din proiectul MyProject. Aceasta va avea urmatorul continut:
using Xamarin.Forms;
namespace MyProject.Effects
{
public class ShowHidePassEffect : RoutingEffect
{
public string EntryText { get; set; }
public ShowHidePassEffect() : base("Xamarin.ShowHidePassEffect") { }
}
}
Clasa din proiectul MyProject.Android va avea un continut mai mare:
using Android.Text.Method;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(MyProject
.Droid.Effects.ShowHidePassEffect), "ShowHidePassEffect")]
namespace MyProject.Droid.Effects
{
public class ShowHidePassEffect : PlatformEffect
{
protected override void OnAttached()
{
ConfigureControl();
}
protected override void OnDetached()
{
}
private void ConfigureControl()
{
EditText editText = ((EditText)Control);
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.HidePass, 0);
editText.SetOnTouchListener(new OnDrawableTouchListener());
}
}
public class OnDrawableTouchListener : Java.Lang.Object, Android.Views.View.IOnTouchListener
{
public bool OnTouch(Android.Views.View v, MotionEvent e)
{
if (v is EditText && e.Action == MotionEventActions.Up)
{
EditText editText = (EditText)v;
if (e.RawX >= (editText.Right - editText.GetCompoundDrawables()[2].Bounds.Width()))
{
if (editText.TransformationMethod == null)
{
editText.TransformationMethod = PasswordTransformationMethod.Instance;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.HidePass, 0);
editText.SetSelection(editText.Length());
}
else
{
editText.TransformationMethod = null;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, Resource.Drawable.ShowPass, 0);
editText.SetSelection(editText.Length());
}
return true;
}
}
return false;
}
}
}
In final, clasa din proiectul MyProject.iOS:
using System;
using MyProject.iOS.Effects;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ResolutionGroupName("Xamarin")]
[assembly: ExportEffect(typeof(ShowHidePassEffect), "ShowHidePassEffect")]
namespace MyProject.iOS.Effects
{
public class ShowHidePassEffect : PlatformEffect
{
protected override void OnAttached()
{
ConfigureControl();
}
protected override void OnDetached()
{
}
private void ConfigureControl()
{
if (Control != null)
{
UITextField vUpdatedEntry = (UITextField)Control;
var buttonRect = UIButton.FromType(UIButtonType.Custom);
buttonRect.SetImage(new UIImage("HidePass"), UIControlState.Normal);
buttonRect.TouchUpInside += (object sender, EventArgs e1) =>
{
if (vUpdatedEntry.SecureTextEntry)
{
vUpdatedEntry.SecureTextEntry = false;
buttonRect.SetImage(new UIImage("ShowPass"), UIControlState.Normal);
}
else
{
vUpdatedEntry.SecureTextEntry = true;
buttonRect.SetImage(new UIImage("HidePass"), UIControlState.Normal);
}
};
vUpdatedEntry.ShouldChangeCharacters += (textField, range, replacementString) =>
{
string text = vUpdatedEntry.Text;
var result = text.Substring(0, (int)range.Location) + replacementString + text.Substring((int)range.Location + (int)range.Length);
vUpdatedEntry.Text = result;
return false;
};
buttonRect.Frame = new CoreGraphics.CGRect(10.0f, 0.0f, 15.0f, 15.0f);
buttonRect.ContentMode = UIViewContentMode.Right;
UIView paddingViewRight = new UIView(new System.Drawing.RectangleF(5.0f, -5.0f, 30.0f, 18.0f));
paddingViewRight.Add(buttonRect);
paddingViewRight.ContentMode = UIViewContentMode.BottomRight;
vUpdatedEntry.LeftView = paddingViewRight;
vUpdatedEntry.LeftViewMode = UITextFieldViewMode.Always;
Control.Layer.CornerRadius = 4;
Control.Layer.BorderColor = new CoreGraphics.CGColor(255, 255, 255);
Control.Layer.MasksToBounds = true;
vUpdatedEntry.TextAlignment = UITextAlignment.Left;
}
}
}
}
Mai trebuie sa incarcam si cele 2 imagini de care avem nevoie: HidePass.png si ShowPass.png (pentru proiectul Android: Resources/drawable; pentru iOS: Resources).
Acum, avand cele 3 clase de mai sus si imaginile incarcate, ne intoarcem la proiectul MyProject. Tot ce mai avem de facut este sa aplicam efectul direct textbox-ului
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ef="clr-namespace:MyProject.Effects"
x:Class="MyProject.LoginPage">
<StackLayout>
<Grid Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackLayout Margin="10,0">
<Label Text="Log Into Your Account"/>
<Entry x:Name="UserName"
Placeholder="User Name"/>
<Entry x:Name="Password"
IsPassword="true"
Placeholder="Password">
<Entry.Effects>
<ef:ShowHidePassEffect />
</Entry.Effects>
</Entry>
<Button x:Name="btnLogin"
Text="Login"/>
</StackLayout>
</Grid>
</StackLayout>
</ContentPage>
Cam asta ar fi tot. Bafta!