[Enhancement] Entry: Read-only Entry and Editor (#1972)
authorAlmir Vuk <almir.vuk@outlook.com>
Thu, 10 Jan 2019 16:21:29 +0000 (17:21 +0100)
committerShane Neuville <shane94@hotmail.com>
Thu, 10 Jan 2019 16:21:28 +0000 (09:21 -0700)
- fixes #1678
- fixes #4834

* InputView BindableProperty IsReadOnly

* Android Editor and Entry setup

* MacOS Editor and Entry setup

* Tizen Editor and Entry setup

* UAP Editor and Entry setup

* WPF Editor and Entry setup

* iOS Editor and Entry setup

* Issue1678 - TestContentPage added

* Tests added

* Tizen Editor and Entry fix

* UI Test fix

* Android fix for Entry and Editor.

* Unit Tests fix.

* Android Renderer first try.

* MacOS Entry renderer small fix.

* UpdateEditable fix.

* Android Entry and Editor reduced number of calls to BP.

* fix TestAttributes conflicts

* Remove keyboard

* [macOS] relinquish first responder

* [Android] remove call to UpdateCursorSelection

* [UWP] fix tabs

21 files changed:
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1678.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Controls/CoreGalleryPages/EditorCoreGalleryPage.cs
Xamarin.Forms.Controls/CoreGalleryPages/EntryCoreGalleryPage.cs
Xamarin.Forms.Core.UnitTests/EditorTests.cs
Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs
Xamarin.Forms.Core.UnitTests/NotifiedPropertiesTests.cs
Xamarin.Forms.Core/InputView.cs
Xamarin.Forms.CustomAttributes/TestAttributes.cs
Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs
Xamarin.Forms.Platform.Android/Renderers/EntryRenderer.cs
Xamarin.Forms.Platform.MacOS/Renderers/EditorRenderer.cs
Xamarin.Forms.Platform.MacOS/Renderers/EntryRenderer.cs
Xamarin.Forms.Platform.Tizen/Renderers/EditorRenderer.cs
Xamarin.Forms.Platform.Tizen/Renderers/EntryRenderer.cs
Xamarin.Forms.Platform.UAP/EditorRenderer.cs
Xamarin.Forms.Platform.UAP/EntryRenderer.cs
Xamarin.Forms.Platform.WPF/Renderers/EditorRenderer.cs
Xamarin.Forms.Platform.WPF/Renderers/EntryRenderer.cs
Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs
Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1678.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue1678.cs
new file mode 100644 (file)
index 0000000..45aebfa
--- /dev/null
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Github, 1678, "[Enhancement] Entry: Read-only entry", PlatformAffected.All)]
+       public class Issue1678 
+               : TestContentPage
+       {
+               protected override void Init()
+               {
+                       var entryText = "Entry Lorem Ipsum";
+                       var editorText = "Editor Lorem Ipsum";
+
+                       var entryDefaults = new Entry { Text = entryText };
+                       var editorDefaults = new Editor { Text = editorText };
+                       var entryReadOnly = new Entry { Text = entryText, IsReadOnly = true };
+                       var editorReadOnly = new Editor { Text = editorText, IsReadOnly = true };
+                       var entryToggleable = new Entry { Text = entryText };
+                       var editorToggleable = new Editor { Text = editorText };
+
+                       var toggle = new Switch { IsToggled = false };
+
+                       var stackLayout = new StackLayout();
+                       stackLayout.Children.Add(new Label { Text = "Defaults" });
+                       stackLayout.Children.Add(entryDefaults);
+                       stackLayout.Children.Add(editorDefaults);
+                       stackLayout.Children.Add(new Label { Text = "Read Only" });
+                       stackLayout.Children.Add(entryReadOnly);
+                       stackLayout.Children.Add(editorReadOnly);
+                       stackLayout.Children.Add(new Label { Text = "Toggleable is read only" });
+                       stackLayout.Children.Add(entryToggleable);
+                       stackLayout.Children.Add(editorToggleable);
+                       stackLayout.Children.Add(toggle);
+
+                       toggle.Toggled += (_, b) =>
+                       {
+                               entryToggleable.IsReadOnly = b.Value;
+                               editorToggleable.IsReadOnly = b.Value;
+                       };
+
+                       stackLayout.Padding = new Thickness(0, 20, 0, 0);
+                       Content = stackLayout;
+               }
+       }
+}
index f5c9c8a..78e8d92 100644 (file)
@@ -35,6 +35,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Issue3788.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue1724.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue3524.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Issue1678.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue2004.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue3333.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Issue2338.cs" />
index b8ba817..2f961e5 100644 (file)
@@ -40,6 +40,8 @@ namespace Xamarin.Forms.Controls
 
                        var maxLengthContainer = new ViewContainer<Editor>(Test.InputView.MaxLength, new Editor { MaxLength = 3 });
 
