Entry and Editor RTL fixes (#10046) fixes #9022 fixes #5860 fixes #3359

* Use right alignment instead of natural for RTL Entry on iOS; fixes #9022
Fixes #3359;
Remove DetectFromContent as default alignment for UWP Editor; Fixes #5860

* Fix occasional ReusebindingInstance test failures due to GC

* Remove commented code
This commit is contained in:
E.Z. Hart 2020-04-15 08:23:01 -06:00 коммит произвёл GitHub
Родитель d677324410
Коммит f207a9c88e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 185 добавлений и 33 удалений

Просмотреть файл

@ -194,6 +194,8 @@ namespace Xamarin.Forms.Core.UnitTests
bindable2.BindingContext = new MockViewModel();
Assert.Throws<InvalidOperationException>(() => bindable2.SetBinding(property, binding),
"Binding allowed reapplication with a different context");
GC.KeepAlive(bindable);
}
[Test, Category("[Binding] Set Value")]

Просмотреть файл

@ -7,7 +7,7 @@ using Windows.UI.Xaml.Media;
using Xamarin.Forms.Platform.UWP;
using WColor = Windows.UI.Color;
namespace Xamarin.Forms.Platform.UAP.Tests
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
[TestFixture]
public class BackgroundColorTests : PlatformTestFixture

Просмотреть файл

@ -0,0 +1,104 @@
using System.Threading.Tasks;
using NUnit.Framework;
using WTextAlignment = Windows.UI.Xaml.TextAlignment;
using WFlowDirection = Windows.UI.Xaml.FlowDirection;
using System;
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
public class FlowDirectionTests : PlatformTestFixture
{
[TestCase(true, FlowDirection.LeftToRight, Category = "FlowDirection,Entry", ExpectedResult = WTextAlignment.Left)]
[TestCase(true, FlowDirection.RightToLeft, Category = "FlowDirection,Entry", ExpectedResult = WTextAlignment.Right)]
[TestCase(false, FlowDirection.LeftToRight, Category = "FlowDirection,Entry", ExpectedResult = WTextAlignment.Left)]
[TestCase(false, FlowDirection.RightToLeft, Category = "FlowDirection,Entry", ExpectedResult = WTextAlignment.Right)]
public async Task<WTextAlignment> EntryAlignmentMatchesFlowDirection(bool isExplicit, FlowDirection flowDirection)
{
var entry = new Entry { Text = "Checking flow direction", HorizontalTextAlignment = TextAlignment.Start };
var contentPage = new ContentPage { Title = "Flow Direction", Content = entry };
if (isExplicit)
{
entry.FlowDirection = flowDirection;
}
else
{
contentPage.FlowDirection = flowDirection;
}
var nativeAlignment = await Device.InvokeOnMainThreadAsync(() => {
if (!isExplicit)
{
GetRenderer(contentPage);
}
var textField = GetNativeControl(entry);
return textField.TextAlignment;
});
return nativeAlignment;
}
async Task<Tuple<WTextAlignment, WFlowDirection>> GetEditorAlignmentAndFlowDirection(bool isExplicit, FlowDirection flowDirection)
{
var editor = new Editor { Text = " تسجيل الدخول" };
var contentPage = new ContentPage { Title = "Flow Direction", Content = editor };
if (isExplicit)
{
editor.FlowDirection = flowDirection;
}
else
{
contentPage.FlowDirection = flowDirection;
}
var (nativeAlignment, nativeFlowDirection) = await Device.InvokeOnMainThreadAsync(() => {
if (!isExplicit)
{
GetRenderer(contentPage);
}
var textField = GetNativeControl(editor);
return (textField.TextAlignment, textField.FlowDirection);
});
return new Tuple<WTextAlignment, WFlowDirection>(nativeAlignment, nativeFlowDirection);
}
// The Left TextAlignment seems counterintuitive, but for the Editor the FlowDirection
// is going to automatically handle the alignment anyway.
// The important thing is that the TextAlignment is *not* set to DetectFromContent,
// as that will override our FlowDirection settings if they don't agree
[Test, Category("Editor"), Category("FlowDirection")]
public async Task EditorAlignmentMatchesFlowDirectionRtlExplicit()
{
var results = await GetEditorAlignmentAndFlowDirection(true, FlowDirection.RightToLeft);
Assert.That(results.Item1, Is.EqualTo(WTextAlignment.Left));
Assert.That(results.Item2, Is.EqualTo(WFlowDirection.RightToLeft));
}
[Test, Category("Editor"), Category("FlowDirection")]
public async Task EditorAlignmentMatchesFlowDirectionLtrExplicit()
{
var results = await GetEditorAlignmentAndFlowDirection(true, FlowDirection.LeftToRight);
Assert.That(results.Item1, Is.EqualTo(WTextAlignment.Left));
Assert.That(results.Item2, Is.EqualTo(WFlowDirection.LeftToRight));
}
[Test, Category("Editor"), Category("FlowDirection")]
public async Task EditorAlignmentMatchesFlowDirectionRtlImplicit()
{
var results = await GetEditorAlignmentAndFlowDirection(false, FlowDirection.RightToLeft);
Assert.That(results.Item1, Is.EqualTo(WTextAlignment.Left));
Assert.That(results.Item2, Is.EqualTo(WFlowDirection.RightToLeft));
}
[Test, Category("Editor"), Category("FlowDirection")]
public async Task EditorAlignmentMatchesFlowDirectionLtrImplicit()
{
var results = await GetEditorAlignmentAndFlowDirection(false, FlowDirection.LeftToRight);
Assert.That(results.Item1, Is.EqualTo(WTextAlignment.Left));
Assert.That(results.Item2, Is.EqualTo(WFlowDirection.LeftToRight));
}
}
}

