I'm trying to search how to create a custom picker on Xamarin but I have no idea how to do it.
Here is what I want to do
I don't even know if I need to install a nuget package. Please help and thanks.
I'm trying to search how to create a custom picker on Xamarin but I have no idea how to do it.
Here is what I want to do
I don't even know if I need to install a nuget package. Please help and thanks.
As mentioned by @Skalpel02, you need to sub-class the Picker
class and implement the corresponding Renderer
s in each platform. There, you have the ability to interact with native APIs of the platform.
This could be implemented by custom renderer.
First,a custom Picker control can be created by subclassing the Picker control, as shown in the following code:
public class BorderlessPicker : Picker
{
public BorderlessPicker() : base()
{
}
}
Second:Create the Custom Renderer on each Platform,Override the OnElementChanged
method and write logic to customize the control,then Add an ExportRenderer
attribute to the custom renderer class to specify that it will be used.
In Android:
[assembly: ExportRenderer(typeof(BorderlessPicker), typeof(BordlessPickerRenderer))]
namespace AppPicker01.Droid
{
public class BordlessPickerRenderer : PickerRenderer
{
public BordlessPickerRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
Control.Background = null;
}
}
}
}
In iOS:
[assembly: ExportRenderer(typeof(BorderlessPicker), typeof(BorderlessPickerRenderer))]
namespace AppPicker01.iOS
{
public class BorderlessPickerRenderer : PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control == null)
{
return;
}
Control.Layer.BorderWidth = 0;
Control.BorderStyle = UITextBorderStyle.None;
}
}
}
Last but not least, consume the custom picker control in Xaml:
<apppicker01:BorderlessPicker Title="Select a color" ItemsSource="{Binding ColorNames}" SelectedItem="{Binding SelectedColorName, Mode=TwoWay}" />
Screenshot:
MS official docs link: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/
You can easily create your own control that doesn't need a renderer and works on iOS, Android, and UWP. Here my solution. You have to create a View "PickerCustom" for the control
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="___YOURCLASS"
xmlns:xmleditor="clr-namespace:XmlEditor" HorizontalOptions="FillAndExpand" BackgroundColor="#ddd">
<StackLayout x:Name="stack" Orientation="Horizontal" HorizontalOptions="FillAndExpand" Margin="1" BackgroundColor="#fff" Padding="5">
<Label Text="{Binding TextValue}" Margin="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<ImageButton BackgroundColor="#ffffff" Source="dropdown.png" x:Name="img" WidthRequest="20"></ImageButton>
<Entry WidthRequest="0"></Entry>
</StackLayout>
</ContentView>
with this code behind
public partial class PickerCustom : ContentView
{
public PickerCustom()
{
InitializeComponent();
Items = new ObservableCollection<CustomItem>();
SelectedIndex = -1;
BindingContext = this;
TapGestureRecognizer tap0 = new TapGestureRecognizer();
tap0.Tapped += (sender, e) =>
{
img.Focus();
PickerCustomList pcl = new PickerCustomList();
pcl.Items = this.Items;
App.Current.MainPage.Navigation.PushModalAsync(pcl);
MessagingCenter.Subscribe<PickerCustomList>(this, "finish", (sender1) =>
{
MessagingCenter.Unsubscribe<PickerCustomList>(this, "finish");
img.Focus();
if(((PickerCustomList)sender1).SelectedIndex != -1)
{
SelectedIndex = ((PickerCustomList)sender1).SelectedIndex;
}
});
};
GestureManager.AddGesture(stack, tap0);
}
string _textvalue = "";
public string TextValue
{
get
{
return _textvalue;
}
set
{
_textvalue = value;
OnPropertyChanged();
}
}
public ObservableCollection<CustomItem> Items { get; set; }
int _selectedIndex = 0;
public int SelectedIndex
{
get
{
return _selectedIndex;
}
set
{
_selectedIndex = value;
if(_selectedIndex>= Items.Count)
{
_selectedIndex = -1;
} else if (_selectedIndex != -1)
{
TextValue = Items[SelectedIndex].Name;
}
else
{
TextValue = "";
}
OnPropertyChanged();
}
}
}
public class CustomItem
{
public CustomItem(string _name)
{
name = _name;
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
And a View "PickerCustomList" for the choice
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="___YOURCLASS" BackgroundColor="#66aaaaaa"
x:Name="ContentPage1" Padding="30,100,30,100" >
<ListView x:Name="ContactsList" ItemsSource="{Binding Items}" IsVisible="True"
VerticalOptions="Start" HorizontalOptions="Center"
BackgroundColor="Transparent" HasUnevenRows="True">
<ListView.Header HorizontalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" BackgroundColor="#f0f0f0" >
<ImageButton Source="close.png" WidthRequest="20" Clicked="Button_Clicked" Margin="10,5,10,5" BackgroundColor="Transparent"></ImageButton>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Tapped="ViewCell_Tapped" >
<StackLayout BackgroundColor="#ffffff">
<Label Text="{Binding Name}" Padding="10"></Label>
<ContentView HeightRequest="1" BackgroundColor="#666"></ContentView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
with this code behind
public partial class PickerCustomList : ContentPage
{
public int SelectedIndex = -1;
ObservableCollection<CustomItem> myItems= new ObservableCollection<CustomItem>();
public ObservableCollection<CustomItem> Items
{
get { return myItems; }
set {
myItems = value;
OnPropertyChanged();
}
}
public PickerCustomList()
{
InitializeComponent();
BindingContext = this;
}
private void Button_Clicked(object sender, EventArgs e)
{
SelectedIndex = -1;
App.Current.MainPage.Navigation.PopModalAsync();
MessagingCenter.Send<PickerCustomList>(this, "finish");
}
private void ViewCell_Tapped(object sender, EventArgs e)
{
SelectedIndex = Items.IndexOf(((CustomItem)((ViewCell)sender).BindingContext));
App.Current.MainPage.Navigation.PopModalAsync();
MessagingCenter.Send<PickerCustomList>(this, "finish");
}
}