+                       var readOnlyContainer = new ViewContainer<Editor>(Test.Editor.IsReadOnly, new Editor { Text = "This is read-only Editor", IsReadOnly = true });
+
                        Add(completedContainer);
                        Add(textContainer);
                        Add(textChangedContainer);
@@ -54,6 +56,7 @@ namespace Xamarin.Forms.Controls
                        Add(textColorDisabledContainer);
                        Add(keyboardContainer);
                        Add(maxLengthContainer);
+                       Add(readOnlyContainer);
                }
        }
 }
\ No newline at end of file
index 67bc5cd..8368f08 100644 (file)
@@ -66,6 +66,7 @@ namespace Xamarin.Forms.Controls
 
                        var maxLengthContainer = new ViewContainer<Entry>(Test.InputView.MaxLength,     new Entry { MaxLength = 3 });
 
+                       var readOnlyContainer = new ViewContainer<Entry>(Test.Entry.IsReadOnly, new Entry { Text = "This is read-only Entry", IsReadOnly = true });
                        var isPasswordInputScopeContainer = new ViewContainer<Entry>(Test.Entry.IsPasswordNumeric,      new Entry { Keyboard = Keyboard.Numeric });
                        var switchPasswordButton = new Button
                        {
@@ -110,6 +111,7 @@ namespace Xamarin.Forms.Controls
                        Add (placeholderColorDisabledContainer);
                        Add (passwordColorContainer);
                        Add (maxLengthContainer);
+                       Add (readOnlyContainer);
                        Add (isPasswordInputScopeContainer);
                }
        }
index c16f1d2..b4a969b 100644 (file)
@@ -30,5 +30,19 @@ namespace Xamarin.Forms.Core.UnitTests
                        Assert.AreEqual (initialText, oldText);
                        Assert.AreEqual (finalText, newText);
                }
+
+               [TestCase(true)]
+               public void IsReadOnlyTest(bool isReadOnly)
+               {
+                       Editor editor = new Editor();
+                       editor.SetValue(InputView.IsReadOnlyProperty, isReadOnly);
+                       Assert.AreEqual(isReadOnly, editor.IsReadOnly);
+               }
+               [Test]
+               public void IsReadOnlyDefaultValueTest()
+               {
+                       Editor editor = new Editor();
+                       Assert.AreEqual(editor.IsReadOnly, false);
+               }
        }
 }
index 906f697..96eaf5e 100644 (file)
@@ -154,5 +154,20 @@ namespace Xamarin.Forms.Core.UnitTests
 
                        Assert.True(result == isEnabled ? true : false);
                }
+
+               [TestCase(true)]
+               public void IsReadOnlyTest(bool isReadOnly)
+               {
+                       Entry entry = new Entry();
+                       entry.SetValue(InputView.IsReadOnlyProperty, isReadOnly);
+                       Assert.AreEqual(isReadOnly, entry.IsReadOnly);
+               }
+
+               [Test]
+               public void IsReadOnlyDefaultValueTest()
+               {
+                       Entry entry = new Entry();
+                       Assert.AreEqual(entry.IsReadOnly, false);
+               }
        }
 }
index bd47c0b..5f4027c 100644 (file)
@@ -151,7 +151,9 @@ namespace Xamarin.Forms.Core.UnitTests
                        new PropertyTestCase<TapGestureRecognizer, int> ("NumberOfTapsRequired", t => t.NumberOfTapsRequired, (t, o) => t.NumberOfTapsRequired = o, () => 1, 3),
                        new PropertyTestCase<TapGestureRecognizer, object> ("CommandParameter", t => t.CommandParameter, (t, o) => t.CommandParameter = o, () => null, "Test"),
                        new PropertyTestCase<TapGestureRecognizer, ICommand> ("Command", t => t.Command, (t, o) => t.Command = o, () => null, new Command(()=>{})),
-                       new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false)
+                       new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false),
+                       new PropertyTestCase<Entry, bool> ("IsReadOnly", v => v.IsReadOnly, (v, o) => v.IsReadOnly = o, () => false, true),
+                       new PropertyTestCase<Editor, bool> ("IsReadOnly", v => v.IsReadOnly, (v, o) => v.IsReadOnly = o, () => false, true)
                };
 #pragma warning restore 0414
 
