Removing Padding from Entry - xamarin

So Entry does not have a padding attribute, however there is some definite padding that goes on the Entry.
Example
I have the "Michigan" Entry lined up with the "Select" Label below, however they look misaligned because the entry has some padding to the left. I tried the margin attribute that entry does have, however it did not work.
How do I get rid of that gap/padding?
I'd like to add that adding an offset margin does not working.

You need to make a custom renderer for the entry and set the Android EditText's PaddingLeft to 0 using the SetPadding method.
Excerpt from CustomEntryRenderer on Android:
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement == null) return;
Control.SetPadding(0, Control.PaddingTop, Control.PaddingRight, Control.PaddingBottom);
}

For me the custom render that worked was:
[assembly: Xamarin.Forms.ExportRenderer(typeof(MyApp.Views.Controls.CustomEntry), typeof(MyApp.Droid.Views.Controls.CustomRenderer.Android.CustomEntryRenderer))]
namespace MyApp.Droid.Views.Controls
{
namespace CustomRenderer.Android
{
public class CustomEntryRenderer : EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Background = new ColorDrawable(Color.Transparent);
Control.SetPadding(0, 0, 0, 0);
Control.Gravity = GravityFlags.CenterVertical | GravityFlags.Left;
Control.TextAlignment = TextAlignment.Gravity;
}
}
}
}
}

I was struggling with the same issue, but I solved it by creating a custom Entry type which adds a Padding property to Xamarin Forms' Entry:
public class CustomEntry : Entry
{
public static readonly BindableProperty PaddingProperty =
BindableProperty.Create(
nameof(Padding),
typeof(Thickness),
typeof(CustomEntry),
new Thickness());
public Thickness Padding
{
get { return (Thickness)this.GetValue(PaddingProperty); }
set { this.SetValue(PaddingProperty, value); }
}
}
Then I render this CustomEntry with a custom renderer, just as Danilow proposed, with the only difference, that I read the PaddingProperty from CustomEntry and apply it in the CustomEntryRenderer.
[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
namespace CrossPlatformLibrary.Forms.Android.Renderers
{
public class CustomEntryRenderer : EntryRenderer
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
{
return;
}
if (this.Element is CustomEntry customEntry)
{
var paddingLeft = (int)customEntry.Padding.Left;
var paddingTop = (int)customEntry.Padding.Top;
var paddingRight = (int)customEntry.Padding.Right;
var paddingBottom = (int)customEntry.Padding.Bottom;
this.Control.SetPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
}
}
}
Beware: This code needs to be extended if you want to react on PaddingProperty changes - AND - you will need to write a custom renderer for IOS if you want to support the Padding property there too.

Here's the same thing implemented on iOS for anyone who needs it there too. It's basically setting the left view to have 0 width that does it, but you can also play with the "LeftViewMode" to hide it completely.
this.Control.LeftView = new UIView(new CGRect(0, 0, 0, this.Control.Frame.Height));
Full code
using CoreGraphics;
using UIKit;
using YourNamespace.iOS.CustomRenderers;
using YourNamespace.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(BorderlessEntry), typeof(BorderlessEntryRenderer))]
namespace YourNamespace.iOS.CustomRenderers
{
public class BorderlessEntryRenderer : Xamarin.Forms.Platform.iOS.EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (this.Control != null)
{
this.Control.LeftView = new UIView(new CGRect(0, 0, 0, this.Control.Frame.Height));
this.Control.LeftViewMode = UITextFieldViewMode.Always;
}
}
}
}

Related

How to keep soft keyboard always open in Xamarin Forms

I am working in a Xamarin Forms APP, we want to go through different entries (not using TabIndex because we need a custom logic), but we want to keep the keyboard always on during looping through entries. We are using ReturnCommand to Focus the NEXT entry.
Create a CustomEntryRenderer in your Android project :
[assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))]
namespace your namespace
class CustomEntryRenderer:EntryRenderer
{
public CustomEntryRenderer(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
}
}
and add this in your MainActivity:
private bool _lieAboutCurrentFocus;
public override bool DispatchTouchEvent(MotionEvent ev)
{
var focused = CurrentFocus;
bool customEntryRendererFocused = focused != null && focused.Parent is CustomEntryRenderer;
_lieAboutCurrentFocus = customEntryRendererFocused;
var result = base.DispatchTouchEvent(ev);
_lieAboutCurrentFocus = false;
return result;
}
public override Android.Views.View CurrentFocus
{
get
{
if (_lieAboutCurrentFocus)
{
return null;
}
return base.CurrentFocus;
}
}

