Last active
August 29, 2015 14:05
-
-
Save ChaseFlorell/fbe3e43ddd891a27d5ed to your computer and use it in GitHub Desktop.
This is in response to Xamarin Forms Question https://forums.xamarin.com/discussion/21917/best-way-to-reproduce-spotify-grid-view
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Threading.Tasks; | |
| using Xamarin.Forms; | |
| namespace FutureState.AppCore.Pages | |
| { | |
| public class SegmentTab : ContentPage | |
| { | |
| private Grid _grid; | |
| private ScrollView _scrollView; | |
| public SegmentTab(/*Stuff in here*/) | |
| { | |
| Content = BuildPage(segmentPageViewModel); | |
| } | |
| private View BuildPage(SegmentPageViewModel segment) | |
| { | |
| _scrollView = new ScrollView {BackgroundColor = Color.FromHex("#d3d6db")}; | |
| _grid = BuildGrid(segment.SegmentMedia); | |
| // Build the page. | |
| var contentStackLayout = new StackLayout | |
| { | |
| Orientation = StackOrientation.Vertical, | |
| VerticalOptions = LayoutOptions.FillAndExpand, | |
| HorizontalOptions = LayoutOptions.FillAndExpand, | |
| Padding = 10, | |
| Children = | |
| { | |
| _grid, | |
| webView | |
| } | |
| }; | |
| _scrollView.Content = contentStackLayout; | |
| return _scrollView; | |
| } | |
| private Grid BuildGrid(IList<MediaViewModel> segmentMedia) | |
| { | |
| var grid = new Grid | |
| { | |
| RowSpacing = 10, | |
| ColumnSpacing = 10, | |
| Padding = new Thickness(0, 0, 0, 4), | |
| ColumnDefinitions = new ColumnDefinitionCollection | |
| { | |
| new ColumnDefinition {Width = new GridLength(2, GridUnitType.Star)}, | |
| new ColumnDefinition {Width = new GridLength(2, GridUnitType.Star)} | |
| } | |
| }; | |
| BuildTiles(grid, segmentMedia); | |
| return grid; | |
| } | |
| private async void BuildTiles(Grid grid, IList<MediaViewModel> segmentMedia) | |
| { | |
| for (var index = 0; index < segmentMedia.Count; index++) | |
| { | |
| var column = index%2; | |
| var row = (int) Math.Floor(index/2f); | |
| var mediaItem = segmentMedia[index]; | |
| // Awaiting this helps the grid build up rather than locking the UI | |
| var vimeoItem = await GetVimeoStuffAsync(mediaItem.FileLocation.ParseVimeoId()); | |
| vimeoItem.Number = mediaItem.Number; | |
| vimeoItem.Name = mediaItem.Title; | |
| grid.Children.Add(BuildTile(vimeoItem), column, row); | |
| if (column%2 == 0) | |
| { | |
| grid.RowDefinitions.Add(new RowDefinition {Height = 120}); | |
| } | |
| } | |
| } | |
| public View BuildTile(VimeoViewModel mediaItem) | |
| { | |
| var imgSize = new Size(mediaItem.Pictures[0].Width, mediaItem.Pictures[0].Height); | |
| var videoImage = new Image | |
| { | |
| Source = new UriImageSource { | |
| Uri = new Uri(mediaItem.Pictures[0].Link), | |
| CacheValidity = new TimeSpan(10,0,0,0)}, // cache the image for 10 days | |
| Aspect = Aspect.AspectFill | |
| }; | |
| var videoNumberBadge = new RoundedBoxView {WidthRequest = 30, HeightRequest = 30, Color = Color.FromHex(Colors.br_orange), BorderRadius = 50}; | |
| var videoNumber = new Label {Text = mediaItem.Number.ToString(), TextColor = Color.White, Font = Font.SystemFontOfSize(25f)}; | |
| var playIcon = new FontAwesomeLabel {FontSize = 40, Text = FontAwesome.icon_play, TextColor = Color.White}; | |
| var innerLayout = new RelativeLayout {WidthRequest = int.MaxValue, HeightRequest = int.MaxValue, BackgroundColor = Color.Black}; | |
| innerLayout.Children.Add( | |
| videoImage, | |
| Constraint.RelativeToParent(parent => | |
| { | |
| var parentSize = new Size(parent.Width, parent.Height); | |
| var newImgSize = ResizeFit(imgSize, parentSize); | |
| return ((double) Decimal.Subtract((decimal) parent.Width, (decimal) newImgSize.Width))/2; | |
| }), | |
| Constraint.RelativeToParent(parent => | |
| { | |
| var parentSize = new Size(parent.Width, parent.Height); | |
| var newImgSize = ResizeFit(imgSize, parentSize); | |
| return ((double) Decimal.Subtract((decimal) parent.Height, (decimal) newImgSize.Height))/2; | |
| })); | |
| innerLayout.Children.Add(playIcon, | |
| Constraint.RelativeToParent(parent => (parent.Width/2) - 10), | |
| Constraint.RelativeToParent(parent => (parent.Height/2) - 20)); | |
| innerLayout.Children.Add(videoNumberBadge, | |
| Constraint.RelativeToParent(parent => parent.X - 5), | |
| Constraint.RelativeToParent(parent => parent.Y - 5)); | |
| innerLayout.Children.Add(videoNumber, | |
| Constraint.Constant(2.5), | |
| Constraint.RelativeToParent(parent => parent.Y - 8)); | |
| var tile = new ContentView | |
| { | |
| BackgroundColor = Color.White, | |
| Content = innerLayout, | |
| VerticalOptions = LayoutOptions.FillAndExpand | |
| }; | |
| return tile; | |
| } | |
| private static Size ResizeFit(Size originalSize, Size maxSize) | |
| { | |
| var widthRatio = maxSize.Width/originalSize.Width; | |
| var heightRatio = maxSize.Height/originalSize.Height; | |
| var minAspectRatio = Math.Min(widthRatio, heightRatio); | |
| return minAspectRatio > 1 ? originalSize : new Size((int) (originalSize.Width*minAspectRatio), (int) (originalSize.Height*minAspectRatio)); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment