All credits to the original author for doing this. Although I’m trying to extend it in the coming days, but props to Adam for finding this one out!
Go to https://www.syntaxismyui.com/xamarin-forms-in-anger-cards/ and follow his other tutorial as well.
The #1 request I get for the Xamarin.Forms in Anger is for a Google or Facebook like card view. Today is the day that I fulfill those requests.
To be completely honest, I’ve been thinking about how to do a card view for a while and let me tell you, it’s not easy. Especially when you try to stick with the “in the box” components of Xamarin.Forms. My first attempt at it was hideous.
Hideous Forms
Hideous would be the most polite way of saying it was crap. I started off using BoxViews to draw the lines and contain the whole thing in a Xamarin.Forms Grid. Ouch, yes hideous.
The Grid was becoming a nightmare with all the extra rows and columns needed for lines. What I wouldn’t do for some HTML Tables with a borders = 1 in Xamarin.Forms. I thought of putting in a feature request to the team, but didn’t. I don’t want them to laugh at me. 😉
Waffle Fries to the Rescue
With the BoxViews not working out, I went to lunch to clear my head and to think. I love lunch and I don’t miss a meal. That day, I decided to go to Chick Fil A and get a chicken sandwich with a side of epiphany fries.
There I was, eating my chicken and dunking my fries in ketchup (Sauce de American). When I dipped a waffle fry into the ketchup, the ketchup squeezed through the holes and made a red checkerboard on top of the fry. Then it hit me. Bam!
I was going about the card UI backwards or forwards. Either way, it was the wrong way. I had to do an about face and approach it in another way. The way the ketchup came up through the fry not by putting ketchup onto the fry.
A Grid of Lines
As soon as I got home, I worked up a Xamarin.Forms Grid with some padding, row and column spacing. In addition to those settings, I also set the background color of the grid to a medium dark grey. Then added ContentViews with white backgrounds into each cell of the Grid. This is what it looked like when I finished.
The white panels acted like the ketchup on my waffle fries and the borders are the potato. Yes, I know, it’s strange to describe Xamarin.Forms design techniques using food, but stay with me; it gets better. Now that I knew the technique worked and was a heck of a lot less messy, I pushed on.
Content View Panels
Each CardView is made up of 5 ContentViews with a background color set to the designed color. Here are some of the background colors for each panel.
The CardView.cs file would have been gigantic if I kept all the code in the same file so I broke it up into different ContentViews. Here are the names for each ContentView that makes up the CardView.
The CardDetailsView has a column span of three to horizontally bridge the two IconLableViews and the ConfigIconView. The CardStatusView has a row span of two to complete the vertical lefthand status bar.
The CardView Code
For the demo, I put a couple of CardViews in a vertical StackLayout. If I had a lot of cards, I would prefer to use a ListView. Hopefully a reader will let me know how well this design works in a ListView. It should be ok, especially while using the Grid and not a bunch of nested StackLayouts. I’ve learned my lesson.
public class CardView : ContentView { public CardView (Card card) { Grid grid = new Grid { Padding = new Thickness (0, 1, 1, 1), RowSpacing = 1, ColumnSpacing = 1, BackgroundColor = StyleKit.CardBorderColor, VerticalOptions = LayoutOptions.FillAndExpand, RowDefinitions = { new RowDefinition { Height = new GridLength (70, GridUnitType.Absolute) }, new RowDefinition { Height = new GridLength (30, GridUnitType.Absolute) } }, ColumnDefinitions = { new ColumnDefinition { Width = new GridLength (4, GridUnitType.Absolute) }, new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star) }, new ColumnDefinition { Width = new GridLength (100, GridUnitType.Absolute) }, new ColumnDefinition { Width = new GridLength (50, GridUnitType.Absolute) } } }; grid.Children.Add ( new CardStatusView (card) , 0, 1, 0, 2); grid.Children.Add (new CardDetailsView (card), 1, 4, 0, 1); grid.Children.Add ( new IconLabelView ( card.StatusMessageFileSource, card.StatusMessage ) , 1, 1); grid.Children.Add ( new IconLabelView ( card.ActionMessageFileSource, card.ActionMessage ) , 2, 1); grid.Children.Add (new ConfigIconView (), 3, 1); Content = grid; } }
With all the refactoring; the CardView looks small and plain but the devil is in the ContentViews.
Final Layout:
Solution
The code for this sample is up on GitHub in the “In Anger” repository. For this post, I broke the code out into a separate directory and solution to make it easier for you to reuse the CardView without getting confused with all the other code and resources from other posts.
Moar Epiphany Fires
Who knew that a humble waffle fry would be the answer to the Xamarin.Forms CardView? Not me; I go for the chicken. Don’t you worry dear read, I will continue to go to “Chick Fil a” to get more Xamarin.Forms design inspiration in the future. Stay tuned to this blog and, if you have a design challenge, just put it in the comments below or email me at adam [at] adamjwolf dot com.
Xamarin.Forms in Anger Series
Can Xamarin.Forms produce good looking cross-platform UI from a single codebase? Each “In Anger” blog post will tackle a single page of a beautifully designed iOS or Android application. My job will be to reproduce the design in Xamarin.Forms as faithfully as possible.