Search code examples
c#xamlmauimaui-windows

MAUI - Calculate collection view grid columns using available width


I, i am exploring .NET MAUI, and trying to sample some things, and one thing i came across was, how can i calculate a collection view grid column number, to fit the available space.

I managed to get it working on some way, but only discovered how to get de device screen width, but my main goal is to use the app on desktop too, and on desktop not always going to be used on full screen, so the calculation does not work very well.

So far i got this, using a binding to the calculation on the view model using the device screen width, to the GridItemsLayout Span:

XAML:

<StackLayout>
        <CollectionView ItemsSource="{Binding MenuItems}"
                        x:Name="clvMenuItems">
            <CollectionView.ItemsLayout>
                <GridItemsLayout 
                    Orientation="Vertical"
                    Span="{Binding NumHorizontalViewMenuItems}"
                    VerticalItemSpacing="4"
                    HorizontalItemSpacing="4" />
            </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid RowDefinitions="Auto, *" BackgroundColor="Orange">
                        <ImageButton Grid.Row="0"
                           HorizontalOptions="Start"
                           AbsoluteLayout.LayoutBounds="25,12,39,39"
                           Margin="16,16,0,8"
                            MaximumHeightRequest="50"
                           Source="{Binding Icon}"/>

                        <Label VerticalOptions="Start"
                           HorizontalOptions="End"
                           IsVisible="{Binding ShowBadge}"
                           WidthRequest="38"
                           Margin="16"
                           FontAttributes="Bold"
                           FontSize="16"
                           Text="NEW"
                           TextColor="{DynamicResource BadgeThemeColor}"/>
                        <Label Grid.Row="1"
                           VerticalTextAlignment="End"
                           Margin="16,0,10,16"
                           HorizontalTextAlignment="Start"
                           Text="{Binding Name}"
                           FontSize="16"
                           FontFamily="Roboto"
                           MaxLines="2"
                           LineHeight="1"
                           LineBreakMode="WordWrap"
                           TextColor="{DynamicResource TextThemeColor}"
                           BackgroundColor="Transparent" />
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </StackLayout>

ViewModel:

        public int NumHorizontalViewMenuItems => CalcHorizontalViewMenuItems();

        static int MenuItemMaxWidth = 120;

        private int CalcHorizontalViewMenuItems()
        {
            return (int)Math.Floor(DeviceDisplay.Current.MainDisplayInfo.Width / MenuItemMaxWidth);
        }

Any help would be appreciated! Thanks


Solution

  • Has @ewerspej suggested, i used FlexLayout with a BindableLayout instead of CollectionView, because its design is more equal to what i was trying to reach, some kind of a tyle menu, that fits more on bigger screens or less on smaller screens.

    I leave here a sample of what i've done:

    <ScrollView VerticalOptions="Start">
        <FlexLayout VerticalOptions="Start"
                    HorizontalOptions="Fill"
                    Direction="Row"
                    Wrap="Wrap"
                    AlignContent="Start"
                    AlignItems="Start"
                    JustifyContent="Start"
                    Margin="5"
                    Padding="0"
                    BindableLayout.ItemsSource="{Binding MenuItems}">
            <BindableLayout.ItemTemplate>
                <DataTemplate>
                    <Grid RowDefinitions="Auto, *" BackgroundColor="Transparent" Margin="2">
                        <Grid.GestureRecognizers>
                            <TapGestureRecognizer 
                                Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:MainViewModel}}, Path=OpenMenuCommand}"
                                CommandParameter="{Binding .}"/>
                        </Grid.GestureRecognizers>
    
                        <Image Grid.Row="0"
                           HorizontalOptions="Center"
                           AbsoluteLayout.LayoutBounds="25,12,39,39"
                           Margin="5"
                           MaximumHeightRequest="50"
                           MaximumWidthRequest="50"
                           Source="{Binding Icon}"/>
    
                        <Label VerticalOptions="Start"
                           HorizontalOptions="End"
                           IsVisible="{Binding ShowBadge}"
                           WidthRequest="38"
                           Margin="5"
                           FontAttributes="Bold"
                           FontSize="14"
                           Text="NEW"
                           TextColor="{DynamicResource BadgeThemeColor}"/>
                        
                        <Label Grid.Row="1"
                           VerticalTextAlignment="End"
                           Margin="5,0,5,5"
                           HorizontalTextAlignment="Center"
                           Text="{Binding Name}"
                           FontSize="16"
                           FontFamily="Roboto"
                           WidthRequest="90"
                           MaximumWidthRequest="90"
                           MaxLines="3"
                           LineHeight="1"
                           LineBreakMode="WordWrap"
                           TextColor="{DynamicResource TextThemeColor}"
                           BackgroundColor="Transparent" />
    
                    </Grid>
                </DataTemplate>
            </BindableLayout.ItemTemplate>
        </FlexLayout>
    </ScrollView>
    

    Thanks for the help.