Merge main into net9.0 (#24385)
### Description of Change Merge main into net9.0
|
@ -209,6 +209,26 @@ Task("dotnet-samples")
|
|||
RunMSBuildWithDotNet(projectsToBuild, properties, binlogPrefix: "sample-");
|
||||
});
|
||||
|
||||
// Builds the host app for the UI Tests
|
||||
Task("uitests-apphost")
|
||||
.IsDependentOn("dotnet-buildtasks")
|
||||
.Does(() =>
|
||||
{
|
||||
var tempDir = PrepareSeparateBuildContext("samplesTest");
|
||||
|
||||
var properties = new Dictionary<string, string>();
|
||||
|
||||
if(useNuget)
|
||||
{
|
||||
properties = new Dictionary<string, string> {
|
||||
["UseWorkload"] = "true",
|
||||
// ["GenerateAppxPackageOnBuild"] = "true",
|
||||
["RestoreConfigFile"] = tempDir.CombineWithFilePath("NuGet.config").FullPath,
|
||||
};
|
||||
}
|
||||
RunMSBuildWithDotNet("./src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj", properties, binlogPrefix: "uitests-apphost-");
|
||||
});
|
||||
|
||||
Task("dotnet-legacy-controlgallery")
|
||||
.IsDependentOn("dotnet-legacy-controlgallery-android")
|
||||
.IsDependentOn("dotnet-legacy-controlgallery-ios");
|
||||
|
|
|
@ -49,7 +49,7 @@ steps:
|
|||
- pwsh: echo "##vso[task.prependpath]$(DotNet.Dir)"
|
||||
displayName: 'Add .NET to PATH'
|
||||
|
||||
- pwsh: ./build.ps1 --target=dotnet-samples --configuration="${{ parameters.configuration }}" --${{ parameters.platform }} --verbosity=diagnostic --usenuget=false --runtimevariant="${{ parameters.runtimeVariant }}"
|
||||
- pwsh: ./build.ps1 --target=uitests-apphost --configuration="${{ parameters.configuration }}" --${{ parameters.platform }} --verbosity=diagnostic --usenuget=false --runtimevariant="${{ parameters.runtimeVariant }}"
|
||||
displayName: 'Build the samples'
|
||||
|
||||
- bash: |
|
||||
|
|
|
@ -998,23 +998,35 @@ namespace Microsoft.Maui.Controls.Build.Tasks
|
|||
// IL_008e: newobj instance void class [mscorlib]System.Tuple`2<class [mscorlib]System.Func`2<class ViewModel, object>, string>::'.ctor'(!0, !1)
|
||||
// IL_0093: stelem.ref
|
||||
|
||||
yield return Create(Ldc_I4, properties.Count);
|
||||
yield return Create(Newarr, tupleRef);
|
||||
|
||||
for (var i = 0; i < properties.Count; i++)
|
||||
var handlers = new List<(MethodDefinition PartGetter, string PropertyName)>();
|
||||
for (int i = 0; i < properties.Count; i++)
|
||||
{
|
||||
if (properties[i].property == null)
|
||||
continue;
|
||||
|
||||
var partGetter = partGetters[i];
|
||||
var propertyName = properties[i].Item1.Name;
|
||||
|
||||
handlers.Add((partGetter, propertyName));
|
||||
|
||||
// for indexers add also a handler for the specific index
|
||||
if (properties[i].Item3 is not null)
|
||||
{
|
||||
handlers.Add((partGetter, $"{propertyName}[{properties[i].Item3}]"));
|
||||
}
|
||||
}
|
||||
|
||||
yield return Create(Ldc_I4, handlers.Count);
|
||||
yield return Create(Newarr, tupleRef);
|
||||
|
||||
for (var i = 0; i < handlers.Count; i++)
|
||||
{
|
||||
yield return Create(Dup);
|
||||
yield return Create(Ldc_I4, i);
|
||||
yield return Create(Ldnull);
|
||||
yield return Create(Ldftn, partGetters[i]);
|
||||
yield return Create(Ldftn, handlers[i].PartGetter);
|
||||
yield return Create(Newobj, module.ImportReference(funcCtor));
|
||||
if (properties[i].Item3 == null) //no indexer
|
||||
yield return Create(Ldstr, properties[i].Item1.Name);
|
||||
else
|
||||
yield return Create(Ldstr, $"{properties[i].Item1.Name}[{properties[i].Item3}]");
|
||||
|
||||
yield return Create(Ldstr, handlers[i].PropertyName);
|
||||
yield return Create(Newobj, module.ImportReference(tupleCtor));
|
||||
yield return Create(Stelem_Ref);
|
||||
}
|
||||
|
|
|
@ -428,29 +428,34 @@ namespace Microsoft.Maui.Controls.Handlers.Items
|
|||
var item = args.Item;
|
||||
if (args.Mode == ScrollToMode.Position)
|
||||
{
|
||||
item = FindBoundItem(args);
|
||||
// Do not use `IGroupableItemsViewSource` since `UngroupedItemsSource` also implements that interface
|
||||
if (ItemsViewAdapter.ItemsSource is UngroupedItemsSource)
|
||||
{
|
||||
return args.Index;
|
||||
}
|
||||
else if (ItemsViewAdapter.ItemsSource is IGroupableItemsViewSource groupItemSource)
|
||||
{
|
||||
item = FindBoundItemInGroup(args, groupItemSource);
|
||||
}
|
||||
}
|
||||
|
||||
return ItemsViewAdapter.GetPositionForItem(item);
|
||||
}
|
||||
|
||||
private object FindBoundItem(ScrollToRequestEventArgs args)
|
||||
private static object FindBoundItemInGroup(ScrollToRequestEventArgs args, IGroupableItemsViewSource groupItemSource)
|
||||
{
|
||||
if (args.Index >= ItemsViewAdapter.ItemsSource.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ItemsViewAdapter.ItemsSource is IGroupableItemsViewSource groupItemSource &&
|
||||
args.GroupIndex >= 0 &&
|
||||
if (args.GroupIndex >= 0 &&
|
||||
args.GroupIndex < groupItemSource.Count)
|
||||
{
|
||||
var group = groupItemSource.GetGroupItemsViewSource(args.GroupIndex);
|
||||
|
||||
// NOTE: GetItem calls AdjustIndexRequest, which subtracts 1 if we have a header
|
||||
return group.GetItem(args.Index + 1);
|
||||
if (group is not null)
|
||||
{
|
||||
// GetItem calls AdjustIndexRequest, which subtracts 1 if we have a header (UngroupedItemsSource does not do this)
|
||||
return group.GetItem(args.Index + 1);
|
||||
}
|
||||
}
|
||||
return ItemsViewAdapter.ItemsSource.GetItem(args.Index);
|
||||
return groupItemSource.GetItem(args.Index);
|
||||
}
|
||||
|
||||
protected virtual void UpdateItemSpacing()
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace Microsoft.Maui.Controls.Platform
|
|||
Foreground = textColor?.ToPlatform(),
|
||||
};
|
||||
|
||||
run.Foreground = textColor?.ToPlatform();
|
||||
textBlock.TextHighlighters.Add(textHighlighter);
|
||||
}
|
||||
|
||||
|
|
|
@ -172,6 +172,65 @@ namespace Microsoft.Maui.DeviceTests
|
|||
#if IOS || MACCATALYST || WINDOWS
|
||||
Skip = "Fails: https://github.com/dotnet/maui/issues/17664"
|
||||
#endif
|
||||
)]
|
||||
public async Task CollectionScrollToUngroupedWorks()
|
||||
{
|
||||
SetupBuilder();
|
||||
|
||||
var dataList = new List<TestData>();
|
||||
string letters = "abcdefghijklmnopqrstuvwxyz";
|
||||
for (int i = 0; i < letters.Length; i++)
|
||||
{
|
||||
dataList.Add(new TestData
|
||||
{
|
||||
Name = $"{letters[i]}"
|
||||
});
|
||||
}
|
||||
|
||||
var collectionView = new CollectionView
|
||||
{
|
||||
IsGrouped = false,
|
||||
ItemsSource = dataList,
|
||||
ItemTemplate = new DataTemplate(() =>
|
||||
{
|
||||
var name = new Label()
|
||||
{
|
||||
TextColor = Colors.Grey,
|
||||
HeightRequest = 64
|
||||
};
|
||||
name.SetBinding(Label.TextProperty, "Name");
|
||||
return name;
|
||||
})
|
||||
};
|
||||
|
||||
await CreateHandlerAndAddToWindow<CollectionViewHandler>(collectionView, async handler =>
|
||||
{
|
||||
collectionView.ScrollTo(index: 24, animate: false); // Item "x"
|
||||
|
||||
int retryCount = 3;
|
||||
bool foundItem = false;
|
||||
while (retryCount > 0 && !foundItem)
|
||||
{
|
||||
retryCount--;
|
||||
await Task.Delay(500);
|
||||
for (int i = 0; i < collectionView.LogicalChildrenInternal.Count; i++)
|
||||
{
|
||||
var item = collectionView.LogicalChildrenInternal[i];
|
||||
if (item is Label label && label.Text.Equals("x", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foundItem = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.True(foundItem);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact(
|
||||
#if IOS || MACCATALYST
|
||||
Skip = "Fails on iOS/macOS: https://github.com/dotnet/maui/issues/17664"
|
||||
#endif
|
||||
)]
|
||||
public async Task CollectionScrollToGroupWorks()
|
||||
{
|
||||
|
|
Двоичные данные
src/Controls/tests/TestCases.Android.Tests/snapshots/android/LabelHyperlinkUnderlineColor.png
Normal file
После Ширина: | Высота: | Размер: 8.9 KiB |
Двоичные данные
src/Controls/tests/TestCases.Android.Tests/snapshots/android/SettingDatePickerBackgroundFromHandler.png
Normal file
После Ширина: | Высота: | Размер: 40 KiB |
Двоичные данные
src/Controls/tests/TestCases.Android.Tests/snapshots/android/SettingEditorBackgroundFromHandler.png
Normal file
После Ширина: | Высота: | Размер: 15 KiB |
Двоичные данные
src/Controls/tests/TestCases.Android.Tests/snapshots/android/SettingEntryBackgroundFromHandler.png
Normal file
После Ширина: | Высота: | Размер: 16 KiB |
Двоичные данные
src/Controls/tests/TestCases.Android.Tests/snapshots/android/SettingTimePickerBackgroundFromHandler.png
Normal file
После Ширина: | Высота: | Размер: 40 KiB |
|
@ -0,0 +1,24 @@
|
|||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace Maui.Controls.Sample.Issues
|
||||
{
|
||||
[Issue(IssueTracker.Github, 10645, "Image is not centered in AspectFill mode", PlatformAffected.UWP)]
|
||||
public class Issue10645 : TestContentPage
|
||||
{
|
||||
protected override void Init()
|
||||
{
|
||||
Content =
|
||||
new Grid()
|
||||
{
|
||||
new Image()
|
||||
{
|
||||
AutomationId = "AspectFillImage",
|
||||
Aspect = Microsoft.Maui.Aspect.AspectFill,
|
||||
WidthRequest = 100,
|
||||
HeightRequest = 200,
|
||||
Source = "dotnet_bot.png",
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Maui.Controls.Sample.Issues.Issue18720"
|
||||
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="HeightRequest" Value="36" />
|
||||
<Setter Property="FontSize" Value="9" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<VerticalStackLayout
|
||||
Padding="30,0"
|
||||
Spacing="25">
|
||||
<VerticalStackLayout
|
||||
x:Name="TestLayout">
|
||||
<Label
|
||||
Text="BackgroundColor" />
|
||||
<Entry
|
||||
x:Name="BackgroundColorEntry"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundColorButton"
|
||||
Text="Update Background Color"
|
||||
Clicked="OnUpdateBackgroundColorButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundColorButton"
|
||||
Text="Clear Background Color"
|
||||
Clicked="OnClearBackgroundColorButtonClicked"/>
|
||||
<Label
|
||||
Text="Background" />
|
||||
<Entry
|
||||
x:Name="BackgroundEntry"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundButton"
|
||||
Text="Update Background"
|
||||
Clicked="OnUpdateBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundButton"
|
||||
Text="Clear Background"
|
||||
Clicked="OnClearBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="TestButton"
|
||||
AutomationId="TestButton"
|
||||
Text="Test"
|
||||
Margin="0, 12"
|
||||
Clicked="OnTestButtonClicked"/>
|
||||
</VerticalStackLayout>
|
||||
<Label
|
||||
Text="Custom Entry (Null Android Background)" />
|
||||
<controls:Issue18720Entry1
|
||||
AutomationId="CustomEntry1"/>
|
||||
<Label
|
||||
Text="Custom Entry (Custom Android Drawable)" />
|
||||
<controls:Issue18720Entry2
|
||||
AutomationId="CustomEntry2"/>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
|
@ -0,0 +1,117 @@
|
|||
using System;
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Controls.Xaml;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Hosting;
|
||||
|
||||
namespace Maui.Controls.Sample.Issues
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
[Issue(IssueTracker.Github, 18720, "Setting the background property of AppCompatEditText (Entry) in a handler mapping does not work", PlatformAffected.Android)]
|
||||
public partial class Issue18720 : ContentPage
|
||||
{
|
||||
public Issue18720()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateEntryBackgroundColor();
|
||||
UpdateEntryBackground();
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundColorButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
UpdateEntryBackgroundColor();
|
||||
}
|
||||
|
||||
void OnClearBackgroundColorButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
BackgroundColorEntry.BackgroundColor = null;
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
UpdateEntryBackground();
|
||||
}
|
||||
|
||||
void OnClearBackgroundButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
BackgroundEntry.Background = null;
|
||||
}
|
||||
|
||||
void OnTestButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
TestLayout.IsVisible = false;
|
||||
}
|
||||
|
||||
void UpdateEntryBackgroundColor()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color backgroundColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
BackgroundColorEntry.BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
void UpdateEntryBackground()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color startColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
Color endColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
|
||||
BackgroundEntry.Background = new LinearGradientBrush
|
||||
{
|
||||
EndPoint = new Point(1, 0),
|
||||
GradientStops = new GradientStopCollection
|
||||
{
|
||||
new GradientStop { Color = startColor },
|
||||
new GradientStop { Color = endColor, Offset = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue18720Entry1 : Entry
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Issue18720Entry2 : Entry
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class Issue18720Extensions
|
||||
{
|
||||
public static MauiAppBuilder Issue18720AddMappers(this MauiAppBuilder builder)
|
||||
{
|
||||
builder.ConfigureMauiHandlers(handlers =>
|
||||
{
|
||||
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(Issue18720Entry1), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720Entry1)
|
||||
{
|
||||
#if ANDROID
|
||||
handler.PlatformView.Background = null;
|
||||
handler.PlatformView.SetBackgroundColor(Android.Graphics.Color.Pink);
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.WhiteSmoke);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
Microsoft.Maui.Handlers.EntryHandler.Mapper.AppendToMapping(nameof(Issue18720Entry2), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720Entry2)
|
||||
{
|
||||
#if ANDROID
|
||||
Android.Graphics.Drawables.GradientDrawable gd = new Android.Graphics.Drawables.GradientDrawable();
|
||||
gd.SetCornerRadius(10);
|
||||
gd.SetStroke(2, Android.Graphics.Color.Violet);
|
||||
handler.PlatformView.Background = gd;
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.DeepPink);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Maui.Controls.Sample.Issues.Issue18720DatePicker"
|
||||
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="HeightRequest" Value="36" />
|
||||
<Setter Property="FontSize" Value="9" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<VerticalStackLayout
|
||||
Padding="30,0"
|
||||
Spacing="25">
|
||||
<VerticalStackLayout
|
||||
x:Name="TestLayout">
|
||||
<Label
|
||||
Text="BackgroundColor" />
|
||||
<DatePicker
|
||||
x:Name="BackgroundColorDatePicker"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundColorButton"
|
||||
Text="Update Background Color"
|
||||
Clicked="OnUpdateBackgroundColorButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundColorButton"
|
||||
Text="Clear Background Color"
|
||||
Clicked="OnClearBackgroundColorButtonClicked"/>
|
||||
<Label
|
||||
Text="Background" />
|
||||
<DatePicker
|
||||
x:Name="BackgroundDatePicker"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundButton"
|
||||
Text="Update Background"
|
||||
Clicked="OnUpdateBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundButton"
|
||||
Text="Clear Background"
|
||||
Clicked="OnClearBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="TestButton"
|
||||
AutomationId="TestButton"
|
||||
Text="Test"
|
||||
Margin="0, 12"
|
||||
Clicked="OnTestButtonClicked"/>
|
||||
</VerticalStackLayout>
|
||||
<Label
|
||||
Text="Custom DatePicker (Null Android Background)" />
|
||||
<controls:Issue18720DatePicker1
|
||||
AutomationId="CustomDatePicker1"/>
|
||||
<Label
|
||||
Text="Custom DatePicker (Custom Android Drawable)" />
|
||||
<controls:Issue18720DatePicker2
|
||||
AutomationId="CustomDatePicker2"/>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
|
@ -0,0 +1,117 @@
|
|||
using System;
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Controls.Xaml;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Hosting;
|
||||
|
||||
namespace Maui.Controls.Sample.Issues
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
[Issue(IssueTracker.ManualTest, "18720 DatePicker", "Setting the background property of AppCompatEditText (DatePicker) in a handler mapping does not work", PlatformAffected.Android)]
|
||||
public partial class Issue18720DatePicker : ContentPage
|
||||
{
|
||||
public Issue18720DatePicker()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateDatePickerBackgroundColor();
|
||||
UpdateDatePickerBackground();
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundColorButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
UpdateDatePickerBackgroundColor();
|
||||
}
|
||||
|
||||
void OnClearBackgroundColorButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
BackgroundColorDatePicker.BackgroundColor = null;
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
UpdateDatePickerBackground();
|
||||
}
|
||||
|
||||
void OnClearBackgroundButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
BackgroundDatePicker.Background = null;
|
||||
}
|
||||
|
||||
void OnTestButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
TestLayout.IsVisible = false;
|
||||
}
|
||||
|
||||
void UpdateDatePickerBackgroundColor()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color backgroundColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
BackgroundColorDatePicker.BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
void UpdateDatePickerBackground()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color startColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
Color endColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
|
||||
BackgroundDatePicker.Background = new LinearGradientBrush
|
||||
{
|
||||
EndPoint = new Point(1, 0),
|
||||
GradientStops = new GradientStopCollection
|
||||
{
|
||||
new GradientStop { Color = startColor },
|
||||
new GradientStop { Color = endColor, Offset = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue18720DatePicker1 : DatePicker
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Issue18720DatePicker2 : DatePicker
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class Issue18720DatePickerExtensions
|
||||
{
|
||||
public static MauiAppBuilder Issue18720DatePickerAddMappers(this MauiAppBuilder builder)
|
||||
{
|
||||
builder.ConfigureMauiHandlers(handlers =>
|
||||
{
|
||||
Microsoft.Maui.Handlers.DatePickerHandler.Mapper.AppendToMapping(nameof(Issue18720DatePicker1), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720DatePicker1)
|
||||
{
|
||||
#if ANDROID
|
||||
handler.PlatformView.Background = null;
|
||||
handler.PlatformView.SetBackgroundColor(Android.Graphics.Color.Pink);
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.WhiteSmoke);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
Microsoft.Maui.Handlers.DatePickerHandler.Mapper.AppendToMapping(nameof(Issue18720DatePicker2), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720DatePicker2)
|
||||
{
|
||||
#if ANDROID
|
||||
Android.Graphics.Drawables.GradientDrawable gd = new Android.Graphics.Drawables.GradientDrawable();
|
||||
gd.SetCornerRadius(10);
|
||||
gd.SetStroke(2, Android.Graphics.Color.Violet);
|
||||
handler.PlatformView.Background = gd;
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.DeepPink);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Maui.Controls.Sample.Issues.Issue18720Editor"
|
||||
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="HeightRequest" Value="36" />
|
||||
<Setter Property="FontSize" Value="9" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<VerticalStackLayout
|
||||
Padding="30,0"
|
||||
Spacing="25">
|
||||
<VerticalStackLayout
|
||||
x:Name="TestLayout">
|
||||
<Label
|
||||
Text="BackgroundColor" />
|
||||
<Editor
|
||||
x:Name="BackgroundColorEditor"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundColorButton"
|
||||
Text="Update Background Color"
|
||||
Clicked="OnUpdateBackgroundColorButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundColorButton"
|
||||
Text="Clear Background Color"
|
||||
Clicked="OnClearBackgroundColorButtonClicked"/>
|
||||
<Label
|
||||
Text="Background" />
|
||||
<Editor
|
||||
x:Name="BackgroundEditor"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundButton"
|
||||
Text="Update Background"
|
||||
Clicked="OnUpdateBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundButton"
|
||||
Text="Clear Background"
|
||||
Clicked="OnClearBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="TestButton"
|
||||
AutomationId="TestButton"
|
||||
Text="Test"
|
||||
Margin="0, 12"
|
||||
Clicked="OnTestButtonClicked"/>
|
||||
</VerticalStackLayout>
|
||||
<Label
|
||||
Text="Custom Editor (Null Android Background)" />
|
||||
<controls:Issue18720Editor1
|
||||
AutomationId="CustomEditor1"/>
|
||||
<Label
|
||||
Text="Custom Editor (Custom Android Drawable)" />
|
||||
<controls:Issue18720Editor2
|
||||
AutomationId="CustomEditor2"/>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
|
@ -0,0 +1,117 @@
|
|||
using System;
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Controls.Xaml;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Hosting;
|
||||
|
||||
namespace Maui.Controls.Sample.Issues
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
[Issue(IssueTracker.Github, "18720 Editor", "Setting the background property of AppCompatEditText (Editor) in a handler mapping does not work", PlatformAffected.Android)]
|
||||
public partial class Issue18720Editor : ContentPage
|
||||
{
|
||||
public Issue18720Editor()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateEditorBackgroundColor();
|
||||
UpdateEditorBackground();
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundColorButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
UpdateEditorBackgroundColor();
|
||||
}
|
||||
|
||||
void OnClearBackgroundColorButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
BackgroundColorEditor.BackgroundColor = null;
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
UpdateEditorBackground();
|
||||
}
|
||||
|
||||
void OnClearBackgroundButtonClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
BackgroundEditor.Background = null;
|
||||
}
|
||||
|
||||
void OnTestButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
TestLayout.IsVisible = false;
|
||||
}
|
||||
|
||||
void UpdateEditorBackgroundColor()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color backgroundColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
BackgroundColorEditor.BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
void UpdateEditorBackground()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color startColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
Color endColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
|
||||
BackgroundEditor.Background = new LinearGradientBrush
|
||||
{
|
||||
EndPoint = new Point(1, 0),
|
||||
GradientStops = new GradientStopCollection
|
||||
{
|
||||
new GradientStop { Color = startColor },
|
||||
new GradientStop { Color = endColor, Offset = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue18720Editor1 : Editor
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Issue18720Editor2 : Editor
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class Issue18720EditorExtensions
|
||||
{
|
||||
public static MauiAppBuilder Issue18720EditorAddMappers(this MauiAppBuilder builder)
|
||||
{
|
||||
builder.ConfigureMauiHandlers(handlers =>
|
||||
{
|
||||
Microsoft.Maui.Handlers.EditorHandler.Mapper.AppendToMapping(nameof(Issue18720Editor1), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720Editor1)
|
||||
{
|
||||
#if ANDROID
|
||||
handler.PlatformView.Background = null;
|
||||
handler.PlatformView.SetBackgroundColor(Android.Graphics.Color.Pink);
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.WhiteSmoke);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
Microsoft.Maui.Handlers.EditorHandler.Mapper.AppendToMapping(nameof(Issue18720Editor2), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720Editor2)
|
||||
{
|
||||
#if ANDROID
|
||||
Android.Graphics.Drawables.GradientDrawable gd = new Android.Graphics.Drawables.GradientDrawable();
|
||||
gd.SetCornerRadius(10);
|
||||
gd.SetStroke(2, Android.Graphics.Color.Violet);
|
||||
handler.PlatformView.Background = gd;
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.DeepPink);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Maui.Controls.Sample.Issues.Issue18720TimePicker"
|
||||
xmlns:controls="clr-namespace:Maui.Controls.Sample.Issues">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="HeightRequest" Value="36" />
|
||||
<Setter Property="FontSize" Value="9" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<VerticalStackLayout
|
||||
Padding="30,0"
|
||||
Spacing="25">
|
||||
<VerticalStackLayout
|
||||
x:Name="TestLayout">
|
||||
<Label
|
||||
Text="BackgroundColor" />
|
||||
<TimePicker
|
||||
x:Name="BackgroundColorTimePicker"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundColorButton"
|
||||
Text="Update Background Color"
|
||||
Clicked="OnUpdateBackgroundColorButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundColorButton"
|
||||
Text="Clear Background Color"
|
||||
Clicked="OnClearBackgroundColorButtonClicked"/>
|
||||
<Label
|
||||
Text="Background" />
|
||||
<TimePicker
|
||||
x:Name="BackgroundTimePicker"/>
|
||||
<Button
|
||||
x:Name="UpdateBackgroundButton"
|
||||
Text="Update Background"
|
||||
Clicked="OnUpdateBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="ClearBackgroundButton"
|
||||
Text="Clear Background"
|
||||
Clicked="OnClearBackgroundButtonClicked"/>
|
||||
<Button
|
||||
x:Name="TestButton"
|
||||
AutomationId="TestButton"
|
||||
Text="Test"
|
||||
Margin="0, 12"
|
||||
Clicked="OnTestButtonClicked"/>
|
||||
</VerticalStackLayout>
|
||||
<Label
|
||||
Text="Custom TimePicker (Null Android Background)" />
|
||||
<controls:Issue18720TimePicker1
|
||||
AutomationId="CustomTimePicker1"/>
|
||||
<Label
|
||||
Text="Custom TimePicker (Custom Android Drawable)" />
|
||||
<controls:Issue18720TimePicker2
|
||||
AutomationId="CustomTimePicker2"/>
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
|
@ -0,0 +1,117 @@
|
|||
using System;
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Controls.Xaml;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Hosting;
|
||||
|
||||
namespace Maui.Controls.Sample.Issues
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
[Issue(IssueTracker.ManualTest, "18720 TimePicker", "Setting the background property of AppCompatEditText (TimePicker) in a handler mapping does not work", PlatformAffected.Android)]
|
||||
public partial class Issue18720TimePicker : ContentPage
|
||||
{
|
||||
public Issue18720TimePicker()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateTimePickerBackgroundColor();
|
||||
UpdateTimePickerBackground();
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundColorButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
UpdateTimePickerBackgroundColor();
|
||||
}
|
||||
|
||||
void OnClearBackgroundColorButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
BackgroundColorTimePicker.BackgroundColor = null;
|
||||
}
|
||||
|
||||
void OnUpdateBackgroundButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
UpdateTimePickerBackground();
|
||||
}
|
||||
|
||||
void OnClearBackgroundButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
BackgroundTimePicker.Background = null;
|
||||
}
|
||||
|
||||
void OnTestButtonClicked(object sender, EventArgs e)
|
||||
{
|
||||
TestLayout.IsVisible = false;
|
||||
}
|
||||
|
||||
void UpdateTimePickerBackgroundColor()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color backgroundColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
BackgroundColorTimePicker.BackgroundColor = backgroundColor;
|
||||
}
|
||||
|
||||
void UpdateTimePickerBackground()
|
||||
{
|
||||
Random rnd = new Random();
|
||||
Color startColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
Color endColor = Color.FromRgba(rnd.Next(256), rnd.Next(256), rnd.Next(256), 255);
|
||||
|
||||
BackgroundTimePicker.Background = new LinearGradientBrush
|
||||
{
|
||||
EndPoint = new Point(1, 0),
|
||||
GradientStops = new GradientStopCollection
|
||||
{
|
||||
new GradientStop { Color = startColor },
|
||||
new GradientStop { Color = endColor, Offset = 1 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Issue18720TimePicker1 : TimePicker
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class Issue18720TimePicker2 : TimePicker
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static class Issue18720TimePickerExtensions
|
||||
{
|
||||
public static MauiAppBuilder Issue18720TimePickerAddMappers(this MauiAppBuilder builder)
|
||||
{
|
||||
builder.ConfigureMauiHandlers(handlers =>
|
||||
{
|
||||
Microsoft.Maui.Handlers.TimePickerHandler.Mapper.AppendToMapping(nameof(Issue18720TimePicker1), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720TimePicker1)
|
||||
{
|
||||
#if ANDROID
|
||||
handler.PlatformView.Background = null;
|
||||
handler.PlatformView.SetBackgroundColor(Android.Graphics.Color.Pink);
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.WhiteSmoke);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
Microsoft.Maui.Handlers.TimePickerHandler.Mapper.AppendToMapping(nameof(Issue18720TimePicker2), (handler, view) =>
|
||||
{
|
||||
if (view is Issue18720TimePicker2)
|
||||
{
|
||||
#if ANDROID
|
||||
Android.Graphics.Drawables.GradientDrawable gd = new Android.Graphics.Drawables.GradientDrawable();
|
||||
gd.SetCornerRadius(10);
|
||||
gd.SetStroke(2, Android.Graphics.Color.Violet);
|
||||
handler.PlatformView.Background = gd;
|
||||
handler.PlatformView.SetTextColor(Android.Graphics.Color.DeepPink);
|
||||
#endif
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="Maui.Controls.Sample.Issues.Issue23488">
|
||||
|
||||
<StackLayout HorizontalOptions="Center"
|
||||
VerticalOptions="Center">
|
||||
<Label Text="hyperlink"
|
||||
TextColor="Blue"
|
||||
TextDecorations="Underline" />
|
||||
<Label AutomationId="WaitForLabelControl">
|
||||
<Label.FormattedText>
|
||||
<FormattedString>
|
||||
<Span Text="hyperlink"
|
||||
TextColor="Blue"
|
||||
TextDecorations="Underline" />
|
||||
</FormattedString>
|
||||
</Label.FormattedText>
|
||||
</Label>
|
||||
</StackLayout>
|
||||
|
||||
</ContentPage>
|
|
@ -0,0 +1,12 @@
|
|||
namespace Maui.Controls.Sample.Issues
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
[Issue(IssueTracker.Github, 23488, "Span text-decoration is incorrect whereas the Label behaves properly", PlatformAffected.UWP)]
|
||||
public partial class Issue23488 : ContentPage
|
||||
{
|
||||
public Issue23488()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using Maui.Controls.Sample.Issues;
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Controls;
|
||||
|
@ -23,7 +23,11 @@ namespace Maui.Controls.Sample
|
|||
fonts.AddFont("FontAwesome.ttf", "FA");
|
||||
fonts.AddFont("ionicons.ttf", "Ion");
|
||||
})
|
||||
.Issue21109AddMappers();
|
||||
.Issue21109AddMappers()
|
||||
.Issue18720AddMappers()
|
||||
.Issue18720EditorAddMappers()
|
||||
.Issue18720DatePickerAddMappers()
|
||||
.Issue18720TimePickerAddMappers();
|
||||
|
||||
appBuilder.Services.AddTransient<TransientPage>();
|
||||
appBuilder.Services.AddScoped<ScopedPage>();
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#if WINDOWS
|
||||
using NUnit.Framework;
|
||||
using UITest.Appium;
|
||||
using UITest.Core;
|
||||
|
||||
namespace Microsoft.Maui.TestCases.Tests.Issues
|
||||
{
|
||||
public class Issue10645 : _IssuesUITest
|
||||
{
|
||||
public Issue10645(TestDevice device) : base(device)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Issue => "Image is not centered in AspectFill mode";
|
||||
|
||||
[Test]
|
||||
[Category(UITestCategories.ActionSheet)]
|
||||
public void Issue10645Test()
|
||||
{
|
||||
App.WaitForElement("AspectFillImage", timeout: TimeSpan.FromSeconds(4));
|
||||
|
||||
VerifyScreenshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#if ANDROID
|
||||
using NUnit.Framework;
|
||||
using UITest.Appium;
|
||||
using UITest.Core;
|
||||
|
||||
namespace Microsoft.Maui.TestCases.Tests.Issues
|
||||
{
|
||||
public class Issue18720 : _IssuesUITest
|
||||
{
|
||||
public Issue18720(TestDevice device) : base(device)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Issue => "Setting the background property of AppCompatEditText (Entry) in a handler mapping does not work";
|
||||
|
||||
[Test]
|
||||
[Category(UITestCategories.Entry)]
|
||||
public async Task SettingEntryBackgroundFromHandler()
|
||||
{
|
||||
App.WaitForElement("TestButton");
|
||||
App.Tap("TestButton");
|
||||
App.WaitForElement("CustomEntry1");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
VerifyScreenshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#if ANDROID
|
||||
using NUnit.Framework;
|
||||
using UITest.Appium;
|
||||
using UITest.Core;
|
||||
|
||||
namespace Microsoft.Maui.TestCases.Tests.Issues
|
||||
{
|
||||
public class Issue18720DatePicker : _IssuesUITest
|
||||
{
|
||||
public Issue18720DatePicker(TestDevice device) : base(device)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Issue => "Setting the background property of AppCompatEditText (DatePicker) in a handler mapping does not work";
|
||||
|
||||
[Test]
|
||||
[Category(UITestCategories.DatePicker)]
|
||||
public async Task SettingDatePickerBackgroundFromHandler()
|
||||
{
|
||||
App.WaitForElement("TestButton");
|
||||
App.Tap("TestButton");
|
||||
App.WaitForElement("CustomDatePicker1");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
VerifyScreenshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#if ANDROID
|
||||
using NUnit.Framework;
|
||||
using UITest.Appium;
|
||||
using UITest.Core;
|
||||
|
||||
namespace Microsoft.Maui.TestCases.Tests.Issues
|
||||
{
|
||||
public class Issue18720Editor : _IssuesUITest
|
||||
{
|
||||
public Issue18720Editor(TestDevice device) : base(device)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Issue => "Setting the background property of AppCompatEditText (Editor) in a handler mapping does not work";
|
||||
|
||||
[Test]
|
||||
[Category(UITestCategories.Editor)]
|
||||
public async Task SettingEditorBackgroundFromHandler()
|
||||
{
|
||||
App.WaitForElement("TestButton");
|
||||
App.Tap("TestButton");
|
||||
App.WaitForElement("CustomEditor1");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
VerifyScreenshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
#if ANDROID
|
||||
using NUnit.Framework;
|
||||
using UITest.Appium;
|
||||
using UITest.Core;
|
||||
|
||||
namespace Microsoft.Maui.TestCases.Tests.Issues
|
||||
{
|
||||
public class Issue18720TimePicker : _IssuesUITest
|
||||
{
|
||||
public Issue18720TimePicker(TestDevice device) : base(device)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Issue => "Setting the background property of AppCompatEditText (TimePicker) in a handler mapping does not work";
|
||||
|
||||
[Test]
|
||||
[Category(UITestCategories.TimePicker)]
|
||||
public async Task SettingTimePickerBackgroundFromHandler()
|
||||
{
|
||||
App.WaitForElement("TestButton");
|
||||
App.Tap("TestButton");
|
||||
App.WaitForElement("CustomTimePicker1");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
VerifyScreenshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
#if !MACCATALYST
|
||||
using NUnit.Framework;
|
||||
using UITest.Appium;
|
||||
using UITest.Core;
|
||||
|
||||
namespace Microsoft.Maui.TestCases.Tests.Issues
|
||||
{
|
||||
public class Issue23488 : _IssuesUITest
|
||||
{
|
||||
public Issue23488(TestDevice device): base(device)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Issue => "Span text-decoration is incorrect whereas the Label behaves properly";
|
||||
|
||||
[Test]
|
||||
[Category(UITestCategories.Label)]
|
||||
public void LabelHyperlinkUnderlineColor()
|
||||
{
|
||||
App.WaitForElement("WaitForLabelControl");
|
||||
VerifyScreenshot();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
Двоичные данные
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/Issue10645Test.png
Normal file
После Ширина: | Высота: | Размер: 24 KiB |
Двоичные данные
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/LabelHyperlinkUnderlineColor.png
Normal file
После Ширина: | Высота: | Размер: 3.5 KiB |
Двоичные данные
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/LabelHyperlinkUnderlineColor.png
Normal file
После Ширина: | Высота: | Размер: 20 KiB |
|
@ -98,6 +98,10 @@ namespace Microsoft.Maui.Controls.Xaml.UnitTests
|
|||
vm.Model[3] = "TextIndex2";
|
||||
Assert.AreEqual("TextIndex2", layout.label3.Text);
|
||||
|
||||
//https://github.com/dotnet/maui/issues/23621
|
||||
vm.Model.SetIndexerValueAndCallOnPropertyChangedWithoutIndex(3, "TextIndex3");
|
||||
Assert.AreEqual("TextIndex3", layout.label3.Text);
|
||||
|
||||
//testing 2way
|
||||
Assert.AreEqual("Text2", layout.entry0.Text);
|
||||
((IElementController)layout.entry0).SetValueFromRenderer(Entry.TextProperty, "Text3");
|
||||
|
@ -235,6 +239,15 @@ namespace Microsoft.Maui.Controls.Xaml.UnitTests
|
|||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public void SetIndexerValueAndCallOnPropertyChangedWithoutIndex(int v, string value)
|
||||
{
|
||||
if (values[v] == value)
|
||||
return;
|
||||
|
||||
values[v] = value;
|
||||
OnPropertyChanged("Indexer");
|
||||
}
|
||||
}
|
||||
|
||||
class MockItemViewModel : INotifyPropertyChanged
|
||||
|
|
|
@ -136,7 +136,12 @@ namespace Microsoft.Maui
|
|||
var visualElements = new List<IVisualTreeElement>();
|
||||
if (visualElement is IWindow window)
|
||||
{
|
||||
uiElement = window.Content?.ToPlatform();
|
||||
// Get the UI.Xaml.Window so we catch everything in the app window rather than the frame which doesn't include modal content
|
||||
var platformView = window.Handler?.PlatformView;
|
||||
if (platformView is UI.Xaml.Window winUiWindow)
|
||||
{
|
||||
uiElement = winUiWindow.Content;
|
||||
}
|
||||
}
|
||||
else if (visualElement is IView view)
|
||||
{
|
||||
|
|
|
@ -8,8 +8,10 @@ namespace Microsoft.Maui.Handlers
|
|||
{
|
||||
public partial class ImageHandler : ViewHandler<IImage, WImage>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override WImage CreatePlatformView() => new WImage();
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ConnectHandler(WImage platformView)
|
||||
{
|
||||
platformView.ImageOpened += OnImageOpened;
|
||||
|
@ -17,6 +19,7 @@ namespace Microsoft.Maui.Handlers
|
|||
base.ConnectHandler(platformView);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void DisconnectHandler(WImage platformView)
|
||||
{
|
||||
platformView.ImageOpened -= OnImageOpened;
|
||||
|
@ -25,25 +28,113 @@ namespace Microsoft.Maui.Handlers
|
|||
SourceLoader.Reset();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool NeedsContainer =>
|
||||
VirtualView?.Background != null ||
|
||||
VirtualView?.Aspect == Aspect.AspectFill ||
|
||||
base.NeedsContainer;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetupContainer()
|
||||
{
|
||||
base.SetupContainer();
|
||||
|
||||
// VerticalAlignment only works when the child's Height is Auto
|
||||
PlatformView.Height = Primitives.Dimension.Unset;
|
||||
|
||||
UpdateValue(nameof(IView.Height));
|
||||
UpdateValue(nameof(IView.Width));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void RemoveContainer()
|
||||
{
|
||||
base.RemoveContainer();
|
||||
|
||||
UpdateValue(nameof(IView.Height));
|
||||
UpdateValue(nameof(IView.Width));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IView.Height"/> property to the platform-specific implementations.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="view">The associated <see cref="Image"/> instance.</param>
|
||||
public static void MapHeight(IImageHandler handler, IImage view)
|
||||
{
|
||||
// VerticalAlignment only works when the container's Height is set and the child's Height is Auto. The child's Height
|
||||
// is set to Auto when the container is introduced.
|
||||
if (handler.ContainerView is FrameworkElement container)
|
||||
{
|
||||
container.Height = view.Height;
|
||||
handler.PlatformView.Height = Primitives.Dimension.Unset;
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewHandler.MapHeight(handler, view);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IView.Width"/> property to the platform-specific implementations.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="view">The associated <see cref="Image"/> instance.</param>
|
||||
public static void MapWidth(IImageHandler handler, IImage view)
|
||||
{
|
||||
if (handler.ContainerView is FrameworkElement container)
|
||||
{
|
||||
container.Width = view.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewHandler.MapWidth(handler, view);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IView.Background"/> property to the platform-specific implementations.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="image">The associated <see cref="Image"/> instance.</param>
|
||||
public static void MapBackground(IImageHandler handler, IImage image)
|
||||
{
|
||||
handler.UpdateValue(nameof(IViewHandler.ContainerView));
|
||||
handler.ToPlatform().UpdateBackground(image);
|
||||
}
|
||||
|
||||
public static void MapAspect(IImageHandler handler, IImage image) =>
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IImage.Aspect"/> property to the platform-specific implementations.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="image">The associated <see cref="Image"/> instance.</param>
|
||||
public static void MapAspect(IImageHandler handler, IImage image)
|
||||
{
|
||||
handler.UpdateValue(nameof(IViewHandler.ContainerView));
|
||||
handler.PlatformView?.UpdateAspect(image);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IImageSourcePart.IsAnimationPlaying"/> property to the platform-specific implementations.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="image">The associated <see cref="Image"/> instance.</param>
|
||||
public static void MapIsAnimationPlaying(IImageHandler handler, IImage image) =>
|
||||
handler.PlatformView?.UpdateIsAnimationPlaying(image);
|
||||
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IImageSourcePart.Source"/> property to the platform-specific implementations.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="image">The associated <see cref="Image"/> instance.</param>
|
||||
public static void MapSource(IImageHandler handler, IImage image) =>
|
||||
MapSourceAsync(handler, image).FireAndForget(handler);
|
||||
|
||||
/// <summary>
|
||||
/// Maps the abstract <see cref="IImageSourcePart.Source"/> property to the platform-specific implementations as an asynchronous operation.
|
||||
/// </summary>
|
||||
/// <param name="handler">The associated handler.</param>
|
||||
/// <param name="image">The associated <see cref="Image"/> instance.</param>
|
||||
public static Task MapSourceAsync(IImageHandler handler, IImage image) =>
|
||||
handler.SourceLoader.UpdateImageSourceAsync();
|
||||
|
||||
|
@ -66,4 +157,4 @@ namespace Microsoft.Maui.Handlers
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ namespace Microsoft.Maui.Handlers
|
|||
{
|
||||
#if __ANDROID__ || WINDOWS || TIZEN
|
||||
[nameof(IImage.Background)] = MapBackground,
|
||||
#endif
|
||||
#if WINDOWS
|
||||
[nameof(IImage.Height)] = MapHeight,
|
||||
[nameof(IImage.Width)] = MapWidth,
|
||||
#endif
|
||||
[nameof(IImage.Aspect)] = MapAspect,
|
||||
[nameof(IImage.IsAnimationPlaying)] = MapIsAnimationPlaying,
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
using Android.Graphics.Drawables;
|
||||
using Android.Runtime;
|
||||
|
||||
namespace Microsoft.Maui.Platform;
|
||||
|
||||
internal class MauiLayerDrawable : LayerDrawable
|
||||
{
|
||||
public MauiLayerDrawable(params Drawable[] layers)
|
||||
: base(layers)
|
||||
{
|
||||
}
|
||||
|
||||
protected MauiLayerDrawable(nint javaReference, JniHandleOwnership transfer)
|
||||
: base(javaReference, transfer)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -9,10 +9,9 @@ using Android.Views;
|
|||
using Android.Views.InputMethods;
|
||||
using Android.Widget;
|
||||
using AndroidX.AppCompat.Widget;
|
||||
using AndroidX.ConstraintLayout.Helper.Widget;
|
||||
using AndroidX.Core.Content;
|
||||
using AndroidX.Core.View;
|
||||
using AndroidX.Window.Layout;
|
||||
using Kotlin;
|
||||
using Microsoft.Maui.ApplicationModel;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Primitives;
|
||||
|
@ -188,62 +187,83 @@ namespace Microsoft.Maui.Platform
|
|||
|
||||
internal static void UpdateBackground(this EditText platformView, IView view)
|
||||
{
|
||||
if (platformView is null || platformView.Background is null || platformView.Context is null)
|
||||
if (platformView is null || platformView.Context is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove previous background gradient if any
|
||||
if (platformView.Background is MauiDrawable mauiDrawable)
|
||||
// The user has removed the background from the platform view in platform code
|
||||
// so we need to make sure to do absolutely nothing.
|
||||
if (platformView.Background is null)
|
||||
{
|
||||
platformView.Background = null;
|
||||
mauiDrawable.Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (platformView.Background is LayerDrawable layerDrawable)
|
||||
// Get the current background of the edit text so we can make sure to not overwite it
|
||||
// if it is not something that we have set in MAUI.
|
||||
var previousDrawable = platformView.Background;
|
||||
|
||||
// Remove the previous MAUI background (if any).
|
||||
if (previousDrawable is MauiDrawable || previousDrawable is MauiLayerDrawable)
|
||||
{
|
||||
platformView.Background = null;
|
||||
layerDrawable.Dispose();
|
||||
previousDrawable.Dispose();
|
||||
previousDrawable = null;
|
||||
}
|
||||
|
||||
// Android will reset the padding when setting a Background drawable
|
||||
// So we need to reapply the padding after
|
||||
var padLeft = platformView.PaddingLeft;
|
||||
var padTop = platformView.PaddingTop;
|
||||
var padRight = platformView.PaddingRight;
|
||||
var padBottom = platformView.PaddingBottom;
|
||||
|
||||
// Get the new background from the virtual view
|
||||
var paint = view.Background;
|
||||
|
||||
Drawable? defaultBackgroundDrawable = ContextCompat.GetDrawable(platformView.Context, Resource.Drawable.abc_edit_text_material);
|
||||
|
||||
var previousDrawable = defaultBackgroundDrawable ?? platformView.Background;
|
||||
var backgroundDrawable = paint.ToDrawable(platformView.Context);
|
||||
|
||||
if (previousDrawable is null)
|
||||
platformView.Background = backgroundDrawable;
|
||||
else
|
||||
if (backgroundDrawable is not null || previousDrawable is null)
|
||||
{
|
||||
if (backgroundDrawable is null)
|
||||
{
|
||||
// The default Drawable of EditText is an InsetDrawable and setting the background we use a LayerDrawable
|
||||
// to compose the custom background with the default behavior (bottom line).
|
||||
//
|
||||
// If the Background is null or is a ColorDrawable, a Custom Handler is being created, removing the default behavior.
|
||||
// In this case, we don't want to reset the Drawable to the default one.
|
||||
if (platformView.Background is not ColorDrawable)
|
||||
platformView.Background = previousDrawable;
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is a new background to set, or we removed a previous background and
|
||||
// now we have to re-apply just the default "line" background.
|
||||
|
||||
LayerDrawable layer = new LayerDrawable(new Drawable[] { backgroundDrawable, previousDrawable });
|
||||
platformView.Background = layer;
|
||||
// Regardless of what the new background is, we will need to apply the default
|
||||
// background "line" on top of it.
|
||||
// If for some reason this returns null, then there is nothing we can do because
|
||||
// AndroidX is probably broken since this is a resource from the AndroidX library.
|
||||
var defaultBackground = ContextCompat.GetDrawable(platformView.Context, Resource.Drawable.abc_edit_text_material);
|
||||
|
||||
if (backgroundDrawable is not null)
|
||||
{
|
||||
// The user set some background, so we need to apply it below the default "line".
|
||||
// If there is a broken AndroidX, then nothing we can do but just use ours.
|
||||
SetBackground(platformView, defaultBackground is null
|
||||
? new MauiLayerDrawable(backgroundDrawable)
|
||||
: new MauiLayerDrawable(backgroundDrawable, defaultBackground));
|
||||
}
|
||||
else if (previousDrawable is null)
|
||||
{
|
||||
// The user set null in the virtual view (or did not set anything/kept the defaults)
|
||||
// as we just removed a MAUI background from the platform view.
|
||||
// This means we just use the default Material background (the "line").
|
||||
SetBackground(platformView, defaultBackground);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The drawable currently in use was not a MAUI drawable nor are we setting a new
|
||||
// one so just do nothing and keep whatever the user has set in platform code.
|
||||
}
|
||||
|
||||
// Apply previous padding
|
||||
platformView.SetPadding(padLeft, padTop, padRight, padBottom);
|
||||
// A helper method to set the background and re-apply the padding since
|
||||
// Android will reset the padding when setting a Background drawable.
|
||||
static void SetBackground(EditText platformView, Drawable? background)
|
||||
{
|
||||
// Cache the current padding
|
||||
var padLeft = platformView.PaddingLeft;
|
||||
var padTop = platformView.PaddingTop;
|
||||
var padRight = platformView.PaddingRight;
|
||||
var padBottom = platformView.PaddingBottom;
|
||||
|
||||
// Set the new background
|
||||
platformView.Background = background;
|
||||
|
||||
// Apply previous padding
|
||||
platformView.SetPadding(padLeft, padTop, padRight, padBottom);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateBackground(this AView platformView, Paint? background) =>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#nullable enable
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using WImage = Microsoft.UI.Xaml.Controls.Image;
|
||||
|
||||
|
@ -14,6 +15,12 @@ namespace Microsoft.Maui.Platform
|
|||
public static void UpdateAspect(this WImage imageView, IImage image)
|
||||
{
|
||||
imageView.Stretch = image.Aspect.ToStretch();
|
||||
|
||||
if (image.Aspect == Aspect.AspectFill)
|
||||
{
|
||||
imageView.VerticalAlignment = VerticalAlignment.Center;
|
||||
imageView.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateIsAnimationPlaying(this WImage imageView, IImageSourcePart image)
|
||||
|
|
|
@ -83,6 +83,8 @@ override Microsoft.Maui.Handlers.HybridWebViewHandler.ConnectHandler(Microsoft.U
|
|||
override Microsoft.Maui.Handlers.HybridWebViewHandler.CreatePlatformView() -> Microsoft.UI.Xaml.Controls.WebView2!
|
||||
override Microsoft.Maui.Handlers.HybridWebViewHandler.DisconnectHandler(Microsoft.UI.Xaml.Controls.WebView2! platformView) -> void
|
||||
override Microsoft.Maui.Handlers.ImageHandler.ConnectHandler(Microsoft.UI.Xaml.Controls.Image! platformView) -> void
|
||||
override Microsoft.Maui.Handlers.ImageHandler.RemoveContainer() -> void
|
||||
override Microsoft.Maui.Handlers.ImageHandler.SetupContainer() -> void
|
||||
override Microsoft.Maui.Handlers.MenuFlyoutHandler.DisconnectHandler(Microsoft.UI.Xaml.Controls.MenuFlyout! platformView) -> void
|
||||
override Microsoft.Maui.Layouts.FlexBasis.Equals(object? obj) -> bool
|
||||
override Microsoft.Maui.Layouts.FlexBasis.GetHashCode() -> int
|
||||
|
@ -106,6 +108,8 @@ static Microsoft.Maui.Handlers.HybridWebViewHandler.MapEvaluateJavaScriptAsync(M
|
|||
static Microsoft.Maui.Handlers.HybridWebViewHandler.Mapper -> Microsoft.Maui.IPropertyMapper<Microsoft.Maui.IHybridWebView!, Microsoft.Maui.Handlers.IHybridWebViewHandler!>!
|
||||
static Microsoft.Maui.Handlers.HybridWebViewHandler.MapSendRawMessage(Microsoft.Maui.Handlers.IHybridWebViewHandler! handler, Microsoft.Maui.IHybridWebView! hybridWebView, object? arg) -> void
|
||||
static Microsoft.Maui.Handlers.LayoutHandler.MapInputTransparent(Microsoft.Maui.ILayoutHandler! handler, Microsoft.Maui.ILayout! layout) -> void
|
||||
static Microsoft.Maui.Handlers.ImageHandler.MapHeight(Microsoft.Maui.Handlers.IImageHandler! handler, Microsoft.Maui.IImage! view) -> void
|
||||
static Microsoft.Maui.Handlers.ImageHandler.MapWidth(Microsoft.Maui.Handlers.IImageHandler! handler, Microsoft.Maui.IImage! view) -> void
|
||||
static Microsoft.Maui.Handlers.SearchBarHandler.MapIsSpellCheckEnabled(Microsoft.Maui.Handlers.ISearchBarHandler! handler, Microsoft.Maui.ISearchBar! searchBar) -> void
|
||||
static Microsoft.Maui.Handlers.SwipeItemMenuItemHandler.MapSourceAsync(Microsoft.Maui.Handlers.ISwipeItemMenuItemHandler! handler, Microsoft.Maui.ISwipeItemMenuItem! image) -> System.Threading.Tasks.Task!
|
||||
static Microsoft.Maui.Hosting.MauiHandlersCollectionExtensions.AddHandler<TType>(this Microsoft.Maui.Hosting.IMauiHandlersCollection! handlersCollection, System.Func<System.IServiceProvider!, Microsoft.Maui.IElementHandler!>! handlerImplementationFactory) -> Microsoft.Maui.Hosting.IMauiHandlersCollection!
|
||||
|
|