339 строки
8.8 KiB
C#
339 строки
8.8 KiB
C#
using System;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using Android.App;
|
|
using Android.Content;
|
|
using Android.Util;
|
|
using Android.Views;
|
|
using Android.Widget;
|
|
using AView = Android.Views.View;
|
|
using AListView = Android.Widget.ListView;
|
|
using Android.Graphics.Drawables;
|
|
using Android.Support.V7.App;
|
|
|
|
namespace Xamarin.Forms.Platform.Android
|
|
{
|
|
public abstract class CellAdapter : BaseAdapter<object>, AdapterView.IOnItemLongClickListener, ActionMode.ICallback, AdapterView.IOnItemClickListener,
|
|
global::Android.Support.V7.View.ActionMode.ICallback
|
|
{
|
|
readonly Context _context;
|
|
ActionMode _actionMode;
|
|
Cell _actionModeContext;
|
|
|
|
bool _actionModeNeedsUpdates;
|
|
AView _contextView;
|
|
global::Android.Support.V7.View.ActionMode _supportActionMode;
|
|
|
|
protected CellAdapter(Context context)
|
|
{
|
|
if (context == null)
|
|
throw new ArgumentNullException("context");
|
|
|
|
_context = context;
|
|
}
|
|
|
|
internal Cell ActionModeContext
|
|
{
|
|
get { return _actionModeContext; }
|
|
set
|
|
{
|
|
if (_actionModeContext == value)
|
|
return;
|
|
|
|
if (_actionModeContext != null)
|
|
((INotifyCollectionChanged)_actionModeContext.ContextActions).CollectionChanged -= OnContextItemsChanged;
|
|
|
|
ActionModeObject = null;
|
|
_actionModeContext = value;
|
|
|
|
if (_actionModeContext != null)
|
|
{
|
|
((INotifyCollectionChanged)_actionModeContext.ContextActions).CollectionChanged += OnContextItemsChanged;
|
|
ActionModeObject = _actionModeContext.BindingContext;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal object ActionModeObject { get; set; }
|
|
|
|
internal AView ContextView
|
|
{
|
|
get { return _contextView; }
|
|
set
|
|
{
|
|
if (_contextView == value)
|
|
return;
|
|
|
|
if (_contextView != null)
|
|
{
|
|
var isSelected = (bool)ActionModeContext.GetValue(ListViewAdapter.IsSelectedProperty);
|
|
if (isSelected)
|
|
SetSelectedBackground(_contextView);
|
|
else
|
|
UnsetSelectedBackground(_contextView);
|
|
}
|
|
|
|
_contextView = value;
|
|
|
|
if (_contextView != null)
|
|
SetSelectedBackground(_contextView, true);
|
|
}
|
|
}
|
|
|
|
public bool OnActionItemClicked(ActionMode mode, IMenuItem item)
|
|
{
|
|
mode.Menu.Clear();
|
|
OnActionItemClickedImpl(item);
|
|
_actionMode?.Finish();
|
|
return true;
|
|
}
|
|
|
|
bool global::Android.Support.V7.View.ActionMode.ICallback.OnActionItemClicked(global::Android.Support.V7.View.ActionMode mode, IMenuItem item)
|
|
{
|
|
mode.Menu.Clear();
|
|
OnActionItemClickedImpl(item);
|
|
_supportActionMode?.Finish();
|
|
return true;
|
|
}
|
|
|
|
public bool OnCreateActionMode(ActionMode mode, IMenu menu)
|
|
{
|
|
CreateContextMenu(menu);
|
|
return true;
|
|
}
|
|
|
|
bool global::Android.Support.V7.View.ActionMode.ICallback.OnCreateActionMode(global::Android.Support.V7.View.ActionMode mode, IMenu menu)
|
|
{
|
|
CreateContextMenu(menu);
|
|
return true;
|
|
}
|
|
|
|
public void OnDestroyActionMode(ActionMode mode)
|
|
{
|
|
OnDestroyActionModeImpl();
|
|
_actionMode.Dispose();
|
|
_actionMode = null;
|
|
}
|
|
|
|
void global::Android.Support.V7.View.ActionMode.ICallback.OnDestroyActionMode(global::Android.Support.V7.View.ActionMode mode)
|
|
{
|
|
OnDestroyActionModeImpl();
|
|
_supportActionMode.Dispose();
|
|
_supportActionMode = null;
|
|
}
|
|
|
|
public bool OnPrepareActionMode(ActionMode mode, IMenu menu)
|
|
{
|
|
return OnPrepareActionModeImpl(menu);
|
|
}
|
|
|
|
bool global::Android.Support.V7.View.ActionMode.ICallback.OnPrepareActionMode(global::Android.Support.V7.View.ActionMode mode, IMenu menu)
|
|
{
|
|
return OnPrepareActionModeImpl(menu);
|
|
}
|
|
|
|
public void OnItemClick(AdapterView parent, AView view, int position, long id)
|
|
{
|
|
if (_actionMode != null || _supportActionMode != null)
|
|
{
|
|
var listView = parent as AListView;
|
|
if (listView != null)
|
|
position -= listView.HeaderViewsCount;
|
|
HandleContextMode(view, position);
|
|
}
|
|
else
|
|
HandleItemClick(parent, view, position, id);
|
|
}
|
|
|
|
public bool OnItemLongClick(AdapterView parent, AView view, int position, long id)
|
|
{
|
|
var listView = parent as AListView;
|
|
if (listView != null)
|
|
position -= listView.HeaderViewsCount;
|
|
return HandleContextMode(view, position);
|
|
}
|
|
|
|
protected abstract Cell GetCellForPosition(int position);
|
|
|
|
protected virtual void HandleItemClick(AdapterView parent, AView view, int position, long id)
|
|
{
|
|
}
|
|
|
|
protected void SetSelectedBackground(AView view, bool isContextTarget = false)
|
|
{
|
|
int attribute = isContextTarget ? global::Android.Resource.Attribute.ColorLongPressedHighlight : global::Android.Resource.Attribute.ColorActivatedHighlight;
|
|
using (var value = new TypedValue())
|
|
{
|
|
if (_context.Theme.ResolveAttribute(attribute, value, true))
|
|
view.SetBackgroundResource(value.ResourceId);
|
|
else
|
|
view.SetBackgroundResource(global::Android.Resource.Color.HoloBlueDark);
|
|
}
|
|
}
|
|
|
|
protected void UnsetSelectedBackground(AView view)
|
|
{
|
|
view.SetBackgroundResource(0);
|
|
}
|
|
|
|
internal void CloseContextActions()
|
|
{
|
|
_actionMode?.Finish();
|
|
_supportActionMode?.Finish();
|
|
}
|
|
|
|
void CreateContextMenu(IMenu menu)
|
|
{
|
|
var changed = new PropertyChangedEventHandler(OnContextActionPropertyChanged);
|
|
var changing = new PropertyChangingEventHandler(OnContextActionPropertyChanging);
|
|
var commandChanged = new EventHandler(OnContextActionCommandCanExecuteChanged);
|
|
|
|
for (var i = 0; i < ActionModeContext.ContextActions.Count; i++)
|
|
{
|
|
MenuItem action = ActionModeContext.ContextActions[i];
|
|
|
|
IMenuItem item = menu.Add(global::Android.Views.Menu.None, i,global::Android.Views.Menu.None, action.Text);
|
|
var icon = action.Icon;
|
|
if (icon != null)
|
|
{
|
|
Drawable iconDrawable = _context.GetFormsDrawable(icon);
|
|
if (iconDrawable != null)
|
|
item.SetIcon(iconDrawable);
|
|
}
|
|
|
|
action.PropertyChanged += changed;
|
|
action.PropertyChanging += changing;
|
|
|
|
if (action.Command != null)
|
|
action.Command.CanExecuteChanged += commandChanged;
|
|
|
|
if (!((IMenuItemController)action).IsEnabled)
|
|
item.SetEnabled(false);
|
|
}
|
|
}
|
|
|
|
bool HandleContextMode(AView view, int position)
|
|
{
|
|
if (view is EditText || view is TextView || view is SearchView)
|
|
return false;
|
|
|
|
Cell cell = GetCellForPosition(position);
|
|
|
|
if (cell == null)
|
|
return false;
|
|
|
|
if (_actionMode != null || _supportActionMode != null)
|
|
{
|
|
if (!cell.HasContextActions)
|
|
{
|
|
CloseContextActions();
|
|
return false;
|
|
}
|
|
|
|
ActionModeContext = cell;
|
|
|
|
_actionMode?.Invalidate();
|
|
_supportActionMode?.Invalidate();
|
|
}
|
|
else
|
|
{
|
|
if (!cell.HasContextActions)
|
|
return false;
|
|
|
|
ActionModeContext = cell;
|
|
|
|
var appCompatActivity = view.Context as AppCompatActivity;
|
|
if (appCompatActivity == null)
|
|
_actionMode = ((Activity)view.Context).StartActionMode(this);
|
|
else
|
|
_supportActionMode = appCompatActivity.StartSupportActionMode(this);
|
|
}
|
|
|
|
ContextView = view;
|
|
|
|
return true;
|
|
}
|
|
|
|
void OnActionItemClickedImpl(IMenuItem item)
|
|
{
|
|
int index = item.ItemId;
|
|
IMenuItemController action = ActionModeContext.ContextActions[index];
|
|
|
|
action.Activate();
|
|
}
|
|
|
|
void OnContextActionCommandCanExecuteChanged(object sender, EventArgs eventArgs)
|
|
{
|
|
_actionModeNeedsUpdates = true;
|
|
_actionMode?.Invalidate();
|
|
_supportActionMode?.Invalidate();
|
|
}
|
|
|
|
void OnContextActionPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
var action = (MenuItem)sender;
|
|
|
|
if (e.PropertyName == MenuItem.CommandProperty.PropertyName)
|
|
{
|
|
if (action.Command != null)
|
|
action.Command.CanExecuteChanged += OnContextActionCommandCanExecuteChanged;
|
|
}
|
|
else
|
|
_actionModeNeedsUpdates = true;
|
|
}
|
|
|
|
void OnContextActionPropertyChanging(object sender, PropertyChangingEventArgs e)
|
|
{
|
|
var action = (MenuItem)sender;
|
|
|
|
if (e.PropertyName == MenuItem.CommandProperty.PropertyName)
|
|
{
|
|
if (action.Command != null)
|
|
action.Command.CanExecuteChanged -= OnContextActionCommandCanExecuteChanged;
|
|
}
|
|
}
|
|
|
|
void OnContextItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
_actionModeNeedsUpdates = true;
|
|
_actionMode?.Invalidate();
|
|
_supportActionMode?.Invalidate();
|
|
}
|
|
|
|
void OnDestroyActionModeImpl()
|
|
{
|
|
var changed = new PropertyChangedEventHandler(OnContextActionPropertyChanged);
|
|
var changing = new PropertyChangingEventHandler(OnContextActionPropertyChanging);
|
|
var commandChanged = new EventHandler(OnContextActionCommandCanExecuteChanged);
|
|
|
|
((INotifyCollectionChanged)ActionModeContext.ContextActions).CollectionChanged -= OnContextItemsChanged;
|
|
|
|
for (var i = 0; i < ActionModeContext.ContextActions.Count; i++)
|
|
{
|
|
MenuItem action = ActionModeContext.ContextActions[i];
|
|
action.PropertyChanged -= changed;
|
|
action.PropertyChanging -= changing;
|
|
|
|
if (action.Command != null)
|
|
action.Command.CanExecuteChanged -= commandChanged;
|
|
}
|
|
ContextView = null;
|
|
|
|
ActionModeContext = null;
|
|
_actionModeNeedsUpdates = false;
|
|
}
|
|
|
|
bool OnPrepareActionModeImpl(IMenu menu)
|
|
{
|
|
if (_actionModeNeedsUpdates)
|
|
{
|
|
_actionModeNeedsUpdates = false;
|
|
|
|
menu.Clear();
|
|
CreateContextMenu(menu);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} |