diff --git a/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs b/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs index 9189e7ca447a..8a96e674a433 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs @@ -255,6 +255,8 @@ void UpdatePickerFromPickerSource(PickerSource? pickerSource) PlatformView.Text = VirtualView.GetItem(pickerSource.SelectedIndex); VirtualView.SelectedIndex = pickerSource.SelectedIndex; + // Re-apply kern: plain Text assignment above clears iOS kern attributes. + PlatformView.UpdateCharacterSpacing(VirtualView); } void UpdatePickerSelectedIndex(UIPickerView? pickerView, int formsIndex) diff --git a/src/Core/src/Platform/iOS/PickerExtensions.cs b/src/Core/src/Platform/iOS/PickerExtensions.cs index c2de04d1fd1c..1b026e0960a0 100644 --- a/src/Core/src/Platform/iOS/PickerExtensions.cs +++ b/src/Core/src/Platform/iOS/PickerExtensions.cs @@ -50,6 +50,8 @@ internal static void UpdatePicker(this MauiPicker platformPicker, IPicker picker platformPicker.UpdatePickerTitle(picker); } + platformPicker.UpdateCharacterSpacing(picker); + var pickerView = platformPicker.UIPickerView; pickerView?.ReloadAllComponents(); diff --git a/src/Core/tests/DeviceTests/Handlers/Picker/PickerHandlerTests.iOS.cs b/src/Core/tests/DeviceTests/Handlers/Picker/PickerHandlerTests.iOS.cs index 16a438c76628..0c6b775ae577 100644 --- a/src/Core/tests/DeviceTests/Handlers/Picker/PickerHandlerTests.iOS.cs +++ b/src/Core/tests/DeviceTests/Handlers/Picker/PickerHandlerTests.iOS.cs @@ -64,6 +64,91 @@ public async Task TextColorInitializesCorrectly() Assert.Equal(expectedValue, values.PlatformViewValue); } + [Theory(DisplayName = "Updating SelectedIndex Does Not Affect CharacterSpacing")] + [InlineData(0, 1)] + [InlineData(1, 0)] + public async Task SelectedIndexDoesNotAffectCharacterSpacing(int initialIndex, int newIndex) + { + var picker = new PickerStub + { + Title = "Select an Item", + Items = new[] { "Apple", "Banana", "Cherry" }, + CharacterSpacing = 4, + SelectedIndex = initialIndex + }; + + await InvokeOnMainThreadAsync(() => + { + var handler = CreateHandler(picker); + handler.UpdateValue(nameof(IPicker.CharacterSpacing)); + + var before = GetNativeCharacterSpacing(handler); + Assert.Equal(4.0, before); + + picker.SelectedIndex = newIndex; + handler.UpdateValue(nameof(IPicker.SelectedIndex)); + + var after = GetNativeCharacterSpacing(handler); + Assert.Equal(4.0, after); + }); + } + + [Theory(DisplayName = "Selecting An Item With Done Keeps CharacterSpacing")] + [InlineData(0, 1)] + [InlineData(1, 0)] + public async Task SelectingItemWithDoneDoesNotAffectCharacterSpacing(int initialIndex, int newIndex) + { + var picker = new PickerStub + { + Title = "Select an Item", + Items = new[] { "Apple", "Banana", "Cherry" }, + CharacterSpacing = 4, + SelectedIndex = initialIndex + }; + + await InvokeOnMainThreadAsync(() => + { + var handler = CreateHandler(picker); + handler.UpdateValue(nameof(IPicker.CharacterSpacing)); + + var before = GetNativeCharacterSpacing(handler); + Assert.Equal(4.0, before); + + var mauiPicker = GetNativePicker(handler); + mauiPicker.BecomeFirstResponder(); + + var pickerView = mauiPicker.UIPickerView; + var model = (PickerSource)pickerView.Model; + pickerView.Select(newIndex, 0, false); + model.Selected(pickerView, newIndex, 0); + TapDoneOnInputAccessoryView(mauiPicker); + + Assert.Equal(picker.Items[newIndex], GetNativeText(handler)); + + var after = GetNativeCharacterSpacing(handler); + Assert.Equal(4.0, after); + }); + } + + void TapDoneOnInputAccessoryView(MauiPicker mauiPicker) + { + var toolbar = mauiPicker.InputAccessoryView as UIToolbar; + Assert.NotNull(toolbar); + Assert.NotNull(toolbar.Items); + Assert.NotEmpty(toolbar.Items); + var doneButton = toolbar.Items[toolbar.Items.Length - 1]; + Assert.NotNull(doneButton); + Assert.NotNull(doneButton.Target); + Assert.NotNull(doneButton.Action); + UIApplication.SharedApplication.SendAction(doneButton.Action, doneButton.Target, doneButton, null); + } + + double GetNativeCharacterSpacing(PickerHandler pickerHandler) + { + var mauiPicker = GetNativePicker(pickerHandler); + return mauiPicker.AttributedText.GetCharacterSpacing(); + } + MauiPicker GetNativePicker(PickerHandler pickerHandler) => pickerHandler.PlatformView;