Hello Xamarin Friends,
Today, I am going to create a custom ImageEntry. Whenever we are creating a login page, we can not understand which control we have to use for 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 looks good.
So let's start.
Firstly we create a ContentView and set the image and entry.
then we are using the BindableProperty to create this custom control.
Please make sure to add view reference.....
xmlns:controls="clr-namespace:CustomImageEntry.CustomControls"
TADAA!,
I have not yet told about the Borderless entry and CustomImage in this blog that I will tell in the next post.
All this my original code.
Features of Image Entry controls:-
Today, I am going to create a custom ImageEntry. Whenever we are creating a login page, we can not understand which control we have to use for 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 looks good.
So let's start.
Firstly we create a ContentView and set the image and entry.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
xmlns:controls="clr-namespace:CustomImageEntry.CustomControls"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> | |
</ContentPage> |
TADAA!,

I have not yet told about the Borderless entry and CustomImage in this blog that I will tell in the next post.
All this my original code.
Features of Image Entry 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")