index acb4532..dc5f094 100644 (file)
@@ -8,6 +8,8 @@ namespace Xamarin.Forms
 
                public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create(nameof(MaxLength), typeof(int), typeof(int), int.MaxValue);
 
+               public static readonly BindableProperty IsReadOnlyProperty = BindableProperty.Create(nameof(IsReadOnly), typeof(bool), typeof(InputView), false);
+
                public int MaxLength
                {
                        get { return (int)GetValue(MaxLengthProperty); }
@@ -29,5 +31,11 @@ namespace Xamarin.Forms
                        get { return (bool)GetValue(IsSpellCheckEnabledProperty); }
                        set { SetValue(IsSpellCheckEnabledProperty, value); }
                }
+
+               public bool IsReadOnly
+               {
+                       get { return (bool)GetValue(IsReadOnlyProperty); }
+                       set { SetValue(IsReadOnlyProperty, value); }
+               }
        }
 }
\ No newline at end of file
index 702a7a1..9ab8f12 100644 (file)
@@ -507,6 +507,8 @@ namespace Xamarin.Forms.CustomAttributes
                        FontAttributes,
                        FontFamily,
                        FontSize,
+                       MaxLength,
+                       IsReadOnly
                }
 
                public enum Entry
@@ -530,6 +532,8 @@ namespace Xamarin.Forms.CustomAttributes
                        TextDisabledColor,
                        PlaceholderDisabledColor,
                        PasswordColor,
+                       MaxLength,
+                       IsReadOnly,
                        IsPasswordNumeric
                }
 
index f72ef69..b119f55 100644 (file)
@@ -90,6 +90,7 @@ namespace Xamarin.Forms.Platform.Android
                        UpdateMaxLength();
                        UpdatePlaceholderColor();
                        UpdatePlaceholderText();
+                       UpdateIsReadOnly();
                }
 
                protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -116,6 +117,8 @@ namespace Xamarin.Forms.Platform.Android
                                UpdatePlaceholderText();
                        else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
                                UpdatePlaceholderColor();
+                       else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
 
                        base.OnElementPropertyChanged(sender, e);
                }
@@ -247,5 +250,14 @@ namespace Xamarin.Forms.Platform.Android
                        if (currentControlText.Length > Element.MaxLength)
                                Control.Text = currentControlText.Substring(0, Element.MaxLength);
                }
+
+               void UpdateIsReadOnly()
+               {
+                       bool isReadOnly = !Element.IsReadOnly;
+
+                       Control.FocusableInTouchMode = isReadOnly;
+                       Control.Focusable = isReadOnly;
+                       Control.SetCursorVisible(isReadOnly);
+               }
        }
 }
\ No newline at end of file
index b081461..0c7db11 100644 (file)
@@ -109,6 +109,7 @@ namespace Xamarin.Forms.Platform.Android
                        UpdateMaxLength();
                        UpdateImeOptions();
                        UpdateReturnType();
+                       UpdateIsReadOnly();
 
                        if (_cursorPositionChangePending || _selectionLengthChangePending)
                                UpdateCursorSelection();
@@ -183,6 +184,8 @@ namespace Xamarin.Forms.Platform.Android
                                UpdateCursorSelection();
                        else if (e.PropertyName == Entry.CursorPositionProperty.PropertyName)
                                UpdateCursorSelection();
+                       else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
 
                        base.OnElementPropertyChanged(sender, e);
                }
@@ -332,7 +335,7 @@ namespace Xamarin.Forms.Platform.Android
                        if (_nativeSelectionIsUpdating || Control == null || Element == null)
                                return;
 
-                       if (Control.RequestFocus())
+                       if (!Element.IsReadOnly && Control.RequestFocus())
                        {
                                try
                                {
@@ -414,5 +417,14 @@ namespace Xamarin.Forms.Platform.Android
                                _nativeSelectionIsUpdating = false;
                        }
                }
+
+               void UpdateIsReadOnly()
+               {
+                       bool isReadOnly = !Element.IsReadOnly;
+
+                       Control.FocusableInTouchMode = isReadOnly;
+                       Control.Focusable = isReadOnly;
+                       Control.SetCursorVisible(isReadOnly);
+               }
        }
-}
+}
\ No newline at end of file
index 45139c0..771c6c9 100644 (file)
@@ -42,6 +42,7 @@ namespace Xamarin.Forms.Platform.MacOS
                        UpdateTextColor();
                        UpdateEditable();
                        UpdateMaxLength();
+                       UpdateIsReadOnly();
                }
 
                protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -62,6 +63,8 @@ namespace Xamarin.Forms.Platform.MacOS
                                UpdateFont();
                        else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
                                UpdateMaxLength();
