Sam
Sam

Reputation: 30334

Chat layout behavior on iOS in .NET MAUI app

I have a working chat layout but I'm just not very happy with it because it doesn't quite behave the way I want it to on iOS. I wanted to see how others handled it.

Here's my layout:

<Grid
   x:Name="ChatScreen"
   RowDefinitions="*,55"
   RowSpacing="3"
   HorizontalOptions="Fill"
   VerticalOptions="Fill">

   <!-- Messages Section -->
   <CollectionView
      x:Name="ConversationsCollection"
      Grid.Row="0"
      ItemsSource="{Binding Messages}"
      ItemsUpdatingScrollMode="KeepLastItemInView"
      VerticalOptions="Start">
      ... // Omitted for brevity
   </CollectionView>

   <!-- Entry Section -->
   <Grid
      Grid.Row="1"
      ColumnDefinitions="*,50"
      ColumnSpacing="5"
      HorizontalOptions="Fill"
      VerticalOptions="Start">

      <Editor
         Grid.Column="0"
         Text="{Binding Message}"
         AutoSize="TextChanges"
         Focused="ShiftGridUpward"
         Unfocused="ShiftGridDownward"
         HorizontalOptions="Fill" />

      <ImageButton
         Grid.Column="1"
         Command="{SendMessageCommand}"
         WidthRequest="45"
         HorizontalOptions="Center"
         VerticalOptions="Center">
         <ImageButton.Source>
            ... Omitted for brevity
         </ImageButton.Source>
      </ImageButton>

   </Grid>

</Grid>

And in code behind, I handle shifting the Grid up or down like this:

private void ShiftGridUpward(object sender, FocusEventArgs e)
{
    if (DeviceInfo.Current.Platform == DevicePlatform.iOS)
        ChatScreen.TranslateTo(0, -150, 100);
}

private void ShiftGridDownward(object sender, FocusEventArgs e)
{
    if (DeviceInfo.Current.Platform == DevicePlatform.iOS)
        ChatScreen.TranslateTo(0, 0, 100);
}

Here are the problems I'm having with this layout which are more quality than function issues because this layout works OK but quality doesn't seem great on iOS.

First issue is with shifting the Grid up and down so that the soft keyboard doesn't cover the Editor. Below I provided a link to a video that shows the behavior. As you can see, initially, the shift isn't enough and the soft keyboard still covers the Editor. In subsequent tries, it works better, though I still don't find the behavior nice and smooth.

https://s3.amazonaws.com/iQuest/chat_screen_issue.MP4

The second issue is with making sure the last message is displayed, on load as well as after sending/receiving a message.

As you can see in the video, on iOS, the last message is not really showing properly. It's behind the Editor. The ItemsUpdatingScrollMode="KeepLastItemInView" seems to have no effect whatsoever on iOS. So, I handle it by getting the index number of the last message and then manually calling the function below. Even though I call this function on inital load, as you can see, the last message is still not properly positioned.

private void ScrollToLastMessage(object sender, int index)
{
    ConversationsCollection.ScrollTo(index, position: ScrollToPosition.MakeVisible, animate: true);
}

I'd appreciate it if those who've implemented a chat screen successfully in a .NET MAUI app could give me some pointers here.

P.S. BTW, everything works nicely on Android. These are all iOS issues here.

Upvotes: 1

Views: 140

Answers (1)

Libor B.
Libor B.

Reputation: 509

  1. turn off moving up CollectionView by using

KeyboardAutoManagerScroll.Disconnect();

  1. catch keyboard event by

UIKeyboard.Notifications.ObserveWillShow(OnKeyboardShow) UIKeyboard.Notifications.ObserveWillHide(OnKeyboardHide);

and in method OnKeyboardShow change UI for example by changing grid bottom padding:

private void OnKeyboardShow(object sender, UIKeyboardEventArgs e)
{
    if (_grid == null)
        return;

    var keyboardHeight = e.FrameEnd.Height;

    MainThread.BeginInvokeOnMainThread(() => {
        _originalPadding = _grid.Padding; // Uložíme původní hodnotu

        _grid.Padding = new Thickness(
            _originalPadding.Left,
            _originalPadding.Top,
            _originalPadding.Right,
            keyboardHeight - 50 // Přidáme padding pro klávesnici
        );
    });
}

private void OnKeyboardHide(object sender, UIKeyboardEventArgs e)
{
    if (_grid == null) return;

    MainThread.BeginInvokeOnMainThread(() => {
        _grid.Padding = _originalPadding; // Vrátíme původní padding
    });
}

Upvotes: 0

Related Questions