How to Use AutoCompleteTextView With Xamarin Forms

I am trying to Implement AutocompleteTextview in xamarin forms,
till now i have achieved the customisation and look which i need to for my Auto Complete Bar,
but the thing where i am stuck is filling of data to Dataadapter from Shared Library also i am not getting what text is selected inside the Entry bar, so could anyone help me how can i bind my list from pcl to native and also i need two way data to Text Property
here is the code which i had implemented till now
my common class
public class AutoCompleteViewv3 : View
{
public AutoCompleteViewv3()
{
}
}
My Android Implementation
[assembly: ExportRenderer(typeof(AutoSuggestBox),
typeof(AutoCompleteViewRendererv3))]
namespace PredictiveList.Droid
{
public class AutoCompleteViewRendererv3 :
ViewRenderer<AutoCompleteViewv3,
AutoCompleteTextView>
{
static string[] COUNTRIES = new string[] {
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
"Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", };
public AutoCompleteViewRendererv3(Android.Content.Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<AutoCompleteViewv3> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || this.Element == null)
return;
AutoCompleteTextView textView = (AutoCompleteTextView)LayoutInflater.From(Context).Inflate(Resource.Layout.TextEditorLayouts, null);
var adapter = new ArrayAdapter<String>(Context,
Resource.Layout.list_item, COUNTRIES);
textView.Adapter = adapter;
SetNativeControl(textView);
}
// Use the control here.
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (this.Element == null || this.Control == null)
return;
// variable this.Control is the AutoCompleteTextView, so you an manipulate it.
}
}
}
For Ios i am still trying to implemented
please check Code here for Auto complete

Xamarin forms TabbedPage

I am using Tabbed page in my xamarin forms project.
I am trying to use OnTabReselected event in MyTabsRenderer Class in android. But the events like OnTabSelected, OnTabReselected and OnTabUnselected are not getting called. Does anyone have any solution for this.
xamarin forms version: 3.2.0.871581
VS version : 15.8.6
Here is my code snippet(MyTabsRenderer Class):
using Android.OS;
using Android.Views;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android.AppCompat;
using MyProject;
using MyProject.Droid;
using Xamarin.Forms.Platform.Android;
using System.ComponentModel;
using Android.Support.V4.View;
using Android.Content.Res;
using Android.Content;
using Android.Support.Design.Widget;
[assembly: ExportRenderer(typeof(TabController), typeof(MyTabsRenderer))]
namespace MyProject.Droid
{
public class MyTabsRenderer : TabbedPageRenderer, TabLayout.IOnTabSelectedListener
{
bool setup;
ViewPager viewPager;
TabLayout tabLayout;
public MyTabsRenderer(Context context) : base(context)
{
}
protected override void SetTabIcon(TabLayout.Tab tab, FileImageSource icon)
{
base.SetTabIcon(tab, icon);
}
protected override void OnElementChanged(ElementChangedEventArgs<TabbedPage> e)
{
base.OnElementChanged(e);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
//if (setup)
// return;
if (e.PropertyName == "Renderer" || e.PropertyName == "CurrentPage")
{
viewPager = (ViewPager)ViewGroup.GetChildAt(0);
tabLayout = (TabLayout)ViewGroup.GetChildAt(1);
setup = true;
ColorStateList colors = GetTabColor();
for (int i = 0; i < tabLayout.TabCount; i++)
{
var tab = tabLayout.GetTabAt(i);
SetTintColor(tab, colors);
}
tabLayout.SetOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager));
}
}
void OnTabReselected(TabLayout.Tab tab)
{
// To have the logic only on he tab on position 1
if (tab == null || tab.Position != 1)
{
return;
}
if (tab.Text == "Play")
{
tab.SetText("Pause");
tab.SetIcon(Resource.Drawable.icon);
// App.pauseCard = false;
}
else
{
tab.SetText("Play");
tab.SetIcon(Resource.Drawable.icon);
// App.pauseCard = true;
}
SetTintColor(tab, GetTabColor());
}
void SetTintColor(TabLayout.Tab tab, ColorStateList colors)
{
var icon = tab?.Icon;
if (icon != null)
{
icon = Android.Support.V4.Graphics.Drawable.DrawableCompat.Wrap(icon);
Android.Support.V4.Graphics.Drawable.DrawableCompat.SetTintList(icon, colors);
}
}
ColorStateList GetTabColor()
{
return ((int)Build.VERSION.SdkInt >= 23)
? Resources.GetColorStateList(Resource.Color.icon_tab, Forms.Context.Theme)
: Resources.GetColorStateList(Resource.Color.icon_tab);
}
}
}
It is probably because you are setting the OnTabSelectedListener wrong.
Try setting the listener to this instead: tabLayout.SetOnTabSelectedListener(this);
Also for inspiration check out TabbedPageRenderer.cs source code,

