Xamarin.forms: [Bug] Editor "grows" horizontally in iOS until a newline (Enter) is pressed

Created on 19 Nov 2019  路  26Comments  路  Source: xamarin/Xamarin.Forms

Description

This is not easy to explain, but the screenshots and movies should help.

Until the user presses the enter key, the Editor will continue to grow horizontally while inputting text in iOS. This becomes visible when you try to scroll the text. You will notice that you can scroll horizontally (although there is no extra horizontal content, it鈥檚 just whitespace).

Steps to Reproduce

  1. Create a new Xamarin.Forms project
  2. Add an Editor control
  3. Enter a few lines of text without an enter
  4. Try to scroll (horizontally)

Expected Behavior

You can only scroll vertically. When editor uses AutoSize="textchanges" and becomes larger than container, you should see the cursor at the bottom whenever you enter text.

Actual Behavior

You can scroll horizontally and you see whitespace which seems to be equal to the width of all characters combined. Also, when editor is AutoSizing and the size of the editor becomes larger than container, entered text is is not visible. See example movies.

Basic Information

  • Version with issue: Xamarin.Forms 4.3.0.947036 / Xamarin.iOS 13.6.0.12
  • Last known good version: Unknown
  • IDE: Visual Studio for Mac
  • Platform Target Frameworks:

    • iOS: 13.6.0.12

Screenshots

1
2
3

Screen recordings

(Couldn't upload .mov directly, so zipped)
This shows the problem with the cursor and auto expanding:

ExampleScreenRecordings.zip

2 in-progress high impact iOS 馃崕 bug

Most helpful comment

This is somewhat of a setback. Kindly prioritize a fix.

All 26 comments

I have this issue as well.

It works as expected with https://github.com/rdelrosario/ChatUIXForms which uses Xamarin.Forms 3.1.0.637273. Once I upgrade that project to Xamarin.Forms 4.3.0.991211 the functionality breaks as mentioned in the original post.

I noticed that if I hit enter as the first character and then start typing, it works as expected, scrolling to the current line that it being typed on for as many lines as I can type.

If I exclude the enter key and just type text, scrolling is only available horizontally (it should be vertical) and it doesn't allow me to scroll to where I am typing and doesn't autoscroll as I type on new lines.

My info on this is as follows:

  • Version with issue: 4.3.0.991211
  • Last known good version: 3.1.0.637273
  • IDE: Visual Studio Enterprise 2019 for Mac 8.3.10 (build 2)
  • Platform Target Frameworks:

    • iOS: 13.6.0.12

    • Android: 10.0.6.2

    • UWP: NA

  • Android Support Library Version: 28.0.0.3
  • Nuget Packages:
  • Affected Devices: iOS 13

Thanks for the info @renzska

Yep, I see this happening. Here is a repro.

Repro8569.zip

Thank you for acknowledging this bug.

I have a hacky "workaround" for the time being which ensures that the first character in the editor always is a newline. Notice the use of Margin to align the editor (with the newline character using about 16 dp):

  using System;
  using System.Text.RegularExpressions;
  using Xamarin.Forms;

  namespace Converters
  {
      public class StringToStringWithNewLineConverter : IValueConverter
      {
          //https://github.com/xamarin/Xamarin.Forms/issues/8569
          public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
          {
              if (value != null)
              {
                  return $"\n{(string)value}";
              }
              else
              {
                  return "\n";
              }
          }

          public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
          {
              if (value != null)
              {
                  return Regex.Replace((string)value, "^\\n", "");
              }

              return value;
          }
      }
  }

<Editor Text="{Binding Entity.Text, Converter={StaticResource stringToStringWithNewLineConverter}}" Margin="16,0,16,16" AutoSize="TextChanges" />

I ran into this problem as well. You can disable scrolling for Editors on iOS and it fixes this issue, but it obviously prevents scrolling. Wrapping it in a ScrollView will work for most situations, but not all.

Any news on this bug?

On 4.0.0.618610 the problem did not occur.
Currently on 4.3.0.991211, it occurs.
This issue currently blocks the release with the new Xamarin version. When can we expect an update on this issue?

Unfortunately this makes my editor unusable. The hack solution might work, but I would rather prefer to have a non hack one 馃槄

Is it already know which changes causes this bug?

No progress on this issue?

After comparing the current implementation with the working one, I noticed that the function "UpdateCharacterSpacing" was added. So, I tried to used the old implementation in my project, which worked fine for me.

@jfversluis can you please check that out.
Thank you!

Is there any update on this issue at all?

This is somewhat of a setback. Kindly prioritize a fix.

Great find @ttmher thanks! We will definitely look into that

Interesting bug. A few things coincide here.

Because of the character spacing introduction and (what I think) a bug in that code, the placeholder text was set to the actual text of the Editor. _But_ the placeholder label was hidden. Since the UITextView the native control for Editor does not have a placeholder functionality, this is implemented by showing/hiding a label inside the editor control.

However, the text in the placeholder label is not wrapped like the editor text. So, the longer the placeholder text, the further you could scroll to the right.

I've fixed the bug that fills the editor text as a placeholder text wrongfully, but now when you set a placeholder value, the text still doesn't wrap. You can see what I mean below.

image

The grey text is the placeholder, the black text is the editor text value. I have disabled the placeholder show/hide functionality to debug this.

Now I just need to make the placeholder text wrap and we should be all good :)

