When Google introduced Material Design for Android they introduced a new view called CardView. Xamarin.Forms doesn’t have support for CardView by default but you can easily create your own view that renderers a CardView on Android.
First step is to create a Xamarin.Forms control in your shared project.
publicclass CardContentView : ContentView{publicstaticreadonly BindableProperty CornerRadiusProperty = BindableProperty.Create<CardContentView,float>( p => p.CornderRadius, 3.0F);publicnewstaticreadonly BindableProperty BackgroundColorProperty = BindableProperty.Create<CardContentView, Color>(p => p.BackgroundColor, Color.White);publicfloat CornderRadius {get{return(float)GetValue(CornerRadiusProperty);}set{ SetValue(CornerRadiusProperty, value);}}publicnew Color BackgroundColor {get{return(Color)GetValue(BackgroundColorProperty);}set{ SetValue(BackgroundColorProperty, value);}}protectedoverride SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint){if(Content ==null)returnnew SizeRequest(new Size(100, 100));return Content.GetSizeRequest(widthConstraint, heightConstraint);}} |
Next step is to create a custom renderer for Android, on iOS and Windows it will be rendered as a regular ContentView.
You need to add a NuGet package named Xamarin.Android.Support.v7.CardView to get the Android CardView. The renderer will inherit form CardView and implement the IVisaulElementRenderer interface. To get card shadow on both Android KitKat and Android Lollipop you have to set UseCompatPadding to true. You have to remove all view from the ViewGroup, if you don’t do that you will get problems when you using the control in a ListView. The Load method on the VisualElementPackager will load content in to the Card.
[assembly:ExportRendererAttribute(typeof(CardContentView), typeof(CardViewRenderer))]namespace CardViewFormsAndroid{publicclass CardViewRenderer : CardView, IVisualElementRenderer {public CardViewRenderer ():base(Forms.Context){}publicevent EventHandler<VisualElementChangedEventArgs> ElementChanged;bool init; ViewGroup packed;publicvoid SetElement (VisualElement element){var oldElement =this.Element;if(oldElement !=null) oldElement.PropertyChanged-= HandlePropertyChanged;this.Element= element;if(this.Element!=null){this.Element.PropertyChanged+= HandlePropertyChanged;} ViewGroup.RemoveAllViews();//sizes to match the forms view//updates properties, handles visual element properties Tracker =new VisualElementTracker (this); Packager =new VisualElementPackager(this); Packager.Load(); UseCompatPadding =true; SetContentPadding((int)TheView.Padding.Left, (int)TheView.Padding.Top, (int)TheView.Padding.Right, (int)TheView.Padding.Bottom); Radius = TheView.CornderRadius; SetCardBackgroundColor(TheView.BackgroundColor.ToAndroid());if(ElementChanged !=null) ElementChanged (this, new VisualElementChangedEventArgs (oldElement, this.Element));}public CardContentView TheView {get{returnthis.Element==null?null:(CardContentView)Element;}}void HandlePropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e){if(e.PropertyName=="Content"){//Packager.Load(); Tracker.UpdateLayout();}elseif(e.PropertyName== CardContentView.PaddingProperty.PropertyName){ SetContentPadding ((int)TheView.Padding.Left, (int)TheView.Padding.Top, (int)TheView.Padding.Right, (int)TheView.Padding.Bottom);}elseif(e.PropertyName== CardContentView.CornerRadiusProperty.PropertyName){this.Radius= TheView.CornderRadius;}elseif(e.PropertyName== CardContentView.BackgroundColorProperty.PropertyName){if(TheView.BackgroundColor!=null) SetCardBackgroundColor (TheView.BackgroundColor.ToAndroid());}}public SizeRequest GetDesiredSize (int widthConstraint, int heightConstraint){ packed.Measure(widthConstraint, heightConstraint);//Measure child here and determine sizereturnnew SizeRequest (new Size (packed.MeasuredWidth, packed.MeasuredHeight));}publicvoid UpdateLayout (){if(Tracker ==null)return; Tracker.UpdateLayout();}public VisualElementTracker Tracker {get;privateset;}public VisualElementPackager Packager {get;privateset;}public Android.Views.ViewGroup ViewGroup {get{returnthis;}}public VisualElement Element {get;privateset;}}} |
You can browse the complete code with a working example on GitHub, https://github.com/dhindrik/Xamarin.Forms-Awesome-Controls
The repository is a fork from James Montemagno’s repository for awesome Xamarin.Forms controls. What I have done is that I have changed a few things so can have layouts as content, a StackLayout for example.