Просмотреть файл

@ -2,7 +2,7 @@
using System.Threading.Tasks;
using NUnit.Framework;
namespace Xamarin.Forms.Platform.UAP.Tests
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
[TestFixture]
public class IsEnabledTests : PlatformTestFixture

Просмотреть файл

@ -5,7 +5,7 @@ using NUnit.Framework;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms.Platform.UWP;
namespace Xamarin.Forms.Platform.UAP.Tests
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
public class PlatformTestFixture
{

Просмотреть файл

@ -1,7 +1,7 @@
using System.Threading.Tasks;
using NUnit.Framework;
namespace Xamarin.Forms.Platform.UAP.Tests
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
[TestFixture]
public class RendererTests : PlatformTestFixture

Просмотреть файл

@ -5,7 +5,7 @@ using NUnit.Framework;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
namespace Xamarin.Forms.Platform.UAP.Tests
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
[TestFixture]
public class RotationTests : PlatformTestFixture

Просмотреть файл

@ -5,7 +5,7 @@ using NUnit.Framework;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
namespace Xamarin.Forms.Platform.UAP.Tests
namespace Xamarin.Forms.Platform.UAP.UnitTests
{
[TestFixture]
public class ScaleTests : PlatformTestFixture

Просмотреть файл

@ -123,6 +123,7 @@
<Compile Include="BackgroundColorTests.cs" />
<Compile Include="ColorTests.cs" />
<Compile Include="EmbeddingTests.cs" />
<Compile Include="FlowDirectionTests.cs" />
<Compile Include="IsEnabledTests.cs" />
<Compile Include="PlatformTestFixture.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

Просмотреть файл

@ -50,6 +50,10 @@ namespace Xamarin.Forms.Platform.UWP
// color stuff, then the underlying textbox should just use the Forms VSM states
textBox.UseFormsVsm = e.NewElement.HasVisualStateGroups()
|| !e.NewElement.OnThisPlatform().GetIsLegacyColorModeEnabled();
// The default is DetectFromContent, which we don't want because it can
// override the FlowDirection settings.
textBox.TextAlignment = Windows.UI.Xaml.TextAlignment.Left;
}
UpdateText();
@ -57,7 +61,6 @@ namespace Xamarin.Forms.Platform.UWP
UpdateTextColor();
UpdateCharacterSpacing();
UpdateFont();
UpdateTextAlignment();
UpdateFlowDirection();
UpdateMaxLength();
UpdateDetectReadingOrderFromContent();
@ -122,7 +125,6 @@ namespace Xamarin.Forms.Platform.UWP
}
else if (e.PropertyName == VisualElement.FlowDirectionProperty.PropertyName)
{
UpdateTextAlignment();
UpdateFlowDirection();
}
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
@ -177,7 +179,6 @@ namespace Xamarin.Forms.Platform.UWP
Element.SetValueCore(Editor.TextProperty, Control.Text);
}
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
FormsTextBox child = Control;
@ -255,6 +256,7 @@ namespace Xamarin.Forms.Platform.UWP
{
Control.CharacterSpacing = Element.CharacterSpacing.ToEm();
}
void UpdateText()
{
string newText = Element.Text ?? "";
@ -268,11 +270,6 @@ namespace Xamarin.Forms.Platform.UWP
Control.SelectionStart = Control.Text.Length;
}
void UpdateTextAlignment()
{
Control.UpdateTextAlignment(Element);
}
void UpdateTextColor()
{
Color textColor = Element.TextColor;

Просмотреть файл

@ -1,8 +1,5 @@
using Windows.UI.Xaml;
using WFlowDirection = Windows.UI.Xaml.FlowDirection;
using WTextAlignment = Windows.UI.Xaml.TextAlignment;
using Windows.UI.Xaml.Controls;
namespace Xamarin.Forms.Platform.UWP
{
@ -12,22 +9,11 @@ namespace Xamarin.Forms.Platform.UWP
{
if (controller == null || control == null)
return;
if (controller.EffectiveFlowDirection.IsRightToLeft())
control.FlowDirection = WFlowDirection.RightToLeft;
else if (controller.EffectiveFlowDirection.IsLeftToRight())
control.FlowDirection = WFlowDirection.LeftToRight;
}
internal static void UpdateTextAlignment(this TextBox control, IVisualElementController controller)
{
if (controller == null || control == null)
return;
if (controller.EffectiveFlowDirection.IsRightToLeft())
control.TextAlignment = WTextAlignment.Right;
else if (controller.EffectiveFlowDirection.IsLeftToRight())
control.TextAlignment = WTextAlignment.Left;
}
}
}

