2
votes

I am trying to make a gallery style grid view in Xamarin forms for iOS and Android but have an issue where layout options seem to be ignored and I get different results for iOS and Android.

Basic layout is: frame with a border(red) containing a stack layout (pink) set to FillAndExpand for both horizontal and vertical options which contains a label at the top and an image below set to fill the rest of the stack. The image seems to just expand outside of the stack and the frame and ignore the vertical options set.

I have tried setting these vertical options to Fill, FillAndExpand, CentreAndExpand but all have the same result.

If i remove the Stack layout and label and have the image as the only child element in the frame then it works as expected but I am required to also show a label.

The result is the same in landscape and portrait orientations.

Results on platform with iOS being the main issue here: iOS result Android result Code for adding an image to the grid:

var imageSource = ImageSource.FromStream(() => new MemoryStream(imageData));
var framedImage = new Frame
{
    Padding = 0,
    Margin = 3,
    GestureRecognizers = { tapGesture },
    Content = new StackLayout
    {
        Padding = 10,
        HorizontalOptions = LayoutOptions.FillAndExpand,
        VerticalOptions = LayoutOptions.FillAndExpand,
        BackgroundColor = Color.Pink,
        Children =
        {
            textLabel,
            new Image
            {
                VerticalOptions = LayoutOptions.FillAndExpand,
                HorizontalOptions = LayoutOptions.CenterAndExpand,
                Source = imageSource,
                Aspect = Aspect.AspectFit
            },
        }
    },
    BackgroundColor = StyleSheet.BackgroundColorLight,
    BorderColor = StyleSheet.OutlineColorDark,
    CornerRadius = 5,
    HasShadow = false
};

grid.Children.Add(framedImage, columnCounter, rowCounter);

Thanks in advance!

1
I don't know that StackLayout is the right way to go here. I would try a Grid with two rows. The first's height set to Auto (or some specific value), the second to *. That said, it looks like your design might benefit from using a listview and/or flexlayout.Ben Reierson
Try taking Grid with two rows according to required height inside frame, place label and image within it.MShah
Also, if you are still having trouble getting a Grid to work you could try the new FlexLayoutNick Peppers
@AditKothari I had seen this plugin before starting my own implementation, however I prefer to do it myself as it makes future support (especially when the plugin is no longer developed!) easier. Also, i need the grid to handle different files and not just images.LPQ

1 Answers

1
votes

Fixed it by doing this:

var image = new Image
{
    VerticalOptions = LayoutOptions.FillAndExpand,
    HorizontalOptions = LayoutOptions.FillAndExpand,
    Source = imageSource,
    Aspect = Aspect.AspectFit
};

var framedImage = new Frame
{
    Padding = 2,
    Margin = 1,
    GestureRecognizers = { tapGesture },
    Content = image,
    HasShadow = false,
    VerticalOptions = LayoutOptions.FillAndExpand,
    HorizontalOptions = LayoutOptions.FillAndExpand
};

var innergrid = new Grid
{
    RowDefinitions =
    {
        new RowDefinition {Height = new GridLength(20, GridUnitType.Auto)},
        new RowDefinition {Height = new GridLength(20, GridUnitType.Star)},
    }
};

innergrid.Children.Add(textLabel, 0, 0);
innergrid.Children.Add(framedImage, 0, 1);

var frame = new Frame
{
    Padding = 5,
    Margin = 3,
    GestureRecognizers = { tapGesture },
    Content = innergrid,
    BackgroundColor = StyleSheet.BackgroundColorLight,
    BorderColor = StyleSheet.OutlineColorDark,
    CornerRadius = 5,
    HasShadow = true
};

grid.Children.Add(frame, columnCounter, rowCounter);

I might have a go with the new FlexLayout to see if i can have simpler code