Xamarin.Tip – Expanding ViewCells

Here’s another helpful Xamarin tip to allow you to expand your ViewCells – for example when the user taps a ViewCell, expand it to reveal more information.
Take this gif as an example:

ExpandingCell

There are 3 major parts to making a feature like this work:
1. Bind visibility to the hidden parts of your cell
2. Handle updating that visibility on selection or tap
3. Force the ViewCell to remeasure its size to show the hidden bits.

Let’s first create a new class called ExpandingViewCell:

ExpandingViewCell.cs

/// <summary>
/// Expanding view cell.
/// </summary>
public class ExpandingViewCell : ViewCell
{
    protected override void OnTapped()
    {
        base.OnTapped();
        ForceUpdateSize();
    }
}

Yeah it’s literally that stupid easy. Override OnTapped and call ForceUpdateSize(). However, it’s important to note that this is so easy because of the order – calling the base.OnTapped() first allows for your click / select events to fire off before measuring the size. This means that if we bind an update to show / hide certain controls on tap, those will show first, then we remeasure to make sure they fit.

Here’s the XAML for the ViewCell shown in the gif above:

<components:ExpandingViewCell>
    <StackLayout Orientation="Vertical" Spacing="4" Padding="64,8,16,8" Margin="0">
        <Label Text="{Binding DateLabel}" IsVisible="{Binding ShowDate}" Style="{DynamicResource BodySecondary}" HorizontalOptions="End" HorizontalTextAlignment="End" />
        <Frame CornerRadius="12" Padding="12" Margin="0" BackgroundColor="{Binding MessageColor, Converter={StaticResource ColorConverter}}" VerticalOptions="Center" HorizontalOptions="EndAndExpand" effects:LongPressedEffect.Command="{Binding Path=BindingContext.MessageOptionsCommand,Source={x:Reference Page}}" effects:LongPressedEffect.CommandParameter="{Binding .}">
            <Frame.Effects>
                <effects:LongPressedEffect />
            </Frame.Effects>
            <Label Text="{Binding Content}" Style="{DynamicResource BodySecondary}" />
        </Frame>
        <Label Text="{Binding SentDateLabel}" IsVisible="{Binding IsSentDateVisible}" Style="{DynamicResource BodySecondary}" HorizontalOptions="End" HorizontalTextAlignment="End" />
    </StackLayout>
</components:ExpandingViewCell>

There is a lot going on in this cell (it’s a chat page after all, so it’s a feature rich cell). I even have some long press handlers from my LongPressedEffect that you can read about here: Xamarin.Tip – Xamarin.Forms Long Press Effect

The important pieces to note are the IsVisible="{Binding IsSentDateVisible}" to show the date label or not.

Now in order to update this, we need to bind our SelectedItem in our ListView.

Here’s an example from the gif:

<ListView x:Name="ChatListView" ItemsSource="{Binding Messages}" SelectedItem="{Binding SelectedMessage, Mode=TwoWay}" HasUnevenRows="True" SeparatorVisibility="None" ItemTemplate="{StaticResource BubbleSelector}" />

We use the DataTemplateSelector to choose between the sent bubble and the received bubble, but that isn’t important. If you want to read more about that, check out this doc from Xamarin: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector

Now lastly, let’s look at what’s going on in the ViewModel behind the ListView and how we are binding the SelectedItem.

ChatPageViewModel.cs

...

public ChatMessageViewModel SelectedMessage
{
    get
    {
        return _selectedMessage;
    }
    set
    {
        Set(ref _selectedMessage, value);
        if (value != null)
        {
            ToggleDetails(value);
            SelectedMessage = null;
        }
    }
}

/// <summary>
/// Toggles the details of the given message.
/// </summary>
/// <param name="message">The message view model.</param>
private void ToggleDetails(ChatMessageViewModel message)
{
    message.ShowSenderName = !message.ShowSenderName;
    message.IsSentDateVisible = !message.IsSentDateVisible;
}

...

When the SelectedMessage we bound is changed, and not null, we toggle the ShowSenderName and the IsSentDateVisible to show/hide those views.

So the process looks like this:
– ViewCell is tapped
– ViewCell base call
– SelectedItem toggled
– SelectedMessage toggles the ViewModel properties
– Two way binding triggers to show / hide the inner views
– ViewCell ForceUpdateSize called
– ViewCell expands or collapses

And once again, we get a nice little effect like this!

ExpandingCell


If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

Advertisements

4 thoughts on “Xamarin.Tip – Expanding ViewCells”

  1. Hi Alex! Excellent post. Currently there is a bug with ForceUpdateSize happening in XF under iOS, when you tap multiple times the same cell, each time it fades more slowly, until it freezes… Did you have the same behaviour?

    Like

      1. I had encountered the freezing issue on an app which I was working on. Had resolved it by setting CachingStratergy to RecycleElement. Can you please try it out in your sample, Alex.

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s