Today, I am going to create a custom ImageEntry. Whenever we are creating a login page, we can not understand which control should we use for submitting the username and password. I am creating a custom control today to solve this problem. We don't need to write more code with its use and page design will also look good.
So, let's start.
Firstly, we need to create a ContentView and set the image and entry.
- <ContentView.Content>
- <StackLayout Spacing="2">
- <StackLayout Orientation="Horizontal" Spacing="0">
- <local:CustomImage x:Name="LIcon" Source="{Binding LImageSource,Mode=TwoWay}" IsVisible="False"
- HorizontalOptions="Start" HeightRequest="25" WidthRequest="25"/>
- <local:MyEntry x:Name="imgEntry" PlaceholderColor="Red" Text="{Binding Text, Mode=TwoWay}"
- HorizontalOptions="FillAndExpand"/>
- <local:CustomImage x:Name="RIcon" Source="{Binding RImageSourceProperty,Mode=TwoWay}" IsVisible="False"
- HorizontalOptions="End" HeightRequest="25" WidthRequest="25"/>
- </StackLayout>
- <BoxView x:Name="BottomBorder" BackgroundColor="Gray" HeightRequest="1" Margin="0" HorizontalOptions="FillAndExpand"/>
- <BoxView x:Name="HiddenBottomBorder" BackgroundColor="Gray" HeightRequest="5" Margin="0" WidthRequest="0" HorizontalOptions="Center"/>
- </StackLayout>
- </ContentView.Content>
-
Then, we are using the BindableProperty to create this custom control.
- public partial class ImageEntry: ContentView {
- public static BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(ImageEntry), defaultBindingMode: BindingMode.TwoWay);
- public static BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(ImageEntry), defaultBindingMode: BindingMode.TwoWay, propertyChanged: (bindable, oldVal, newval) => {
- var matEntry = (ImageEntry) bindable;
- matEntry.imgEntry.Placeholder = (string) newval;
- });
- public static BindableProperty IsPasswordProperty = BindableProperty.Create(nameof(IsPassword), typeof(bool), typeof(ImageEntry), defaultValue: false, propertyChanged: (bindable, oldVal, newVal) => {
- var matEntry = (ImageEntry) bindable;
- matEntry.imgEntry.IsPassword = (bool) newVal;
- });
- public static BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(ImageEntry), defaultValue: Keyboard.Default, propertyChanged: (bindable, oldVal, newVal) => {
- var matEntry = (ImageEntry) bindable;
- matEntry.imgEntry.Keyboard = (Keyboard) newVal;
- });
- public static BindableProperty AccentColorProperty = BindableProperty.Create(nameof(AccentColor), typeof(Color), typeof(ImageEntry), defaultValue: Color.Accent);
- public static readonly BindableProperty LImageSourceProperty = BindableProperty.Create(nameof(LImageSource), typeof(ImageSource), typeof(ImageEntry), defaultBindingMode: BindingMode.TwoWay, propertyChanged: (bindable, oldVal, newVal) => {
- var matEntry = (ImageEntry) bindable;
- matEntry.LIcon.Source = (ImageSource) newVal;
- });
- public static readonly BindableProperty RImageSourceProperty = BindableProperty.Create(nameof(RImageSource), typeof(ImageSource), typeof(ImageEntry), defaultBindingMode: BindingMode.TwoWay, propertyChanged: (bindable, oldVal, newVal) => {
- var matEntry = (ImageEntry) bindable;
- matEntry.RIcon.Source = (ImageSource) newVal;
- });
- public static readonly BindableProperty ImageAlignmentProperty = BindableProperty.Create(nameof(ImageAlignment), typeof(eImageAlignment), typeof(ImageEntry), defaultValue: eImageAlignment.None, propertyChanged: OnImageAlignmentChanged);
- public ImageSource RImageSource {
- get {
- return (ImageSource) GetValue(RImageSourceProperty);
- }
- set {
- SetValue(RImageSourceProperty, value);
- }
- }
- public ImageSource LImageSource {
- get {
- return (ImageSource) GetValue(LImageSourceProperty);
- }
- set {
- SetValue(LImageSourceProperty, value);
- }
- }
- public Color AccentColor {
- get {
- return (Color) GetValue(AccentColorProperty);
- }
- set {
- SetValue(AccentColorProperty, value);
- }
- }
- public Keyboard Keyboard {
- get {
- return (Keyboard) GetValue(KeyboardProperty);
- }
- set {
- SetValue(KeyboardProperty, value);
- }
- }
- public bool IsPassword {
- get {
- return (bool) GetValue(IsPasswordProperty);
- }
- set {
- SetValue(IsPasswordProperty, value);
- }
- }
- public string Text {
- get {
- return (string) GetValue(TextProperty);
- }
- set {
- SetValue(TextProperty, value);
- }
- }
- public string Placeholder {
- get {
- return (string) GetValue(PlaceholderProperty);
- }
- set {
- SetValue(PlaceholderProperty, value);
- }
- }
- public eImageAlignment ImageAlignment {
- get => (eImageAlignment) GetValue(ImageAlignmentProperty);
- set => SetValue(ImageAlignmentProperty, value);
- }
- public event EventHandler LeftImageClicked;
- public virtual void LeftImageOn_Clicked(object sender, EventArgs e) {
- LeftImageClicked ? .Invoke(sender, e);
- }
- public event EventHandler RightImageClicked;
- public virtual void RightImageOn_Clicked(object sender, EventArgs e) {
- RightImageClicked ? .Invoke(sender, e);
- }
- public ImageEntry() {
- InitializeComponent();
- imgEntry.BindingContext = this;
- RIcon.ImageClicked += RightImageOn_Clicked;
- LIcon.ImageClicked += LeftImageOn_Clicked;
- imgEntry.Focused += async (s, a) => {
- BottomBorder.HeightRequest = 2.5;
- BottomBorder.BackgroundColor = AccentColor;
- HiddenBottomBorder.BackgroundColor = AccentColor;
- if (string.IsNullOrEmpty(imgEntry.Text)) {
- await Task.WhenAll(HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, BottomBorder.Width, BottomBorder.Height), 200));
- imgEntry.Placeholder = null;
- } else {
- await HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, BottomBorder.Width, BottomBorder.Height), 200);
- }
- };
- imgEntry.Unfocused += async (s, a) => {
- BottomBorder.HeightRequest = 1;
- BottomBorder.BackgroundColor = Color.Gray;
- if (string.IsNullOrEmpty(imgEntry.Text)) {
- await Task.WhenAll(HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, 0, BottomBorder.Height), 200));
- imgEntry.Placeholder = Placeholder;
- } else {
- await HiddenBottomBorder.LayoutTo(new Rectangle(BottomBorder.X, BottomBorder.Y, 0, BottomBorder.Height), 200);
- }
- };
- }
- private static void OnImageAlignmentChanged(BindableObject bindable, object oldvalue, object newvalue) {
- var control = bindable as ImageEntry;
- switch (control.ImageAlignment) {
- case eImageAlignment.None:
- control.LIcon.IsVisible = false;
- control.RIcon.IsVisible = false;
- break;
- case eImageAlignment.Left:
- control.LIcon.IsVisible = true;
- control.RIcon.IsVisible = false;
- break;
- case eImageAlignment.Right:
- control.LIcon.IsVisible = false;
- control.RIcon.IsVisible = true;
- break;
- case eImageAlignment.Password:
- control.LIcon.IsVisible = true;
- control.RIcon.IsVisible = true;
- break;
- }
- }
- public enum eImageAlignment {
- Left,
- Right,
- Password,
- None
- }
Please make sure to add View reference.
xmlns:controls="clr-namespace:CustomImageEntry.CustomControls"
- <StackLayout Padding="10">
- <controls:ImageEntry Text="Left Image" Placeholder="Xamarin Skills" AccentColor="Red"
- ImageAlignment="Left" LImageSource="email"/>
- <controls:ImageEntry Text="Right Image" Placeholder="Xamarin Skills"
- AccentColor="Green" ImageAlignment="Right" RImageSource="user"/>
- <controls:ImageEntry Text="Both Side Image" AccentColor="Yellow" LImageSource="email"
- RImageSource="eyeshow" ImageAlignment="Password" />
- <controls:ImageEntry Placeholder="Xamarin Skills" Text="None Image" AccentColor="Black" LImageSource="email"
- RImageSource="eyeshow" ImageAlignment="None" />
- <controls:ImageEntry Placeholder="Xamarin Skills" Text="Left Image Entry Clicked" AccentColor="White"
- LImageSource="email" RImageSource="eyeshow" ImageAlignment="Password"
- LeftImageClicked="ImageEntry_LeftImageClicked" />
- <controls:ImageEntry Placeholder="Xamarin Skills" Text="Right Image Entry Clicked" AccentColor="Blue"
- LImageSource="email" RImageSource="eyeshow" ImageAlignment="Password"
- RightImageClicked="ImageEntry_RightImageClicked"/>
- <controls:ImageEntry Placeholder="Xamarin Skills" Text="Left and Right Image Entry Clicked" AccentColor="BlueViolet"
- LImageSource="email" RImageSource="eyeshow" ImageAlignment="Password"
- LeftImageClicked="ImageEntry_LeftImageClicked_1" RightImageClicked="ImageEntry_RightImageClicked_1"/>
- <Entry x:Name="DefaultEntry" Placeholder="Default Entry"/>
- </StackLayout>
TADAAA! ,
I have not yet told about the Borderless entry and CustomImage in this blog. That I will cover in my next post.
Features of Image Entry With Password Click Controls
- Accent Color = ( AccentColor="BlueViolet")
- Text Property = (Text="Xamarin Skills")
- Keyboard Property = (Keyboard="Default")
- Placeholder Property = (Placeholder="Xamarin Skills")
- IsPassword Property = (IsPassword="False")
- Left ImageSource Property = (LImageSource="email")
- Right ImageSource Property = (RImageSource="eyeshow")
- ImageEntry RightImage = Clicked Property(RightImageClicked="ImageEntry_RightImageClicked")
- ImageEntry LeftImage Clicked Property = (LeftImageClicked="ImageEntry_LeftImageClicked")
- ImageAlignment Property = (ImageAlignment="Password")