Xamarin Forms: Spacing issue between keyboard and the bottom layout in chat page

Sreejith Sreenivasan 691 Reputation points
2023-03-01T14:28:18.15+00:00

I am using a CustomEditorRenderer to solve the spacing issue between keyboard and Editor. I already posted a ticket related to that. Now I have attachment and send icons are in the same place. But when the keyboard appears, only Editor is showing on the UI, the attachment and send icons are not showing.

UI:

enter image description here

My XAML:

<Grid 
x:Name="newcomment_stack"
Margin="2,0,2,10"
IsVisible="false">

<Grid.RowDefinitions>
	<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
	<ColumnDefinition Width="Auto" />
	<ColumnDefinition Width="8*" />
	<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<Image 
Grid.Row="0" 
Grid.Column="0"
VerticalOptions="CenterAndExpand"
x:Name="Attachment_Image"
Source="ic_attachment_xx.png">
	<Image.WidthRequest>
		<OnIdiom x:TypeArguments="x:Double">
			<OnIdiom.Phone>40</OnIdiom.Phone>
			<OnIdiom.Tablet>60</OnIdiom.Tablet>
			<OnIdiom.Desktop>40</OnIdiom.Desktop>
		</OnIdiom>
	</Image.WidthRequest>
	<Image.HeightRequest>
		<OnIdiom x:TypeArguments="x:Double">
			<OnIdiom.Phone>40</OnIdiom.Phone>
			<OnIdiom.Tablet>60</OnIdiom.Tablet>
			<OnIdiom.Desktop>40</OnIdiom.Desktop>
		</OnIdiom>
	</Image.HeightRequest>
</Image>

<renderer:CustomEditor
	Grid.Row="0" 
	Grid.Column="1"
	x:Name="commentbody_entry"
	Placeholder="Add your comment here"
	BackgroundColor="#f1f1f1"
	PlaceholderColor = "#a39ea1"
	TextColor = "#54493b"
	TextChanged="commentbody_entry_TextChanged"
	Style="{StaticResource AddCommentEditorStyle}">
	<renderer:CustomEditor.HeightRequest>
		<OnIdiom x:TypeArguments="x:Double">
			<OnIdiom.Phone>60</OnIdiom.Phone>
			<OnIdiom.Tablet>90</OnIdiom.Tablet>
			<OnIdiom.Desktop>60</OnIdiom.Desktop>
		</OnIdiom>
	</renderer:CustomEditor.HeightRequest>
</renderer:CustomEditor>

<StackLayout 
	x:Name="sendcomment_stack"
	IsEnabled="False"
	VerticalOptions="CenterAndExpand"
	Grid.Row="0" 
	Grid.Column="2">
	<Image 
		x:Name="sendcomment_image"
		Source="ic_gray_sendcomment_xx.png">
		<Image.WidthRequest>
			<OnIdiom x:TypeArguments="x:Double">
				<OnIdiom.Phone>40</OnIdiom.Phone>
				<OnIdiom.Tablet>60</OnIdiom.Tablet>
				<OnIdiom.Desktop>40</OnIdiom.Desktop>
			</OnIdiom>
		</Image.WidthRequest>
		<Image.HeightRequest>
			<OnIdiom x:TypeArguments="x:Double">
				<OnIdiom.Phone>40</OnIdiom.Phone>
				<OnIdiom.Tablet>60</OnIdiom.Tablet>
				<OnIdiom.Desktop>40</OnIdiom.Desktop>
			</OnIdiom>
		</Image.HeightRequest>
	</Image>
	<StackLayout.GestureRecognizers>
		<TapGestureRecognizer
			Tapped="Send_Comment"
			NumberOfTapsRequired="1">
		</TapGestureRecognizer>
	</StackLayout.GestureRecognizers>
</StackLayout>
</Grid>

My CustomEditorRenderer in IOS:

public class CustomEditorRenderer : EditorRenderer
{
	public CustomEditorRenderer()
	{
		UIKeyboard.Notifications.ObserveWillShow((sender, args) =>
		{
			if (Element != null)
			{
				Element.Margin = new Thickness(0, 0, 0, args.FrameEnd.Height); //push the entry up to keyboard height when keyboard is activated
			}
		});

		UIKeyboard.Notifications.ObserveWillHide((sender, args) =>
		{
			if (Element != null)
			{
				Element.Margin = new Thickness(0); //set the margins to zero when keyboard is dismissed
			}
		});
	}

	protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
	{
		base.OnElementChanged(e);

		if (Control != null)
		{
			Control.Layer.CornerRadius = 10;
			Control.TextColor = UIColor.Black;
		}
	}
}

Is there any way to pull up the send and attachment icons when the keyboard appears?

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,297 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Wenyan Zhang (Shanghai Wicresoft Co,.Ltd.) 26,751 Reputation points Microsoft Vendor
    2023-03-02T06:12:03.79+00:00

    Hello,

    Your issue is that the grid with editor and images is covered by keyboard. There are two ways to solve the problem, the first one is to replace the parent element by ScrollView, it's a simple solution. The second one is to do some animation so that the parent element goes up/down when the keyboard is shown/hidden, how to calculate the exact offset is the key point.

    First solution:

    <ScrollView>
            <StackLayout>
                <!-- a fake topview-->
                <StackLayout WidthRequest="300" HeightRequest="500" BackgroundColor="Pink"></StackLayout>
                <!--your code snippets including two images and an Editor -->
              <Grid ...>
                 <Image...> </Image>
    
                <Editor ... no need the use custom renderer> </Editor>
    
                <StackLayout...>
                </StackLayout>
            </Grid>
            </StackLayout>
        </ScrollView>
    

    Second solution:

    <!-- remove the scrollview-->
            <StackLayout>
                <!-- a fake topview-->
                <StackLayout WidthRequest="300" HeightRequest="500" BackgroundColor="Pink"></StackLayout>
                <!--your code snippets including two images and an Editor -->
              <Grid ...>
                 <Image...> </Image>
    
                <renderer:CustomEditor...  use custom renderer> </Editor>
    
                <StackLayout...>
                </StackLayout>
            </Grid>
            </StackLayout>
    

    CustomRenderer

    public CustomEditorRenderer()
            {
                UIKeyboard.Notifications.ObserveWillShow((sender, args) =>
                {
                    NSDictionary userInfo = args.Notification.UserInfo;
                    CGRect keyboardRect = args.FrameEnd;
    
                    UIView view = Control.Superview;//get the superview
    
                    keyboardRect = view.ConvertRectFromView(keyboardRect, null);
    
                    var keyboardTop = keyboardRect.Y;
    
                    CGRect rect = view.ConvertRectFromView(Control.Frame, view);
    
                    NSNumber animationDurationValue = (NSNumber)userInfo.ObjectForKey(UIKeyboard.AnimationDurationUserInfoKey);
    
                    if (keyboardTop < rect.GetMaxY())// compare if the view is covered by the keyboard
                    {
                        var gap = keyboardTop - rect.GetMaxY();//calculate the offset and make animation
                        UIView.Animate((double)animationDurationValue, () =>
                        {
                            view.Superview.Superview.Superview.Frame = new CGRect(view.Superview.Superview.Superview.Frame.X, gap, view.Superview.Superview.Superview.Frame.Size.Width, view.Superview.Superview.Superview.Frame.Size.Height);// the view.Superview.Superview.Superview is pagecontainer (grid->stacklayout->page), if your XAML is different from mine, you can try to modify the superview to find the pagecontainer
                        });
                    }
    
                });
    
                UIKeyboard.Notifications.ObserveWillHide((sender, args) =>
                {
    
                    UIView view = Control.Superview;
                    NSNumber animationDurationValue = (NSNumber)args.Notification.UserInfo.ObjectForKey(UIKeyboard.AnimationDurationUserInfoKey);
                    UIView.Animate((double)animationDurationValue, () =>
                    {
                        view.Superview.Superview.Superview.Frame = new CGRect(view.Superview.Superview.Superview.Frame.X, 0, view.Superview.Superview.Superview.Frame.Size.Width, view.Superview.Superview.Superview.Frame.Size.Height);// if the Safeara is enabled, you also should consider the height of Safeara 
                    });
                });
            }
    
    

    Best Regards,

    Wenyan Zhang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.