Introduction
In Xamarin.Forms, Picker creation and assigning ItemsSource very simple But there is no direct way set right side down Icon like iOS, Android native, TitleColor, BorderColor. So in this article, we will learn how to set those properties for Picker using CustomRenderer.
Requirements:
Then, we have to give the app name; i.e., PickerDemo.
Note
Added a Bindable property for Picker right side Icon in the above class.
In code behind make sure BindingContext with PickerDemoViewModel.
PickerDemoPageViewModel.cs
Xamarin.Android:
In an Android project, create a class that should inherit PickerRenderer and add the code like below.
CustomPickerRenderer.cs
The call to the base class's OnElementChanged method instantiates an Android Picker, with a reference to the control being assigned to the renderer's property. Here we are loading the drawable dynamically with the help of LayerDrawable, LayerDrawable to combine a drawable that will be our border with the drawable image of our right side icon. And the assigned below properties and events are for Picker.
In iOS project, create a class that should inherit PickerRenderer and add the code like below.
CustomPickerRenderer.cs
In Xamarin.Forms, Picker creation and assigning ItemsSource very simple But there is no direct way set right side down Icon like iOS, Android native, TitleColor, BorderColor. So in this article, we will learn how to set those properties for Picker using CustomRenderer.
Requirements:
- This article source code is prepared by using Visual Studio. And it is better to install the latest Visual Studio updates from here.
- This article is prepared on a MAC machine.
- This sample project is Xamarin.Forms PCL project.
- This sample app is targeted for Android, iOS. And tested for Android & iOS.
The creation of a Xamarin.Forms project is very simple in Visual Studio for Mac. It will create three projects:
- Shared Code
- Xamarin.Android
- Xamarin.iOS
The Mac system with Visual Studio for Mac doesn't support Windows projects (UWP, Windows, Windows Phone)
The following steps will show you how to create Xamarin.Forms projects in a Mac system with Visual Studio.
First, open Visual Studio for Mac. And click on New Project.
After that, we need to select whether you're doing Xamarin.Forms or Xamarin.Android or Xamarin.iOS project. If we want to create Xamarin.Forms project just follow the below screenshot.Then, we have to give the app name; i.e., PickerDemo.
Note
In the above screen under Shared Code, select Portable class Library or Use Shared Library.
Then, click on Next Button and the following screenshot will be displayed. In that screen, we have to browse the file path where we want to save that application on our PC.
After clicking on the create button it will create the PickerDemo Xamarin.Forms project like below.
And the project structure will be:
- PickerDemo: It is for Shared Code
- PickerDemo.Droid: It is for Android.
- PickerDemo.iOS: It is for iOS
Now, follow the below steps.
Portable Class Library (PCL)
Step 1:
In PCL, create a class name CustomPicker.cs inside the CustomControls folder which should inherit Picker like below.
CustomPicker.cs- using Xamarin.Forms;
- namespace PickerDemo.CustomControls
- {
- public class CustomPicker : Picker
- {
- public static readonly BindableProperty ImageProperty =
- BindableProperty.Create(nameof(Icon), typeof(string), typeof(CustomPicker), string.Empty);
- public string Icon
- {
- get { return (string)GetValue(ImageProperty); }
- set { SetValue(ImageProperty, value); }
- }
- }
- }
Added a Bindable property for Picker right side Icon in the above class.
Step 2:
Create your own XAML page named PickerDemoPage.xaml inside the Views folder and make sure to refer to "CustomPicker" class in XAML by declaring a namespace for its location and using the namespace prefix on the control element. The following code example shows how the "CustomPicker" renderer class can be consumed by an XAML page:
PickerDemoPage.xaml- <?xml version="1.0" encoding="UTF-8"?>
- <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- xmlns:custom="clr-namespace:PickerDemo.CustomControls"
- x:Class="PickerDemo.Views.PickerDemoPage"
- BackgroundColor="White">
- <StackLayout VerticalOptions="FillAndExpand" Padding="20,50,20,20"
- HorizontalOptions="FillAndExpand">
- <StackLayout Spacing="70">
- <Label Text="Picker with right icon"
- FontSize="20" TextColor="#533F95"
- HorizontalOptions="CenterAndExpand"/>
- <Label Text="{Binding SelectedItemsValue}"
- FontSize="20"
- TextColor="#533F95"
- HorizontalOptions="CenterAndExpand"/>
- </StackLayout>
- <custom:CustomPicker Icon="picker_right_arrow.png"
- Title="Select Country"
- SelectedItem="{Binding SelectedItem}"
- SelectedIndex="{Binding SelectedIndexChanged}"
- ItemsSource="{Binding Countries}"
- HeightRequest="50"
- TextColor="#533F95"
- HorizontalOptions="FillAndExpand"
- VerticalOptions="CenterAndExpand" >
- </custom:CustomPicker>
- </StackLayout>
- </ContentPage>
The "custom" namespace prefix can be named anything. However, the clr-namespace and assembly values must match the details of the custom renderer class. Once the namespace is declared the prefix is used to reference the custom control.
PickerDemoPage.xaml.cs- using PickerDemo.ViewModels;
- using Xamarin.Forms;
- namespace PickerDemo.Views
- {
- public partial class PickerDemoPage : ContentPage
- {
- public PickerDemoPage()
- {
- InitializeComponent();
- BindingContext = new PickerDemoPageViewModel();
- }
- }
- }
In code behind make sure BindingContext with PickerDemoViewModel.
PickerDemoPageViewModel.cs
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Runtime.CompilerServices;
- using System.Windows.Input;
- using Xamarin.Forms;
- namespace PickerDemo.ViewModels
- {
- public class PickerDemoPageViewModel : INotifyPropertyChanged
- {
- string _selectedItem;
- public string SelectedItem {
- get => _selectedItem;
- set {
- _selectedItem = value;
- NotifyPropertyChanged("SelectedItemsValue");
- }
- }
- public string SelectedItemsValue => string.IsNullOrEmpty(SelectedItem) ? "" : "Selected Item: " + SelectedItem;
- List<string> countries = new List<string>{
- "India",
- "Afghanistan",
- "Albania",
- "Algeria",
- "Andorra",
- "Angola",
- "USA",
- "United Kingdom"
- };
- public List<string> Countries => countries;
- #region INotifyPropertyChanged
- public event PropertyChangedEventHandler PropertyChanged;
- protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- #endregion
- }
- }
Xamarin.Android:
In an Android project, create a class that should inherit PickerRenderer and add the code like below.
CustomPickerRenderer.cs
- using Android.Graphics;
- using Android.Graphics.Drawables;
- using Android.Support.V4.Content;
- using Android.Widget;
- using PickerDemo.CustomControls;
- using PickerDemo.Droid;
- using Xamarin.Forms;
- using Xamarin.Forms.Platform.Android;
- [assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
- namespace PickerDemo.Droid
- {
- public class CustomPickerRenderer : PickerRenderer
- {
- CustomPicker element;
- protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
- {
- base.OnElementChanged(e);
- element = (CustomPicker)this.Element;
- if (Control != null && this.Element != null && !string.IsNullOrEmpty(element.Icon))
- {
- Control.Background = AddPickerStyles(element.Icon);
- Control.SetHintTextColor(Android.Graphics.Color.Rgb(83, 63, 149));
- }
- }
- public LayerDrawable AddPickerStyles(string imagePath)
- {
- ShapeDrawable border = new ShapeDrawable();
- border.Paint.Color = Android.Graphics.Color.Gray;
- border.SetPadding(10, 10, 10, 10);
- border.Paint.SetStyle(Paint.Style.Stroke);
- Drawable[] layers = { border, GetDrawable(imagePath) };
- LayerDrawable layerDrawable = new LayerDrawable(layers);
- layerDrawable.SetLayerInset(0, 0, 0, 0, 0);
- return layerDrawable;
- }
- private BitmapDrawable GetDrawable(string imagePath)
- {
- var drawable = Resources.GetDrawable(imagePath);
- var bitmap = ((BitmapDrawable)drawable).Bitmap;
- var result = new BitmapDrawable(Resources, Bitmap.CreateScaledBitmap(bitmap, 70, 70, true));
- result.Gravity = Android.Views.GravityFlags.Right;
- return result;
- }
- }
- }
The call to the base class's OnElementChanged method instantiates an Android Picker, with a reference to the control being assigned to the renderer's property. Here we are loading the drawable dynamically with the help of LayerDrawable, LayerDrawable to combine a drawable that will be our border with the drawable image of our right side icon. And the assigned below properties and events are for Picker.
Properties
- Icon it should taken from Resources what ever we passing from PCL.
- Title Color i.e, SetHintTextColor
- BorderColor
- SetPadding
In iOS project, create a class that should inherit PickerRenderer and add the code like below.
CustomPickerRenderer.cs
- using PickerDemo.CustomControls;
- using PickerDemo.iOS;
- using UIKit;
- using Xamarin.Forms;
- using Xamarin.Forms.Platform.iOS;
- [assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
- namespace PickerDemo.iOS
- {
- public class CustomPickerRenderer : PickerRenderer
- {
- protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
- {
- base.OnElementChanged(e);
- var element = (CustomPicker)Element;
- if (Control != null && Element != null && !string.IsNullOrEmpty(element.Icon))
- {
- var downarrow = UIImage.FromBundle(element.Icon);
- Control.RightViewMode = UITextFieldViewMode.Always;
- Control.RightView = new UIImageView(downarrow);
- Control.TextColor = UIColor.FromRGB(83, 63, 149);
- //Control.BackgroundColor = UIColor.Clear;
- Control.AttributedPlaceholder = new Foundation.NSAttributedString(Control.AttributedPlaceholder.Value, foregroundColor: UIColor.FromRGB(83, 63, 149));
- //Control.BorderStyle = UITextBorderStyle.RoundedRect;
- //Layer.BorderWidth = 1.0f;
- //Layer.CornerRadius = 4.0f;
- //Layer.MasksToBounds = true;
- //Layer.BorderColor = UIColor.FromRGB(83, 63, 149).CGColor;
- }
- }
- }
- }
Properties
- RightView i.e, for Picker Icon.
- TextColor
- Title Color i.e, AttributedPlaceholder.
- BorderColor.
Output:
Source Code:
No comments:
Post a Comment