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
38 changes: 19 additions & 19 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
<Project>
<PropertyGroup>
<NetVersion>net9.0</NetVersion>
<MauiPackageVersion>9.0.100</MauiPackageVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<PropertyGroup>
<NetVersion>net9.0</NetVersion>
<MauiPackageVersion>9.0.100</MauiPackageVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>preview</LangVersion>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>

<IsAndroid>false</IsAndroid>
<IsIos>false</IsIos>
<IsWindows>false</IsWindows>
<IsAndroid>false</IsAndroid>
<IsIos>false</IsIos>
<IsWindows>false</IsWindows>

<IsAndroid Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">true</IsAndroid>
<IsIos Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">true</IsIos>
<IsWindows Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">true</IsWindows>
<IsAndroid Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">true</IsAndroid>
<IsIos Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">true</IsIos>
<IsWindows Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">true</IsWindows>

<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,20 @@ protected override ReorderableItemsViewAdapter<ReorderableItemsView, IGroupableI
}


sealed class PJViewAdapter : ReorderableItemsViewAdapter<ReorderableItemsView, IGroupableItemsViewSource>
/// <summary>
/// Custom adapter for CollectionView that enables context actions (menu items) on long press.
/// </summary>
/// <remarks>
/// This adapter extends the standard ReorderableItemsViewAdapter to provide context menu
/// functionality for items in a CollectionView. It manages the creation and binding of
/// menu items to collection view items, allowing for contextual actions when a user
/// performs a long press on an item.
/// </remarks>
public class PJViewAdapter : ReorderableItemsViewAdapter<ReorderableItemsView, IGroupableItemsViewSource>
{
IGroupableItemsViewSource itemsSource = default!;
ReorderableItemsView collectionView;
internal static MenuItem[]? MenuItems;
protected ReorderableItemsView collectionView;
protected MenuItem[]? menuItems;

public PJViewAdapter(ReorderableItemsView reorderableItemsView, Func<Microsoft.Maui.Controls.View, Context, ItemContentView>? createView = null) : base(reorderableItemsView, createView)
{
Expand Down Expand Up @@ -46,14 +55,14 @@ public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int positi
return;
}

if (MenuItems is null)
if (menuItems is null)
{
MenuItems = new MenuItem[contextActions.Count];
menuItems = new MenuItem[contextActions.Count];

foreach (var (index, item) in contextActions.Index())
{
item.BindingContext = cv.BindingContext;
MenuItems[index] = item;
menuItems[index] = item;
}
}

Expand All @@ -64,9 +73,8 @@ public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int positi
if (position >= 0 && position < size)
{
var element = itemsSource.GetItem(position + 1);
var contextMenuListener = new ItemContextMenuListener(element);
var contextMenuListener = new ItemContextMenuListener(element, menuItems);
holder.ItemView.SetOnCreateContextMenuListener(contextMenuListener);

}
}

Expand All @@ -81,13 +89,24 @@ public override void OnViewRecycled(Java.Lang.Object holder)
}
}

