Search code examples
xamarinxamarin.formscarousel

Xamarin.Forms CarouselView: lower opacity of unselected items


I have a Xamarin.Forms Vertical CarouselView where the PeakAreaInsets is set pretty high so I can see multiple items in the list at once. I want a way to be able to visually show which item in the list is currently "focused" or selected. Is there a way to dynamically change the opacity of Items in a Carousel View as you scroll through it, so as to show which one is currently selected?

Here's a snippet of my code if that helps:

<CarouselView ItemsSource="{Binding Days}"
                  CurrentItem="{Binding SelectedDay}"
                  VerticalOptions="Center"
                  HorizontalOptions="Center"
                  PeekAreaInsets="300"
                  x:Name="DayCarousel">
        <CarouselView.ItemsLayout>
            <LinearItemsLayout SnapPointsAlignment="Center"
                               SnapPointsType="Mandatory"
                               Orientation="Vertical"/>
        </CarouselView.ItemsLayout>
        <CarouselView.ItemTemplate>
            <DataTemplate>
                <StackLayout Spacing="0"
                             Orientation="Vertical"
                             HorizontalOptions="Center"
                             VerticalOptions="Center"
                             Margin="30,10">
                    <Label Text="{Binding FormattedDate}"
                           HorizontalOptions="Center"
                           VerticalOptions="Center"
                           Style="{StaticResource LabelStyle}"/>
                    <Label Text="{Binding TitleText}"
                           HorizontalOptions="Center"
                           VerticalOptions="Center"
                           Style="{StaticResource LabelHeader1Style}"/>
                    <StackLayout.GestureRecognizers>
                        <TapGestureRecognizer Command="{Binding BindingContext.SelectDay, Source={x:Reference this}}"
                                              CommandParameter="{Binding .}"/>
                    </StackLayout.GestureRecognizers>
                </StackLayout>
            </DataTemplate>
        </CarouselView.ItemTemplate>
    </CarouselView>

Here is an illustration of what I am looking for:

enter image description here


Solution

  • Thanks to @MouseOnMars

    Here is the xaml that made this work.

            <CarouselView ItemsSource="{Binding Days}"
                      CurrentItem="{Binding SelectedDay}"
                      VerticalOptions="Center"
                      HorizontalOptions="Center"
                      PeekAreaInsets="300"
                      x:Name="DayCarousel">
            <CarouselView.ItemsLayout>
                <LinearItemsLayout SnapPointsAlignment="Center"
                                   SnapPointsType="Mandatory"
                                   Orientation="Vertical"/>
            </CarouselView.ItemsLayout>
            <CarouselView.ItemTemplate>
                <DataTemplate>
                    <StackLayout Spacing="0"
                                 Orientation="Vertical"
                                 HorizontalOptions="Center"
                                 VerticalOptions="Center"
                                 Margin="30,10"
                                 Opacity=".25">
                        <StackLayout.Triggers>
                            <DataTrigger TargetType="StackLayout"
                                         Binding="{Binding IsSelected}"
                                         Value="True">
                                <Setter Property="Opacity"
                                        Value="1"/>
                            </DataTrigger>
                        </StackLayout.Triggers>
                        <Label Text="{Binding FormattedDate}"
                               HorizontalOptions="Center"
                               VerticalOptions="Center"
                               Style="{StaticResource LabelStyle}"/>
                        <Label Text="{Binding TitleText}"
                               HorizontalOptions="Center"
                               VerticalOptions="Center"
                               Style="{StaticResource LabelHeader1Style}"/>
                        <StackLayout.GestureRecognizers>
                            <TapGestureRecognizer Command="{Binding BindingContext.SelectDay, Source={x:Reference this}}"
                                                  CommandParameter="{Binding .}"/>
                        </StackLayout.GestureRecognizers>
                    </StackLayout>
                </DataTemplate>
            </CarouselView.ItemTemplate>
        </CarouselView>
    

    I had to add a new bool property "IsSelected" to the Model that the ItemTemplate is bound to. Then I had to add some logic in my "SelectedDay" Property on my Page ViewModel to turn on and off the IsSelected bool. Additionally since I am binding the CarouselView directly to a model I had to raise property Changed on the model for IsSelected whenever it was switched on or off.