Platform support
| iOS | Mac Catalyst | Android | Windows | |
|---|---|---|---|---|
| Move in drag and drop | New | New | No change | Works when the drag source allows Move |
| Share preview image | Yes | Yes | Android 10 and later | Ignored |
| Icon Composer icon | Yes | Yes | Not affected | Not affected |
Where the new code lives
The repository keeps each part of the framework in its own folder under src, and this week's code touches three of them.
Controls
src/Controls
The user interface layer: pages, views, and gestures like drag and drop.
Talks to Apple's drag and drop system and now passes a Move request along.
Essentials
src/Essentials
Device features behind one shared API, such as sharing, file access and screenshots.
Describes the text or link you want to share, now with a PreviewImage property.
Tells Apple's share dialog what is being shared, and the image is now part of that.
Resizetizer
src/SingleProject/Resizetizer
A build step that prepares app icons, images and fonts for each platform.
Instructions for MSBuild, the tool that builds .NET projects, with new steps that hand an Icon Composer icon to the Apple build.
1
Drag and drop can now Move
A drop target can now ask for a Move instead of a Copy.
A drop target is the view that receives a dragged item, and in .NET MAUI you make one by adding a DropGestureRecognizer to a view.
Why it was added
A drop target could only answer None or Copy. None blocks the drop, and Copy makes iOS and Windows present the dragged item as a copy. That is the wrong message when the user is moving something and not duplicating it.
A developer asked for a Move answer back in 2023, in issue #16472. Until now the only way to get one on Apple devices was to write Apple-only code.
What you get
One shared line asks for a Move: set AcceptedOperation to DataPackageOperation.Move. On iOS and Mac Catalyst the system is then told that the drag is a move, so it stops presenting it as a copy.
A typical use
Picture a board with two lists, "To do" and "Done". The user drags a task from one list to the other, and the task should leave the first list. That is a move, and now the drop target can say so. Your app still does the actual moving of the task in its own drop handler.
How it works
- The user drags an item over a drop target.
- Your
DragOverhandler setse.AcceptedOperation = DataPackageOperation.Move. - On iOS and Mac Catalyst,
DragAndDropDelegateasks every drop recognizer on the view and combines their answers. - It then picks one result to propose to the system, as the diagram shows.
None?DragAndDropDelegate picks the result on iOS and Mac Catalyst. It asks the questions from top to bottom and stops at the first yes. A drag session here means one drag, from start to end.Copy wins a tie on purpose, so if one recognizer says Copy and another says Move, the drop is a Copy.
Try it
The drop target asks for a Move in its DragOver handler.
void OnDragOver(object? sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Move;
}
On Windows the drag source also has to allow it, which the sample page does in DragStarting.
#if WINDOWS
using WinOp = Windows.ApplicationModel.DataTransfer.DataPackageOperation;
#endif
void OnDragStarting(object? sender, DragStartingEventArgs e)
{
#if WINDOWS
e.PlatformArgs!.DragStartingEventArgs.AllowedOperations =
WinOp.Copy | WinOp.Move;
e.PlatformArgs.Handled = true;
#endif
}
Where the code lives
Controls owns this. The new value is in DataPackageOperation, you set it through DragEventArgs, and the Apple logic sits in DragAndDropDelegate.
Current limit
- Move is opt-in, so if you do nothing, drops are still copies.
- .NET MAUI only reports the Move. Your app still has to take the item out of the old place and put it in the new one, and it won't reorder a list for you.
- Only the iOS and Mac Catalyst code changed, while the Windows and Android framework code is the same as before.
- On Windows, the drag source has to allow a Move through its native settings, as the second snippet shows.
Sources
Gerald Versluis, in pull request #39016: Add opt-in Move support to drag and drop
3
Icon Composer icons for iOS and Mac Catalyst
A MauiIcon can now point to an Icon Composer .icon folder.
Icon Composer is Apple's tool for designing layered app icons, and it saves each icon as a folder whose name ends in .icon. MauiIcon is the project item that names your app icon.
Why it was added
Apple introduced the .icon format with its Liquid Glass design in macOS 26. An app icon in this format is no longer one flat picture. It is a set of layers with effects such as translucency and lighting.
MauiIcon only took a single image, usually SVG or PNG, which Resizetizer resized for each platform. That route cannot carry layers. The .NET tooling for Apple platforms learned to compile .icon folders in dotnet/macios #24722, and this change connects MauiIcon to it.
What you get
Your iOS and Mac Catalyst app can ship the layered icon exactly as it was designed, with no flat export in between. Apple's asset compiler builds the icon, the other platforms keep their SVG or PNG, and there is no new project item to learn.
A typical use
A designer builds the app icon in Icon Composer and hands you a folder called AppIcon.icon. You add the folder to the project, point MauiIcon at it for the Apple targets, and build.
How it works
- Add a
MauiIconthat points to the.iconfolder. Use a condition to limit it to iOS and Mac Catalyst. - Keep your SVG or PNG
MauiIconfor the other platforms. - During the build, a new step called
_CollectMauiNativeAppleIconnotices the.iconending. - It checks the folder. There must be an
icon.jsonfile at the top and at least one file inAssets. - From there the icon takes its own route through the build, shown below.
The route that already existed.
.icon folderNew. iOS and Mac Catalyst only.
AppIcon is set to the folder nameMauiIcon can take through the build. The right one is new.The step also saves a hash of each file in the folder. A hash is a short code that changes when the file changes, so an edited icon gets compiled again.
Try it
In the project file, swap the icon for the Apple targets only.
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'
Or $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<MauiIcon Remove="Resources\AppIcon\appicon.svg" />
<MauiIcon Include="Resources\AppIcon\AppIcon.icon" />
</ItemGroup>
The Remove and Include lines follow the integration test in the pull request. The condition is the usual way a .NET MAUI project limits items to one platform, and the folder name is only an example.
Where the code lives
Resizetizer owns this. All the new steps are in Microsoft.Maui.Resizetizer.After.targets.
Current limit
- It applies to iOS and Mac Catalyst only.
- You need Apple workload 26.5.11720 or newer, where a workload is the installed toolset for one platform. With an older one the build stops with an error.
- Only one
.iconfolder is allowed per Apple target, and you can't combine it with anotherMauiIconfor that target. - If you set
AppIconyourself, it has to match the folder name.
Sources
Gerald Versluis, in pull request #38958: Resizetizer: Support Icon Composer MauiIcon bundles
One last joke
Why did the dragged item refuse to be a Copy?
It was ready to Move on.