Again, thanks for the investigation on where this code went wrong @ttmher!

The problem with the placeholder is actually a known issue: https://github.com/xamarin/Xamarin.Forms/issues/4291

Got it, and opened a PR!

I am seeing the same thing. Does anyone know if this is in process or if there are other options for a work around?

Additional learnings:

  1. The vertical scroll is broken so even if your text is wrapped longer than the Editor, it will not scroll vertically.
  2. If the user adds a return or you insert '\n' to the text, it behaves correctly. (We've tried Gerhard's hack, but it is creating other difficulties and makes it feel more 'broken'.)
  3. If you roll back to Xamarin Forms 4.2 (currently on 4.5), the horizontal scroll goes away, but the vertical scroll still does not work

Same problem here.
Definitely It's not possible to use the Editor with this problem.
Hopefully this will be fixed soon

Simple fix on xamarin.forms 4.5

If you are on a page/contentPage add a "ForceLayout" on the parent layout that contains your Editor (inside "OnApearing").

Finally add Margin = new Thickness(0), on the editor.

 protected override void OnAppearing()
{
            base.OnAppearing();
            parentLayout?.ForceLayout();
}

@jeiksegovia Can you post an example? I am having the same issue and am not able to solve it with the solution that you've provided.

@jeiksegovia Can you post an example? I am having the same issue and am not able to solve it with the solution that you've provided.

  1. Add a marging to the Editor:
Editor editor = new Editor{
 WidthRequest = 100,
 VerticalOptions = LayoutOptions.FillAndExpand,
 Margin = new Thickness(0),
};
  1. add your editor to a layout:
    _layout.Children.Add(view, ......constraints)
    in my case my layout is a relativeLayout.
    Your layout should be added to the page somehow

  2. override on appearing method on the page you are showing the Editor:

        protected override void OnAppearing()
        {
            base.OnAppearing();
            _layout.ForceLayout();
        }

I'm using xamarin.forms 4.5.0.396

Hi, would it possible to know which version this fix will go in? thanks a lot

Looks like this was merged into 4.8. The 4.8-pre1 prerelease should be released soon, within the next two weeks

@jfversluis thanks for your reply. We are going live with a client sooner than the release and on iOS we have a conversation page and looks really bad when a user types a message as soon as it goes over 2-3 lines the text is hidden as its not scrolling vertically . Is there a workaround I can do e.g detecting the line wrap and add "\n" to it . tried few things in a renderer but nothing seem to work. thanks again

@developer9969 I appreciate your pending release, unfortunately there is not much we can do about it. A number of workarounds have been named in this issue, if those do not work for you then I'm afraid you will have to wait until the release.

@jfversluis thanks for replying... none of the workaround mentioned works. Lets hope that you release sooner....

I fix using custom renderer

public class CustomEditorRenderer : ViewRenderer<Editor, UITextView>
    {
        public CustomEditorRenderer()
        {
        }
        protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                // Unsubscribe from event handlers and cleanup any resources
                Control?.Dispose();
            }
            if (e.NewElement == null)
            {
                return;
            }
            if (Control == null)
            {
                var temp = new UITextView();

                temp.Text = (string)e.NewElement.Text;
                temp.Changed += (object sender, EventArgs args) =>
                {
                    this.Element.Text = ((UITextView)sender).Text;
                };

                SetNativeControl(temp);
            }


        }
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == VisualElement.WidthProperty.PropertyName ||
                e.PropertyName == VisualElement.HeightProperty.PropertyName)
            {
                if (Element != null && Element.Bounds.Height > 0 && Element.Bounds.Width > 0)
                {

                    Control.Frame = new CoreGraphics.CGRect(Control.Frame.X, Control.Frame.Y, Element.Width, Element.Height);
                    Control.SetNeedsDisplay();
                    //update size on native control's subviews
                    // or use SetNeedsDisplay() to re-draw
                    //Note: force update to Control's size is not recommended (as it is recommended it be same as forms element)
                    //Instead add a subview that you can update for size here
                }
            }
            else if (e.PropertyName == "Text")
            {
                if (Element != null)
                {
                    Control.Text = Element.Text;
                }
            }
        }
    }
Was this page helpful?
0 / 5 - 0 ratings