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")