How can I change the font for the header of a Navigation page with Xamarin Forms?

I can change the font color like this:
var homePage = new NavigationPage(new HomePage())
{
Title = "Home",
Icon = "ionicons_2_0_1_home_outline_25.png",
BarTextColor = Color.Gray,
};
But is there a way to change the font for the Title. I would like to change it for the iOS and Android platforms only. Hoping that someone knows of custom renderer code that can help me to do this.
You need Custom Renderer , refer to this sample
iOS
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(CustomNavigationPageRenderer))]
namespace CustomFontsNavigationPage.iOS.Renderers
{
public class CustomNavigationPageRenderer : NavigationRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var att = new UITextAttributes();
UIFont customFont = UIFont.FromName("Trashtalk", 20);
UIFont systemFont = UIFont.SystemFontOfSize(20.0);
UIFont systemBoldFont = UIFont.SystemFontOfSize(20.0 , FontAttributes.Bold);
att.Font = font;
UINavigationBar.Appearance.SetTitleTextAttributes(att);
}
}
}
}
Android
[assembly: ExportRenderer(typeof(CustomNavigationPage), typeof(CustomNavigationPageRenderer))]
namespace CustomFontsNavigationPage.Droid.Renderers
{
public class CustomNavigationPageRenderer : NavigationPageRenderer
{
private Android.Support.V7.Widget.Toolbar _toolbar;
public override void OnViewAdded(Android.Views.View child)
{
base.OnViewAdded(child);
if (child.GetType() == typeof(Android.Support.V7.Widget.Toolbar))
{
_toolbar = (Android.Support.V7.Widget.Toolbar)child;
_toolbar.ChildViewAdded += Toolbar_ChildViewAdded;
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if(disposing)
{
_toolbar.ChildViewAdded -= Toolbar_ChildViewAdded;
}
}
private void Toolbar_ChildViewAdded(object sender, ChildViewAddedEventArgs e)
{
var view = e.Child.GetType();
if (e.Child.GetType() == typeof(Android.Widget.TextView))
{
var textView = (Android.Widget.TextView)e.Child;
var spaceFont = Typeface.CreateFromAsset(Forms.Context.ApplicationContext.Assets, "Trashtalk.ttf");
var systemFont = Typeface.DEFAULT;
var systemBoldFont = Typeface.DEFAULT_BOLD;
textView.Typeface = spaceFont;
_toolbar.ChildViewAdded -= Toolbar_ChildViewAdded;
}
}
}
}
There is no need in a custom renderer on iOS, you can just use the Appearance API:
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes
{
Font = UIFont.FromName("MyCoolFont", 20)
});
In Android you do need a renderer, however you should check against Android.Support.V7.Widget.AppCompatTextView and not Android.Widget.TextView.
Tested on Xamarin.Forms 3.4.0

Xamarin Forms timepicker 24hour