+                       else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
                }
 
                protected override void SetBackgroundColor(Color color)
@@ -148,5 +151,12 @@ namespace Xamarin.Forms.Platform.MacOS
                        if (currentControlText.Length > Element?.MaxLength)
                                Control.StringValue = currentControlText.Substring(0, Element.MaxLength);
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.Editable = !Element.IsReadOnly;
+                       if (Element.IsReadOnly && Control.Window?.FirstResponder == Control.CurrentEditor)
+                               Control.Window?.MakeFirstResponder(null);
+               }
        }
 }
\ No newline at end of file
index 0b3ab90..31e462c 100644 (file)
@@ -132,6 +132,8 @@ namespace Xamarin.Forms.Platform.MacOS
                                UpdateAlignment();
                        else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
                                UpdateMaxLength();
+                       else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
 
                        base.OnElementPropertyChanged(sender, e);
                }
@@ -201,7 +203,8 @@ namespace Xamarin.Forms.Platform.MacOS
                        UpdateFont();
                        UpdateAlignment();
                        UpdateMaxLength();
-               }
+                       UpdateIsReadOnly();
+        }
 
                void TextFieldFocusChanged(object sender, BoolEventArgs e)
                {
@@ -289,5 +292,13 @@ namespace Xamarin.Forms.Platform.MacOS
                        if (currentControlText.Length > Element?.MaxLength)
                                Control.StringValue = currentControlText.Substring(0, Element.MaxLength);
                }
+
+
+               void UpdateIsReadOnly()
+               {
+                       Control.Editable = !Element.IsReadOnly;
+                       if (Element.IsReadOnly && Control.Window?.FirstResponder == Control.CurrentEditor)
+                               Control.Window?.MakeFirstResponder(null);
+               }
        }
 }
\ No newline at end of file
index 48b160c..dd57006 100644 (file)
@@ -16,6 +16,7 @@ namespace Xamarin.Forms.Platform.Tizen
                        RegisterPropertyHandler(InputView.IsSpellCheckEnabledProperty, UpdateIsSpellCheckEnabled);
                        RegisterPropertyHandler(Editor.PlaceholderProperty, UpdatePlaceholder);
                        RegisterPropertyHandler(Editor.PlaceholderColorProperty, UpdatePlaceholderColor);
+                       RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
                }
 
                protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
@@ -153,5 +154,10 @@ namespace Xamarin.Forms.Platform.Tizen
 
                        return null;
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.IsEditable = !Element.IsReadOnly;
+               }
        }
 }
\ No newline at end of file
index 715844e..ba77015 100644 (file)
@@ -23,6 +23,7 @@ namespace Xamarin.Forms.Platform.Tizen
                        RegisterPropertyHandler(Entry.IsTextPredictionEnabledProperty, UpdateIsSpellCheckEnabled);
                        RegisterPropertyHandler(Specific.FontWeightProperty, UpdateFontWeight);
                        RegisterPropertyHandler(Entry.SelectionLengthProperty, UpdateSelectionLength);
+                       RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
                }
 
                protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
@@ -198,5 +199,10 @@ namespace Xamarin.Forms.Platform.Tizen
 
                        return Element.Text.IndexOf(selection, Math.Max(Control.CursorPosition - selection.Length, 0));
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.IsEditable = !Element.IsReadOnly;
+               }
        }
 }
\ No newline at end of file
index 188ae47..624c15a 100644 (file)
@@ -62,6 +62,7 @@ namespace Xamarin.Forms.Platform.UWP
                                UpdateDetectReadingOrderFromContent();
                                UpdatePlaceholderText();
                                UpdatePlaceholderColor();
+                               UpdateIsReadOnly();
                        }
 
                        base.OnElementChanged(e);
@@ -127,6 +128,8 @@ namespace Xamarin.Forms.Platform.UWP
                                UpdatePlaceholderText();
                        else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
                                UpdatePlaceholderColor();
+                       else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
                }
 
                void OnLostFocus(object sender, RoutedEventArgs e)
@@ -357,5 +360,10 @@ namespace Xamarin.Forms.Platform.UWP
                                }
                        }
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.IsReadOnly = Element.IsReadOnly;
+               }
        }
 }
\ No newline at end of file
index 8c37a37..27cbd46 100644 (file)
@@ -61,6 +61,7 @@ namespace Xamarin.Forms.Platform.UWP
                                UpdateMaxLength();
                                UpdateDetectReadingOrderFromContent();
                                UpdateReturnType();
+                               UpdateIsReadOnly();
                                UpdateInputScope();
 
                                if (_cursorPositionChangePending)
