Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Controls/src/Core/HandlerImpl/Application/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public partial class Application
new PropertyMapper<Application, ApplicationHandler>(ApplicationHandler.Mapper)
{
#if ANDROID
// There is also a mapper on Window for this property since this property is relevant at the window level for
// Android not the application level
[PlatformConfiguration.AndroidSpecific.Application.WindowSoftInputModeAdjustProperty.PropertyName] = MapWindowSoftInputModeAdjust,
#endif
};
Expand Down
16 changes: 16 additions & 0 deletions src/Controls/src/Core/HandlerImpl/Window/Window.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Android.App;
using Android.Views;
using AndroidX.AppCompat.App;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Handlers;

namespace Microsoft.Maui.Controls
Expand All @@ -20,5 +21,20 @@ public static void MapContent(WindowHandler handler, IWindow view)
public static void MapContent(IWindowHandler handler, IWindow view)
{
}

internal static void MapWindowSoftInputModeAdjust(IWindowHandler handler, IWindow view)
{
if (view.Parent is Application app)
{
var setting = PlatformConfiguration.AndroidSpecific.Application.GetWindowSoftInputModeAdjust(app);
view.UpdateWindowSoftInputModeAdjust(setting.ToPlatform());
}
}

private protected override void OnParentChangedCore()
{
base.OnParentChangedCore();
Handler?.UpdateValue(PlatformConfiguration.AndroidSpecific.Application.WindowSoftInputModeAdjustProperty.PropertyName);
}
}
}
15 changes: 13 additions & 2 deletions src/Controls/src/Core/HandlerImpl/Window/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@ namespace Microsoft.Maui.Controls
{
public partial class Window
{
public static IPropertyMapper<IWindow, WindowHandler> ControlsWindowMapper = new PropertyMapper<IWindow, WindowHandler>(WindowHandler.Mapper);
public static IPropertyMapper<IWindow, WindowHandler> ControlsWindowMapper =
new PropertyMapper<IWindow, WindowHandler>(WindowHandler.Mapper);

// ControlsWindowMapper incorrectly typed to WindowHandler
static IPropertyMapper<IWindow, IWindowHandler> Mapper =
new PropertyMapper<IWindow, IWindowHandler>(ControlsWindowMapper)
{
#if ANDROID
// This property is also on the Application Mapper since that's where the attached property exists
[PlatformConfiguration.AndroidSpecific.Application.WindowSoftInputModeAdjustProperty.PropertyName] = MapWindowSoftInputModeAdjust,
#endif
};

internal static void RemapForControls()
{
WindowHandler.Mapper = ControlsWindowMapper;
WindowHandler.Mapper = Mapper;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Android.App;
using Android.Content;
using Android.Media;
using Android.Views;
using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;
using AApplication = Android.App.Application;
Expand All @@ -10,32 +11,24 @@ public static class ApplicationExtensions
{
public static void UpdateWindowSoftInputModeAdjust(this AApplication platformView, Application application)
{
var adjust = SoftInput.AdjustPan;

if (Application.Current != null)
if (application is IApplication app)
{
WindowSoftInputModeAdjust elementValue = Application.Current.OnThisPlatform().GetWindowSoftInputModeAdjust();

switch (elementValue)
{
case WindowSoftInputModeAdjust.Resize:
adjust = SoftInput.AdjustResize;
break;
case WindowSoftInputModeAdjust.Unspecified:
adjust = SoftInput.AdjustUnspecified;
break;
default:
adjust = SoftInput.AdjustPan;
break;
}
foreach (var window in app.Windows)
window?.Handler?.UpdateValue(PlatformConfiguration.AndroidSpecific.Application.WindowSoftInputModeAdjustProperty.PropertyName);
}
}

IMauiContext mauiContext = application.FindMauiContext(true);
Context context = mauiContext?.Context;
Activity activity = context.GetActivity();

activity?.Window?.SetSoftInputMode(adjust);

internal static SoftInput ToPlatform(this WindowSoftInputModeAdjust windowSoftInputModeAdjust)
{
switch (windowSoftInputModeAdjust)
{
case WindowSoftInputModeAdjust.Resize:
return SoftInput.AdjustResize;
case WindowSoftInputModeAdjust.Unspecified:
return SoftInput.AdjustUnspecified;
default:
return SoftInput.AdjustPan;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using ASoftInput = Android.Views.SoftInput;
using AApplication = Android.App.Application;
using AActivity = Android.App.Activity;

namespace Microsoft.Maui.DeviceTests
{
[Category(TestCategory.Application)]
public partial class ApplicationTests : ControlsHandlerTestBase
{
[Category(TestCategory.Application)]
public class SoftInputModeTests : ControlsHandlerTestBase
{
[Fact]
public async Task SoftInputModeDefaultsToAdjustPan()
{
await InvokeOnMainThreadAsync(() =>
{
Assert.Equal(ASoftInput.AdjustPan, GetSoftInput());
});
}

[Fact]
public async Task SoftInputModeSetOnApplicationPropagatesToWindowHandlers()
{
EnsureHandlerCreated((builder) =>
{
builder.Services.AddSingleton<IApplication>((_) => new SoftInputModeApplication());
builder.ConfigureMauiHandlers(handler =>
{
handler.AddHandler<SoftInputModeWindow, SoftInputWindowHandlerStub>();
handler.AddHandler<SoftInputModeApplication, SoftInputApplicationHandlerStub>();
});
});

await InvokeOnMainThreadAsync(() =>
{
var handlers = new List<IElementHandler>();

try
{
// Setup application stub
var app = MauiContext.Services.GetService<IApplication>() as SoftInputModeApplication;
app.Handler = app.ToHandler(MauiContext);

handlers.Add(app.Handler);

// Setup window
var windowHandler = (SoftInputWindowHandlerStub)app.Window.ToHandler(MauiContext);
app.Window.Handler = windowHandler;

handlers.Insert(0, app.Window.Handler);

// Validate that the Soft Input initializes to AdjustPan
Assert.Equal(ASoftInput.AdjustPan, windowHandler.LastASoftInputSet);

// Set to Resize
Controls.PlatformConfiguration.AndroidSpecific.Application.SetWindowSoftInputModeAdjust(
app,
Controls.PlatformConfiguration.AndroidSpecific.WindowSoftInputModeAdjust.Resize);

// Validate the mapper on the window handler is called with correct value
Assert.Equal(ASoftInput.AdjustResize, windowHandler.LastASoftInputSet);

// Set to Pan
Controls.PlatformConfiguration.AndroidSpecific.Application.SetWindowSoftInputModeAdjust(
app,
Controls.PlatformConfiguration.AndroidSpecific.WindowSoftInputModeAdjust.Pan);

// Validate the mapper on the window handler is called with correct value
Assert.Equal(ASoftInput.AdjustPan, windowHandler.LastASoftInputSet);
}
finally
{
foreach (var handler in handlers)
{
handler.DisconnectHandler();
}
}
});
}

ASoftInput GetSoftInput() =>
GetSoftInput(MauiContext.Context.GetActivity());

ASoftInput GetSoftInput(AActivity aActivity) =>
aActivity.Window.Attributes.SoftInputMode;

class SoftInputApplicationHandlerStub : ApplicationHandler
{
public SoftInputApplicationHandlerStub() : base(Application.ControlsApplicationMapper)
{
}

protected override AApplication CreatePlatformElement()
{
return new AApplication();
}
}

class SoftInputModeApplication : Application, IApplication
{
public SoftInputModeWindow Window { get; } = new SoftInputModeWindow();

public SoftInputModeApplication() : base(false)
{
Window.Parent = this;
}

IReadOnlyList<IWindow> IApplication.Windows
{
get
{
return new List<IWindow>() { Window };
}
}
}

class SoftInputModeWindow : Window
{

}

class SoftInputWindowHandlerStub : ElementHandler<IWindow, AActivity>, IWindowHandler
{
public ASoftInput LastASoftInputSet { get; private set; } = ASoftInput.AdjustUnspecified;

public static IPropertyMapper<IWindow, SoftInputWindowHandlerStub> StubMapper =
new PropertyMapper<IWindow, SoftInputWindowHandlerStub>()
{
[Controls.PlatformConfiguration.AndroidSpecific.Application.WindowSoftInputModeAdjustProperty.PropertyName] = MapWindowSoftInputModeAdjust
};

public static void MapWindowSoftInputModeAdjust(SoftInputWindowHandlerStub arg1, IWindow arg2)
{
if (arg2.Parent is Application app)
{
var setting = Controls.PlatformConfiguration.AndroidSpecific.Application.GetWindowSoftInputModeAdjust(app);
arg1.LastASoftInputSet = setting.ToPlatform();
}
}

public SoftInputWindowHandlerStub() : base(StubMapper, null)
{

}

protected override AActivity CreatePlatformElement()
{
return new AActivity();
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace Microsoft.Maui.DeviceTests
{
public partial class ApplicationTests : ControlsHandlerTestBase
{
}
}
2 changes: 1 addition & 1 deletion src/Controls/tests/DeviceTests/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class MauiProgram
public static Microsoft.UI.Xaml.Window CurrentWindow => MauiProgramDefaults.DefaultWindow;
#endif

public static IApplication DefaultTestApp { get; private set; }
public static IApplication DefaultTestApp => MauiProgramDefaults.DefaultTestApp;

public static MauiApp CreateMauiApp() =>
MauiProgramDefaults.CreateMauiApp(new List<Assembly>()
Expand Down
1 change: 1 addition & 0 deletions src/Controls/tests/DeviceTests/TestCategory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
public static class TestCategory
{
public const string Application = "Application";
public const string Behavior = "Behavior";
public const string Button = "Button";
public const string CheckBox = "CheckBox";
Expand Down
12 changes: 12 additions & 0 deletions src/Core/src/Platform/Android/WindowExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Android.App;
using Android.Content;
using Android.Content.Res;
using Android.Views;
using Microsoft.Maui.Devices;
using Microsoft.Maui.Platform;

Expand All @@ -20,5 +22,15 @@ internal static DisplayOrientation GetOrientation(this IWindow? window)
_ => DisplayOrientation.Unknown
};
}

internal static void UpdateWindowSoftInputModeAdjust(this IWindow platformView, SoftInput inputMode)
{
var activity = platformView?.Handler?.PlatformView as Activity ??
platformView?.Handler?.MauiContext?.GetPlatformWindow();

activity?
.Window?
.SetSoftInputMode(inputMode);
}
}
}