I'm new to Xamarin.Forms and i can't seems to find how to show the dialog in a 24hour format instead of a AM/PM
can someone help me ?
Thank you
This page is really usefull to learn how to format dates in C#:
https://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx
And with this code I was able to show a 24 hour format:
TimePicker timePicker = new TimePicker
{
Format = "HH:mm"
};
The only solution i found is here:
24h timepicker
Basically a custom renderer within each platform project will be needed.
Xamarin.iOS:
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using PersonalTrainer.iOS.View.Controls;
[assembly: ExportRenderer (typeof (TimePicker), typeof (TimePicker24HRenderer))]
namespace YourNamespace.iOS.View.Controls {
public class TimePicker24HRenderer : TimePickerRenderer {
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e) {
base.OnElementChanged(e);
var timePicker = (UIDatePicker)Control.InputView;
timePicker.Locale = new NSLocale("no_nb");
}
}
}
For Android:
[assembly: ExportRenderer(typeof(TimePicker), typeof(TimePicker24HRenderer))]
namespace YourNamespace.Droid.View.Controls {
public class TimePicker24HRenderer : ViewRenderer<Xamarin.Forms.TimePicker, Android.Widget.EditText>, TimePickerDialog.IOnTimeSetListener, IJavaObject, IDisposable {
private TimePickerDialog dialog = null;
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e) {
base.OnElementChanged(e);
this.SetNativeControl(new Android.Widget.EditText(Forms.Context));
this.Control.Click += Control_Click;
this.Control.Text = DateTime.Now.ToString("HH:mm");
this.Control.KeyListener = null;
this.Control.FocusChange += Control_FocusChange;
}
void Control_FocusChange(object sender, Android.Views.View.FocusChangeEventArgs e) {
if (e.HasFocus) { ShowTimePicker(); }
}
void Control_Click(object sender, EventArgs e) {
ShowTimePicker();
}
private void ShowTimePicker() {
if (dialog == null) {
dialog = new TimePickerDialog(Forms.Context, this, DateTime.Now.Hour, DateTime.Now.Minute, true);
}
dialog.Show();
}
public void OnTimeSet(Android.Widget.TimePicker view, int hourOfDay, int minute) {
var time = new TimeSpan(hourOfDay, minute, 0);
this.Element.SetValue(TimePicker.TimeProperty, time);
this.Control.Text = time.ToString(#"hh\:mm");
}
}
}
For Windows Phone:
[assembly: ExportRenderer (typeof (MyTimePicker), typeof (TimePicker24HRenderer))]
namespace YourNamespace.WindowsPhone.View.Controls {
public class TimePicker24HRenderer : TimePickerRenderer {
// Override the OnElementChanged method so we can tweak this renderer post-initial setup
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.TimePicker> e) {
base.OnElementChanged (e);
if (Control != null) {
var nativeControl = (Windows.UI.Xaml.Controls.TimePicker)Control;
nativeControl.Foreground = new SolidColorBrush(Colors.Gray);
Control.ClockIdentifier = "24HourClock";
}
}
}
}
In XAML you can set the the 24 hours format string to TimePicker by using the Format property:
<TimePicker Format="HH:mm"/>
Ok. You have to do it plateform specific.. I did something like that.
So create an interface
public interface TimePickerInterface
{
void showTimePicker (ButtonOrLabel lbl);
}
In Android you create your timepicker class
[assembly:Dependency(typeof(yournamespace.MyTimePicker))]
namespace yournamespace
{
public class MyTimePicker:Java.Lang.Object,TimePickerInterface,Android.App.TimePickerDialog.IOnTimeSetListener
{
String originalText="";
LabelOrButton lbl=new LabelOrButton();
public void showTimePicker(LabelOrButton lbl)
{
var c = Forms.Context;
originalText = lbl.Text;
this.lbl = lbl;
var time = DateTime.Now.TimeOfDay;
TimePickerDialog dialog = new TimePickerDialog(c,this,time.Hours,time.Minutes,true);
dialog.SetCanceledOnTouchOutside (true);
dialog.Show ();
}
public void OnTimeSet (Android.Widget.TimePicker view, int hourOfDay, int minute)
{
if(view.IsShown)
lbl.Text = (hourOfDay<=9 ? ("0"+hourOfDay+""):hourOfDay+"")+":"+(minute<=9 ? ("0"+minute+""):minute+"");
}
}
}
And in your xamarin forms you call it in actionlistener of your button or gesturerecognizer of your label:
DependencyService.Get<TimePickerInterface> ().showTimePicker(myButtonOrLabel);
You can do the same thing for DatePicker..
Hope it helps..

Resources