зеркало из https://github.com/DeGsoft/maui-linux.git
308 строки
7.3 KiB
C#
308 строки
7.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UIKit;
|
|
using NSAction = System.Action;
|
|
using PointF = CoreGraphics.CGPoint;
|
|
using RectangleF = CoreGraphics.CGRect;
|
|
|
|
namespace Xamarin.Forms.Platform.iOS
|
|
{
|
|
internal class iOS7ButtonContainer : UIView
|
|
{
|
|
readonly nfloat _buttonWidth;
|
|
|
|
public iOS7ButtonContainer(nfloat buttonWidth) : base(new RectangleF(0, 0, 0, 0))
|
|
{
|
|
_buttonWidth = buttonWidth;
|
|
ClipsToBounds = true;
|
|
}
|
|
|
|
public override void LayoutSubviews()
|
|
{
|
|
var width = Frame.Width;
|
|
nfloat takenSpace = 0;
|
|
|
|
for (var i = 0; i < Subviews.Length; i++)
|
|
{
|
|
var view = Subviews[i];
|
|
|
|
var pos = Subviews.Length - i;
|
|
var x = width - _buttonWidth * pos;
|
|
view.Frame = new RectangleF(x, 0, view.Frame.Width, view.Frame.Height);
|
|
|
|
takenSpace += view.Frame.Width;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class ContextScrollViewDelegate : UIScrollViewDelegate
|
|
{
|
|
readonly nfloat _finalButtonSize;
|
|
UIView _backgroundView;
|
|
List<UIButton> _buttons;
|
|
UITapGestureRecognizer _closer;
|
|
UIView _container;
|
|
GlobalCloseContextGestureRecognizer _globalCloser;
|
|
|
|
bool _isDisposed;
|
|
static WeakReference<UIScrollView> s_scrollViewBeingScrolled;
|
|
UITableView _table;
|
|
|
|
public ContextScrollViewDelegate(UIView container, List<UIButton> buttons, bool isOpen)
|
|
{
|
|
IsOpen = isOpen;
|
|
_container = container;
|
|
_buttons = buttons;
|
|
|
|
for (var i = 0; i < buttons.Count; i++)
|
|
{
|
|
var b = buttons[i];
|
|
b.Hidden = !isOpen;
|
|
|
|
ButtonsWidth += b.Frame.Width;
|
|
_finalButtonSize = b.Frame.Width;
|
|
}
|
|
}
|
|
|
|
public nfloat ButtonsWidth { get; }
|
|
|
|
public Action ClosedCallback { get; set; }
|
|
|
|
public bool IsOpen { get; private set; }
|
|
|
|
public override void DraggingStarted(UIScrollView scrollView)
|
|
{
|
|
if (ShouldIgnoreScrolling(scrollView))
|
|
return;
|
|
|
|
s_scrollViewBeingScrolled = new WeakReference<UIScrollView>(scrollView);
|
|
|
|
if (!IsOpen)
|
|
SetButtonsShowing(true);
|
|
|
|
var cell = GetContextCell(scrollView);
|
|
if (!cell.Selected)
|
|
return;
|
|
|
|
if (!IsOpen)
|
|
RemoveHighlight(scrollView);
|
|
}
|
|
|
|
public void PrepareForDeselect(UIScrollView scrollView)
|
|
{
|
|
RestoreHighlight(scrollView);
|
|
}
|
|
|
|
public override void Scrolled(UIScrollView scrollView)
|
|
{
|
|
if (ShouldIgnoreScrolling(scrollView))
|
|
return;
|
|
|
|
var width = _finalButtonSize;
|
|
var count = _buttons.Count;
|
|
|
|
if (!UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
|
|
_container.Frame = new RectangleF(scrollView.Frame.Width, 0, scrollView.ContentOffset.X, scrollView.Frame.Height);
|
|
else
|
|
{
|
|
var ioffset = scrollView.ContentOffset.X / (float)count;
|
|
|
|
if (ioffset > width)
|
|
width = ioffset + 1;
|
|
|
|
for (var i = count - 1; i >= 0; i--)
|
|
{
|
|
var b = _buttons[i];
|
|
var rect = b.Frame;
|
|
b.Frame = new RectangleF(scrollView.Frame.Width + (count - (i + 1)) * ioffset, 0, width, rect.Height);
|
|
}
|
|
}
|
|
|
|
if (scrollView.ContentOffset.X == 0)
|
|
{
|
|
IsOpen = false;
|
|
SetButtonsShowing(false);
|
|
RestoreHighlight(scrollView);
|
|
|
|
s_scrollViewBeingScrolled = null;
|
|
ClearCloserRecognizer(GetContextCell(scrollView));
|
|
ClosedCallback?.Invoke();
|
|
}
|
|
}
|
|
|
|
public void Unhook(UIScrollView scrollView)
|
|
{
|
|
RestoreHighlight(scrollView);
|
|
ClearCloserRecognizer(GetContextCell(scrollView));
|
|
}
|
|
|
|
public override void WillEndDragging(UIScrollView scrollView, PointF velocity, ref PointF targetContentOffset)
|
|
{
|
|
if (ShouldIgnoreScrolling(scrollView))
|
|
return;
|
|
|
|
var width = ButtonsWidth;
|
|
var x = targetContentOffset.X;
|
|
var parentThreshold = scrollView.Frame.Width * .4f;
|
|
var contentThreshold = width * .8f;
|
|
|
|
if (x >= parentThreshold || x >= contentThreshold)
|
|
{
|
|
IsOpen = true;
|
|
targetContentOffset = new PointF(width, 0);
|
|
RemoveHighlight(scrollView);
|
|
|
|
if (_globalCloser == null)
|
|
{
|
|
UIView view = scrollView;
|
|
while (view.Superview != null)
|
|
{
|
|
view = view.Superview;
|
|
var table = view as UITableView;
|
|
if (table != null)
|
|
{
|
|
ContextActionsCell contentCell = GetContextCell(scrollView);
|
|
NSAction close = () =>
|
|
{
|
|
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
|
|
RestoreHighlight(scrollView);
|
|
|
|
IsOpen = false;
|
|
scrollView.SetContentOffset(new PointF(0, 0), true);
|
|
ClearCloserRecognizer(contentCell);
|
|
contentCell = null;
|
|
};
|
|
|
|
_table = table;
|
|
_globalCloser = new GlobalCloseContextGestureRecognizer(scrollView, close);
|
|
_globalCloser.ShouldRecognizeSimultaneously = (recognizer, r) => r == _table.PanGestureRecognizer;
|
|
table.AddGestureRecognizer(_globalCloser);
|
|
|
|
_closer = new UITapGestureRecognizer(close);
|
|
contentCell.ContentCell.AddGestureRecognizer(_closer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClearCloserRecognizer(GetContextCell(scrollView));
|
|
|
|
IsOpen = false;
|
|
targetContentOffset = new PointF(0, 0);
|
|
|
|
if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
|
|
RestoreHighlight(scrollView);
|
|
}
|
|
}
|
|
|
|
static bool ShouldIgnoreScrolling(UIScrollView scrollView)
|
|
{
|
|
if (s_scrollViewBeingScrolled == null)
|
|
return false;
|
|
|
|
UIScrollView scrollViewBeingScrolled;
|
|
if (!s_scrollViewBeingScrolled.TryGetTarget(out scrollViewBeingScrolled)
|
|
|| ReferenceEquals(scrollViewBeingScrolled, scrollView)
|
|
|| !ReferenceEquals(((ContextScrollViewDelegate)scrollViewBeingScrolled.Delegate)?._table, ((ContextScrollViewDelegate)scrollView.Delegate)?._table))
|
|
return false;
|
|
|
|
scrollView.SetContentOffset(new PointF(0, 0), false);
|
|
return true;
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (_isDisposed)
|
|
return;
|
|
|
|
_isDisposed = true;
|
|
|
|
if (disposing)
|
|
{
|
|
ClosedCallback = null;
|
|
|
|
s_scrollViewBeingScrolled = null;
|
|
_table = null;
|
|
_backgroundView = null;
|
|
_container = null;
|
|
|
|
_buttons = null;
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
void ClearCloserRecognizer(ContextActionsCell cell)
|
|
{
|
|
if (_globalCloser == null || _globalCloser.State == UIGestureRecognizerState.Cancelled)
|
|
return;
|
|
|
|
cell?.ContentCell?.RemoveGestureRecognizer(_closer);
|
|
_closer.Dispose();
|
|
_closer = null;
|
|
|
|
_table.RemoveGestureRecognizer(_globalCloser);
|
|
_table = null;
|
|
_globalCloser.Dispose();
|
|
_globalCloser = null;
|
|
}
|
|
|
|
ContextActionsCell GetContextCell(UIScrollView scrollView)
|
|
{
|
|
var view = scrollView?.Superview?.Superview;
|
|
var cell = view as ContextActionsCell;
|
|
while (view?.Superview != null)
|
|
{
|
|
cell = view as ContextActionsCell;
|
|
if (cell != null)
|
|
break;
|
|
|
|
view = view.Superview;
|
|
}
|
|
|
|
return cell;
|
|
}
|
|
|
|
void RemoveHighlight(UIScrollView scrollView)
|
|
{
|
|
var subviews = scrollView.Superview.Superview.Subviews;
|
|
|
|
var count = 0;
|
|
for (var i = 0; i < subviews.Length; i++)
|
|
{
|
|
var s = subviews[i];
|
|
if (s.Frame.Height > 1)
|
|
count++;
|
|
}
|
|
|
|
if (count <= 1)
|
|
return;
|
|
|
|
_backgroundView = subviews[0];
|
|
_backgroundView.RemoveFromSuperview();
|
|
|
|
var cell = GetContextCell(scrollView);
|
|
cell.SelectionStyle = UITableViewCellSelectionStyle.None;
|
|
}
|
|
|
|
void RestoreHighlight(UIScrollView scrollView)
|
|
{
|
|
if (_backgroundView == null)
|
|
return;
|
|
|
|
var cell = GetContextCell(scrollView);
|
|
cell.SelectionStyle = UITableViewCellSelectionStyle.Default;
|
|
cell.SetSelected(true, false);
|
|
|
|
scrollView.Superview.Superview.InsertSubview(_backgroundView, 0);
|
|
_backgroundView = null;
|
|
}
|
|
|
|
void SetButtonsShowing(bool show)
|
|
{
|
|
for (var i = 0; i < _buttons.Count; i++)
|
|
_buttons[i].Hidden = !show;
|
|
}
|
|
}
|
|
} |