/// <summary>
/// Handles the creation of context menus for items in a CollectionView on Android.
/// </summary>
/// <remarks>
/// This class implements the Android-specific interface for creating context menus
/// when a user performs a long-press on an item in the CollectionView. It associates
/// the menu items with the data element that was pressed, allowing context-specific
/// actions to be performed.
/// </remarks>
sealed class ItemContextMenuListener : Java.Lang.Object, global::Android.Views.View.IOnCreateContextMenuListener
{
readonly object element;
readonly MenuItem[] items;

public ItemContextMenuListener(object element)
public ItemContextMenuListener(object element, MenuItem[] items)
{
this.element = element;
this.items = items;
}

public void OnCreateContextMenu(IContextMenu? menu, Android.Views.View? v, IContextMenuContextMenuInfo? menuInfo)
Expand All @@ -97,14 +116,7 @@ public void OnCreateContextMenu(IContextMenu? menu, Android.Views.View? v, ICont
return;
}

if (PJViewAdapter.MenuItems is null)
{
return;
}

var menuItems = PJViewAdapter.MenuItems;

foreach (var (index, item) in menuItems.Index())
foreach (var (index, item) in items.Index())
{
var mItem = menu.Add(0, index + 1, index, item.Text);
Assert(mItem is not null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,9 @@ protected override ItemsViewController<ReorderableItemsView> CreateController(Re

sealed class PJReorderableItemsViewController : ReorderableItemsViewController<ReorderableItemsView>
{
public ReorderableItemsView ReorderableItemsView { get; }

public PJReorderableItemsViewController(ReorderableItemsView reorderableItemsView, ItemsViewLayout layout) : base(reorderableItemsView, layout)
{
ReorderableItemsView = reorderableItemsView;

}

protected override UICollectionViewDelegateFlowLayout CreateDelegator()
Expand All @@ -28,10 +26,18 @@ protected override UICollectionViewDelegateFlowLayout CreateDelegator()
}
}

sealed class PJDelegator : ReorderableItemsViewDelegator<ReorderableItemsView,
ReorderableItemsViewController<ReorderableItemsView>>
/// <summary>
/// Custom delegator for handling context menu interactions in CollectionView on iOS.
/// Extends the ReorderableItemsViewDelegator to provide context menu functionality.
/// </summary>
/// <remarks>
/// This class intercepts tap and hold gestures on collection items and displays
/// a context menu with actions defined in the CollectionView's ContextActions property.
/// </remarks>
public class PJDelegator : ReorderableItemsViewDelegator<ReorderableItemsView, ReorderableItemsViewController<ReorderableItemsView>>
{
readonly ReorderableItemsViewController<ReorderableItemsView> itemsViewController;
protected ReorderableItemsViewController<ReorderableItemsView> itemsViewController;
List<MenuItem>? items;

public PJDelegator(ItemsViewLayout itemsViewLayout, ReorderableItemsViewController<ReorderableItemsView> itemsViewController) : base(itemsViewLayout, itemsViewController)
{
Expand All @@ -50,7 +56,7 @@ public PJDelegator(ItemsViewLayout itemsViewLayout, ReorderableItemsViewControll
var element = vc.ItemsSource[indexPath];
var cv = (CollectionView)vc.ItemsView;

var items = ContextActions.GetContextActions(cv);
items ??= ContextActions.GetContextActions(cv);

if (items.Count is 0)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
using Microsoft.Maui.Controls.Handlers.Items;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
using WMenuFlyout = Microsoft.UI.Xaml.Controls.MenuFlyout;
using WMenuFlyoutItem = Microsoft.UI.Xaml.Controls.MenuFlyoutItem;

namespace PJ.ContextActions.Maui;

sealed class PJCollectionViewHandler : CollectionViewHandler
public class PJCollectionViewHandler : CollectionViewHandler
{
MenuItem[]? menuItems;
protected MenuItem[]? menuItems;
Command<CommandBag>? mauiCommand;

protected override ListViewBase CreatePlatformView()
{
var listView = base.CreatePlatformView();

listView.ContainerContentChanging += OnContainerContentChanging;
listView.ContainerContentChanging += OnContainerContentChangingDelegate;

return listView;
}

protected override void DisconnectHandler(ListViewBase platformView)
{
platformView.ContainerContentChanging -= OnContainerContentChanging;
platformView.ContainerContentChanging -= OnContainerContentChangingDelegate;
base.DisconnectHandler(platformView);
}

void OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
/// <summary>
/// Handles the ContainerContentChanging event for the ListView, setting up context menus for each item.
/// </summary>
/// <param name="sender">The ListViewBase that triggered the event.</param>
/// <param name="args">Event arguments containing information about the changed container content.</param>
/// <remarks>
/// This method configures a context menu (MenuFlyout) for each item in the collection view.
/// It initializes menu items from the CollectionView's context actions, binds commands,
/// and sets up icons if specified. The context menu appears when the user right-clicks on an item.
/// </remarks>
protected virtual void OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (args.InRecycleQueue || args.ItemContainer is null)
return;
Expand Down Expand Up @@ -74,4 +83,7 @@ void OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEve

args.ItemContainer.ContextFlyout = menuFlyout;
}

void OnContainerContentChangingDelegate(ListViewBase sender, ContainerContentChangingEventArgs args) =>
OnContainerContentChanging(sender, args);
}
1 change: 1 addition & 0 deletions src/PJ.ContextActions.Maui/PJ.ContextActions.Maui.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> -->

<AllowUnsafeBlocks Condition="$(IsWindows)">true</AllowUnsafeBlocks>
</PropertyGroup>

<PropertyGroup>
Expand Down
Loading