I am creating a custom renderer for an entry. I am mainly trying to add an icon to the left of the entry field. I have achieved this using SetCompoundDrawablesRelativeWithIntrinsicBounds() in Android and using LeftView in iOS.
The problem occurs when ClearButtonVisibility is set to "while editing". After typing something in the entry and the clear button is clicked, the left icon is cleared along with the text (This only occurs in Android. In iOS, only the text is cleared. I realized the built-in clear button image is in the compound drawables so I am setting the compound drawables with my icon as well as the built-in icon.
What is the best workaround to this? I would like it so that when the clear button is clicked, only the text is cleared and not the icon.
Note: The icon is cleared momentarily. When any other event is fired, the icon returns.
CustomEntry - after some event
Android.Renderer:
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace Styles.Android.Renderers
{
public class CustomEntryRenderer : EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// update control UI
UpdateControl();
base.OnElementPropertyChanged(sender, e);
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
// update control UI
UpdateControl();
base.OnElementChanged(e);
}
private void UpdateControl()
{
if (Element == null || Control == null)
return;
var entry = Element as CustomEntry;
// set border/background
var gradientBackground = new GradientDrawable();
gradientBackground.SetShape(ShapeType.Rectangle);
gradientBackground.SetColor(Element.BackgroundColor.ToAndroid());
gradientBackground.SetCornerRadius(entry.CornerRadius);
gradientBackground.SetStroke(entry.BorderWidth, entry.BorderColor.ToAndroid());
Control.SetBackground(gradientBackground);
// set appropriate icon
int resID = Resources.GetIdentifier("icon_image", "drawable", this.Context.PackageName);
var drawable = ContextCompat.GetDrawable(this.Context, resID);
Control.SetCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, Control.GetCompoundDrawables()[2], null);
Control.CompoundDrawablePadding = entry.IconPadding;
paddingLeft = entry.IconPadding;
// set padding
Control.SetPadding(Control.PaddingLeft, Control.PaddingTop, Control.PaddingRight, Control.PaddingBottom);
}
}
}
You could overwrite OnTouchListener
to clean the text and SetCompoundDrawable
again.
change your CustomRenderer like below:
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace Styles.Android.Renderers
{
public class CustomEntryRenderer : EntryRenderer
{
static Drawable drawableLeft;
static Drawable drawableRight;
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// update control UI
UpdateControl();
base.OnElementPropertyChanged(sender, e);
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
// update control UI
UpdateControl();
base.OnElementChanged(e);
}
private void UpdateControl()
{
if (Element == null || Control == null)
return;
var entry = Element as CustomEntry;
// set border/background
var gradientBackground = new GradientDrawable();
gradientBackground.SetShape(ShapeType.Rectangle);
gradientBackground.SetColor(Element.BackgroundColor.ToAndroid());
gradientBackground.SetCornerRadius(entry.CornerRadius);
gradientBackground.SetStroke(entry.BorderWidth, entry.BorderColor.ToAndroid());
Control.SetBackground(gradientBackground);
// set appropriate icon
int resID = Resources.GetIdentifier("icon_image", "drawable", this.Context.PackageName);
drawableLeft = ContextCompat.GetDrawable(this.Context, resID);
drawableRight = Control.GetCompoundDrawables()[2];
Control.SetCompoundDrawablesRelativeWithIntrinsicBounds(drawableLeft, null, drawableRight , null);
Control.CompoundDrawablePadding = entry.IconPadding;
paddingLeft = entry.IconPadding;
// set padding
Control.SetPadding(Control.PaddingLeft, Control.PaddingTop, Control.PaddingRight, Control.PaddingBottom);
Control.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;
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(drawableLeft, null, drawableRight, null);
if (drawableRight != null)
{
bool touchable = e.GetX() > (editText.Width
- editText.PaddingRight - drawableRight.IntrinsicWidth)
&& (e.GetX() < ((editText.Width - editText.PaddingRight)));
if (touchable)
{
Console.WriteLine(editText.Text);
editText.Text = "";
editText.SetCompoundDrawablesRelativeWithIntrinsicBounds(drawableLeft, null, drawableRight, null);
return true;
}
}
}
return false;
}
}
}
}