@@ -136,6 +137,8 @@ namespace Xamarin.Forms.Platform.UWP
                                UpdateCursorPosition();
                        else if (e.PropertyName == Entry.SelectionLengthProperty.PropertyName)
                                UpdateSelectionLength();
+                       else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
                }
 
                protected override void UpdateBackgroundColor()
@@ -424,5 +427,10 @@ namespace Xamarin.Forms.Platform.UWP
                                _nativeSelectionIsUpdating = false;
                        }
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.IsReadOnly = Element.IsReadOnly;
+               }
        }
 }
\ No newline at end of file
index 1b6d03b..cbaef0a 100644 (file)
@@ -27,6 +27,7 @@ namespace Xamarin.Forms.Platform.WPF
                                UpdateTextColor();
                                UpdateFont();
                                UpdateMaxLength();
+                               UpdateIsReadOnly();
                        }
 
                        base.OnElementChanged(e);
@@ -51,6 +52,8 @@ namespace Xamarin.Forms.Platform.WPF
                                UpdateFont();
                        else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
                                UpdateMaxLength();
+                       else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
                }
                
                void NativeOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
@@ -138,5 +141,10 @@ namespace Xamarin.Forms.Platform.WPF
                        _isDisposed = true;
                        base.Dispose(disposing);
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.IsReadOnly = Element.IsReadOnly;
+               }
        }
 }
\ No newline at end of file
index c78a431..321740d 100644 (file)
@@ -35,6 +35,7 @@ namespace Xamarin.Forms.Platform.WPF
                                UpdateAlignment();
                                UpdatePlaceholderColor();
                                UpdateMaxLength();
+                               UpdateIsReadOnly();
                        }
 
                        base.OnElementChanged(e);
@@ -66,6 +67,8 @@ namespace Xamarin.Forms.Platform.WPF
                                UpdatePlaceholderColor();
                        else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
                                UpdateMaxLength();
+                       else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
                }
                
                internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
@@ -259,5 +262,10 @@ namespace Xamarin.Forms.Platform.WPF
                        _isDisposed = true;
                        base.Dispose(disposing);
                }
+
+               void UpdateIsReadOnly()
+               {
+                       Control.IsReadOnly = Element.IsReadOnly;
+               }
        }
 }
index 4654329..47d0577 100644 (file)
@@ -79,6 +79,8 @@ namespace Xamarin.Forms.Platform.iOS
                        UpdateTextAlignment();
                        UpdateMaxLength();
                        UpdateAutoSizeOption();
+                       UpdateReadOnly();
+                       UpdateUserInteraction();
                }
 
                private void UpdateAutoSizeOption()
@@ -134,8 +136,8 @@ namespace Xamarin.Forms.Platform.iOS
                                UpdateKeyboard();
                        else if (e.PropertyName == Editor.IsTextPredictionEnabledProperty.PropertyName)
                                UpdateKeyboard();
-                       else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
-                               UpdateEditable();
+                       else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName || e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateUserInteraction();
                        else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
                                UpdateTextColor();
                        else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
@@ -277,6 +279,19 @@ namespace Xamarin.Forms.Platform.iOS
                        return newLength <= Element.MaxLength;
                }
 
+               void UpdateReadOnly()
+               {
+                       Control.UserInteractionEnabled = !Element.IsReadOnly;
+               }
+
+               void UpdateUserInteraction()
+               {
+                       if (Element.IsEnabled && Element.IsReadOnly)
+                               UpdateReadOnly();
+                       else
+                               UpdateEditable();
+               }
+
                internal class FormsUITextView : UITextView
                {
                        public event EventHandler ContentSizeChanged;
index 9db1f4c..e286eeb 100644 (file)
@@ -126,6 +126,7 @@ namespace Xamarin.Forms.Platform.iOS
                                UpdateCursorSelection();
 
                        UpdateCursorColor();
+                       UpdateIsReadOnly();
                }
 
                protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -171,6 +172,8 @@ namespace Xamarin.Forms.Platform.iOS
                                UpdateCursorSelection();
                        else if (e.PropertyName == Specifics.CursorColorProperty.PropertyName)
                                UpdateCursorColor();
+                       else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
+                               UpdateIsReadOnly();
 
                        base.OnElementPropertyChanged(sender, e);
                }
@@ -478,5 +481,10 @@ namespace Xamarin.Forms.Platform.iOS
                                _nativeSelectionIsUpdating = false;
                        }
                }
-       }
+
+        void UpdateIsReadOnly()
+        {
+            Control.UserInteractionEnabled = !Element.IsReadOnly;
+        }
+    }
 }