Просмотреть файл

@ -1,12 +1,13 @@
using NUnit.Framework;
using System.Threading.Tasks;
using NUnit.Framework;
using UIKit;
namespace Xamarin.Forms.Platform.iOS.UnitTests
{
[TestFixture]
public class FlowDirectionTests
public class FlowDirectionTests : PlatformTestFixture
{
[Test]
[Test, Category("FlowDirection")]
public void FlowDirectionConversion()
{
var ltr = UIUserInterfaceLayoutDirection.LeftToRight.ToFlowDirection();
@ -15,5 +16,65 @@ namespace Xamarin.Forms.Platform.iOS.UnitTests
var rtl = UIUserInterfaceLayoutDirection.RightToLeft.ToFlowDirection();
Assert.That(rtl, Is.EqualTo(FlowDirection.RightToLeft));
}
[TestCase(true, FlowDirection.LeftToRight, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Left)]
[TestCase(true, FlowDirection.RightToLeft, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Right)]
[TestCase(false, FlowDirection.LeftToRight, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Left)]
[TestCase(false, FlowDirection.RightToLeft, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Right)]
public async Task<UITextAlignment> EntryAlignmentMatchesFlowDirection(bool isExplicit, FlowDirection flowDirection)
{
var entry = new Entry { Text = "Checking flow direction", HorizontalTextAlignment = TextAlignment.Start };
var contentPage = new ContentPage { Title = "Flow Direction", Content = entry };
if (isExplicit)
{
entry.FlowDirection = flowDirection;
}
else
{
contentPage.FlowDirection = flowDirection;
}
var nativeAlignment = await Device.InvokeOnMainThreadAsync(() => {
if (!isExplicit)
{
GetRenderer(contentPage);
}
var textField = GetNativeControl(entry);
return textField.TextAlignment;
});
return nativeAlignment;
}
[TestCase(true, FlowDirection.LeftToRight, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Left)]
[TestCase(true, FlowDirection.RightToLeft, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Right)]
[TestCase(false, FlowDirection.LeftToRight, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Left)]
[TestCase(false, FlowDirection.RightToLeft, Category = "FlowDirection,Entry", ExpectedResult = UITextAlignment.Right)]
public async Task<UITextAlignment> EditorAlignmentMatchesFlowDirection(bool isExplicit, FlowDirection flowDirection)
{
var editor = new Editor { Text = "Checking flow direction" };
var contentPage = new ContentPage { Title = "Flow Direction", Content = editor };
if (isExplicit)
{
editor.FlowDirection = flowDirection;
}
else
{
contentPage.FlowDirection = flowDirection;
}
var nativeAlignment = await Device.InvokeOnMainThreadAsync(() => {
if (!isExplicit)
{
GetRenderer(contentPage);
}
var textField = GetNativeControl(editor);
return textField.TextAlignment;
});
return nativeAlignment;
}
}
}

Просмотреть файл

@ -21,7 +21,7 @@ namespace Xamarin.Forms.Platform.iOS
if (isLtr)
return UITextAlignment.Left;
else
return UITextAlignment.Natural;
return UITextAlignment.Right;
}
}

Просмотреть файл

@ -355,6 +355,7 @@ namespace Xamarin.Forms.Platform.iOS
UpdateAttributedPlaceholder(Control.AttributedPlaceholder.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing));
}
protected virtual void UpdateAttributedPlaceholder(NSAttributedString nsAttributedString) =>
Control.AttributedPlaceholder = nsAttributedString;