Avacay
Avacay

Reputation: 163

Control width of element in CarouselView

So I have a CarouselView in my app. Within my CarouselView, I have a label with a long text.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="10*"/>
        <RowDefinition Height="65*"/>
        <RowDefinition Height="25*"/>
    </Grid.RowDefinitions>
    <CarouselView ItemsSource="{Binding .}" BackgroundColor="Transparent" HorizontalOptions="Center" VerticalOptions="Center">
        <CarouselView.ItemsLayout>
            <GridItemsLayout SnapPointsAlignment="Center" SnapPointsType="MandatorySingle" Orientation="Horizontal" HorizontalItemSpacing="20"/>
       </CarouselView.ItemsLayout>
       <CarouselView.ItemTemplate>
           <DataTemplate>
               <Grid Grid.Row="1">
                   <Grid.ColumnDefinitions>
                       <ColumnDefinition Width="0.1*"/>
                       <ColumnDefinition Width="0.8*"/>
                       <ColumnDefinition Width="0.1*"/>
                   </Grid.ColumnDefinitions>
                   <Frame VerticalOptions="Fill" BackgroundColor="Accent" Grid.Column="1">
                       <StackLayout VerticalOptions="Center">
                           <Label Text="{Binding TextExample}"/>
                       </StackLayout>
                   </Frame>
                </Grid>
            </DataTemplate>
       </CarouselView.ItemTemplate>
    </CarouselView>
</grid>

I realized, that no matter what I do, the width of CarouselView Frame is controlled by the length of the text in the label - which means, that the Frame exceeds the boundaries of the view.

I can though set the widthrequest of the frame to a desirable width, which will cause the text in the label to wrap, thus meaning that the width of the Frame doesn't exceed the boundaries of the view. Unfortunately, I would much rather prefer to control the width of the Frame by a relative width-percentage to the view - Which I have tried to do in the above code.

enter image description here

Upvotes: 0

Views: 2734

Answers (3)

Torben Schramme
Torben Schramme

Reputation: 2140

The Solution of Lucas Zhang pointed me the right way, although it has some drawbacks. First it requires a lot of Code behind in App and ViewModel, and the main flaw is that it is not responsive, i.e. when the user turns his screen.

It is much easier to name the CarouselView and then bind the DesiredWidh of the DataTemplate directly to the Width of the CarouselView.

<CarouselView HeightRequest="200" ItemSizingStrategy="MeasureAllItems" 
              x:Name="ctlCarousel">
    <CarouselView.ItemsLayout>
        <ListItemsLayout Orientation="Horizontal" SnapPointsAlignment="Center" SnapPointsType="Mandatory" />
    </CarouselView.ItemsLayout>
    <CarouselView.ItemTemplate>
        <DataTemplate>
            <Grid WidthRequest="{Binding Source={x:Reference ctlCarousel}, Path=Width}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="5" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="5" />
                </Grid.ColumnDefinitions>
                <Frame HorizontalOptions="Fill" Grid.Column="1">
                    <Grid>
                        <Label Text="{Binding}" />
                    </Grid>
                </Frame>
            </Grid>
        </DataTemplate>
    </CarouselView.ItemTemplate>
    <CarouselView.ItemsSource>
        <x:Array Type="{x:Type x:String}">
            <x:String>Hello World!</x:String>
            <x:String>This is a very long string</x:String>
            <x:String>Card 3</x:String>
            <x:String>Test 123</x:String>
        </x:Array>
    </CarouselView.ItemsSource>
</CarouselView>

Upvotes: 5

Lucas Zhang
Lucas Zhang

Reputation: 18861

Cause: You seem to have forgotten to set the width of DataTemplate. So ,the width of grid is controlled by the length of the text in the label .

Solution: From your code , you seem to let the width of DataTemplate equals the width of screen. So you can binding the width in code behind .

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Name="contentPage"   // set the name of the contentpage
             x:Class="xxx.MainPage">
<Grid WidthRequest="{Binding Source={x:Reference contentPage}, Path=BindingContext.Width}">
    <Grid.ColumnDefinitions>
         <ColumnDefinition Width="0.1*"/>
         <ColumnDefinition Width="0.8*"/>
         <ColumnDefinition Width="0.1*"/>
    </Grid.ColumnDefinitions>
    <Frame VerticalOptions="Fill" BackgroundColor="Accent" Grid.Column="1">
         <StackLayout VerticalOptions="Center">
                 <Label Text="{Binding xxx}"/>
         </StackLayout>
    </Frame>
</Grid>

in Share Project App.xaml.cs

public static double ScreenWidth;
public static double ScreenHeight;

in Android MainActivity.cs

protected override void OnCreate(Bundle savedInstanceState)
{
   TabLayoutResource = Resource.Layout.Tabbar;
   ToolbarResource = Resource.Layout.Toolbar;

   base.OnCreate(savedInstanceState);

   Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            
   global::Xamarin.Forms.Forms.SetFlags("Shell_Experimental", "Visual_Experimental", "CollectionView_Experimental");
   global::Xamarin.Forms.Forms.Init(this, savedInstanceState);

   App.ScreenWidth = Resources.DisplayMetrics.WidthPixels/Resources.DisplayMetrics.Density; 
   App.ScreenHeight =Resources.DisplayMetrics.HeightPixels/Resources.DisplayMetrics.Density; 

   LoadApplication(new App());
}

in iOS

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    //...
    App.ScreenWidth = (int)UIScreen.MainScreen.Bounds.Width;
    App.ScreenHeight = (int)UIScreen.MainScreen.Bounds.Height;
    //...
}

in Code Behind or ViewModel

public double Width { get; private set; }

//...

Width = App.ScreenWidth;

Upvotes: 1

Muhammad Abu Mandor
Muhammad Abu Mandor

Reputation: 295

You can use relative layout and set width of frame relative to width of any view

Upvotes: -1

Related Questions