[iOS] Fixes for RefreshControl with iOS11 LargeTitles (#1984) fixes #1950

* [Controls] Add repo for #1905

* [iOS] Update refresh control to handle large titles

* [iOS] Update refresh control to handle large titles

[iOS] Update refresh control to handle large titles

[iOS] Delay setting refreshcontrol hidden to true

[iOS] Better fix, manually animate

Fix animation not showing

fix

* [iOS] Update refresh control to handle large titles

* [iOS] Be safe on UIRefreshcontrol changes

* [iOS] Force the Refresh to show when using large titles

* [iOS] Just trigger if we really pull to refresh

* [iOS] More fixes to refreshcontrol

* [iOS] Only force scroll if in Portrait and large titles

* Update ListViewRenderer.cs
This commit is contained in:
Rui Marinho 2018-04-24 14:13:53 +01:00 коммит произвёл GitHub
Родитель efbadcf401
Коммит de205114f8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 191 добавлений и 22 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Xamarin.Forms.Platform.iOS namespace Xamarin.Forms.Platform.iOS
{ {
@ -16,5 +17,24 @@ namespace Xamarin.Forms.Platform.iOS
return result; return result;
} }
internal static T FindParentOfType<T>(this VisualElement element)
{
var navPage = element.GetParentsPath()
.OfType<T>()
.FirstOrDefault();
return navPage;
}
internal static IEnumerable<Element> GetParentsPath(this VisualElement self)
{
Element current = self;
while (!Application.IsApplicationOrNull(current.RealParent))
{
current = current.RealParent;
yield return current;
}
}
} }
} }

Просмотреть файл

@ -33,6 +33,7 @@ namespace Xamarin.Forms.Platform.iOS
ITemplatedItemsView<Cell> TemplatedItemsView => Element; ITemplatedItemsView<Cell> TemplatedItemsView => Element;
public override UIViewController ViewController => _tableViewController; public override UIViewController ViewController => _tableViewController;
bool _disposed; bool _disposed;
bool _usingLargeTitles;
protected UITableViewRowAnimation InsertRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; protected UITableViewRowAnimation InsertRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic;
protected UITableViewRowAnimation DeleteRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic; protected UITableViewRowAnimation DeleteRowsAnimation { get; set; } = UITableViewRowAnimation.Automatic;
@ -211,10 +212,13 @@ namespace Xamarin.Forms.Platform.iOS
{ {
if (Control == null) if (Control == null)
{ {
_tableViewController = new FormsUITableViewController(e.NewElement); if (Forms.IsiOS11OrNewer)
{
var parentNav = e.NewElement.FindParentOfType<NavigationPage>();
_usingLargeTitles = (parentNav != null && parentNav.OnThisPlatform().PrefersLargeTitles());
}
_tableViewController = new FormsUITableViewController(e.NewElement, _usingLargeTitles);
SetNativeControl(_tableViewController.TableView); SetNativeControl(_tableViewController.TableView);
if (Forms.IsiOS9OrNewer)
Control.CellLayoutMarginsFollowReadableWidth = false;
_insetTracker = new KeyboardInsetTracker(_tableViewController.TableView, () => Control.Window, insets => Control.ContentInset = Control.ScrollIndicatorInsets = insets, point => _insetTracker = new KeyboardInsetTracker(_tableViewController.TableView, () => Control.Window, insets => Control.ContentInset = Control.ScrollIndicatorInsets = insets, point =>
{ {
@ -983,10 +987,9 @@ namespace Xamarin.Forms.Platform.iOS
throw new NotSupportedException("Header cells do not support context actions"); throw new NotSupportedException("Header cells do not support context actions");
var renderer = (CellRenderer)Internals.Registrar.Registered.GetHandlerForObject<IRegisterable>(cell); var renderer = (CellRenderer)Internals.Registrar.Registered.GetHandlerForObject<IRegisterable>(cell);
view = new HeaderWrapperView { Cell = cell }; view = new HeaderWrapperView { Cell = cell };
view.AddSubview(renderer.GetCell(cell, null, tableView)); view.AddSubview(renderer.GetCell(cell, null, tableView));
return view; return view;
} }
@ -1100,7 +1103,14 @@ namespace Xamarin.Forms.Platform.iOS
public override void Scrolled(UIScrollView scrollView) public override void Scrolled(UIScrollView scrollView)
{ {
if (_isDragging && scrollView.ContentOffset.Y < 0) if (_isDragging && scrollView.ContentOffset.Y < 0)
{
_uiTableViewController.UpdateShowHideRefresh(true); _uiTableViewController.UpdateShowHideRefresh(true);
}
if (_isDragging && scrollView.ContentOffset.Y < -10f && _uiTableViewController._usingLargeTitles && Device.Info.CurrentOrientation.IsPortrait())
{
_uiTableViewController.ForceRefreshing();
}
} }
public override string[] SectionIndexTitles(UITableView tableView) public override string[] SectionIndexTitles(UITableView tableView)
@ -1291,12 +1301,17 @@ namespace Xamarin.Forms.Platform.iOS
bool _refreshAdded; bool _refreshAdded;
bool _disposed; bool _disposed;
internal bool _usingLargeTitles;
bool _isRefreshing;
public FormsUITableViewController(ListView element) public FormsUITableViewController(ListView element, bool usingLargeTitles)
{ {
if (Forms.IsiOS9OrNewer) if (Forms.IsiOS9OrNewer)
TableView.CellLayoutMarginsFollowReadableWidth = false; TableView.CellLayoutMarginsFollowReadableWidth = false;
_refresh = new UIRefreshControl();
_usingLargeTitles = usingLargeTitles;
_refresh = new FormsRefreshControl(_usingLargeTitles);
_refresh.ValueChanged += OnRefreshingChanged; _refresh.ValueChanged += OnRefreshingChanged;
_list = element; _list = element;
} }
@ -1315,6 +1330,10 @@ namespace Xamarin.Forms.Platform.iOS
{ {
_refresh.BeginRefreshing(); _refresh.BeginRefreshing();
//hack: On iOS11 with large titles we need to adjust the scroll offset manually
//since our UITableView is not the first child of the UINavigationController
UpdateContentOffset(TableView.ContentOffset.Y - _refresh.Frame.Height);
//hack: when we don't have cells in our UITableView the spinner fails to appear //hack: when we don't have cells in our UITableView the spinner fails to appear
CheckContentSize(); CheckContentSize();
@ -1323,8 +1342,14 @@ namespace Xamarin.Forms.Platform.iOS
} }
else else
{ {
if (RefreshControl == null)
return;
_refresh.EndRefreshing(); _refresh.EndRefreshing();
UpdateContentOffset(-1);
_isRefreshing = false;
if (!_list.IsPullToRefreshEnabled) if (!_list.IsPullToRefreshEnabled)
RemoveRefresh(); RemoveRefresh();
} }
@ -1351,6 +1376,19 @@ namespace Xamarin.Forms.Platform.iOS
// 5. We end up here; A refresh is in progress while being asked to disable pullToRefresh // 5. We end up here; A refresh is in progress while being asked to disable pullToRefresh
} }
//hack: Form some reason UIKit isn't allowing to scroll negative values with largetitles
public void ForceRefreshing()
{
if (!_list.IsPullToRefreshEnabled)
return;
if (!_refresh.Refreshing && !_isRefreshing)
{
_isRefreshing = true;
UpdateContentOffset(TableView.ContentOffset.Y - _refresh.Frame.Height, _refresh.BeginRefreshing);
_list.SendRefreshing();
}
}
public void UpdateShowHideRefresh(bool shouldHide) public void UpdateShowHideRefresh(bool shouldHide)
{ {
if (_list.IsPullToRefreshEnabled) if (_list.IsPullToRefreshEnabled)
@ -1407,6 +1445,8 @@ namespace Xamarin.Forms.Platform.iOS
{ {
if (_refresh.Refreshing) if (_refresh.Refreshing)
_list.SendRefreshing(); _list.SendRefreshing();
_isRefreshing = _refresh.Refreshing;
} }
void RemoveRefresh() void RemoveRefresh()
@ -1414,11 +1454,55 @@ namespace Xamarin.Forms.Platform.iOS
if (!_refreshAdded) if (!_refreshAdded)
return; return;
if (_refresh.Refreshing) if (_refresh.Refreshing || _isRefreshing)
_refresh.EndRefreshing(); _refresh.EndRefreshing();
RefreshControl = null; RefreshControl = null;
_refreshAdded = false; _refreshAdded = false;
_isRefreshing = false;
}
void UpdateContentOffset(nfloat offset, Action completed = null)
{
if (!_usingLargeTitles)
return;
UIView.Animate(0.2, () => TableView.ContentOffset = new CoreGraphics.CGPoint(TableView.ContentOffset.X, offset), completed);
}
}
public class FormsRefreshControl : UIRefreshControl
{
bool _usingLargeTitles;
public FormsRefreshControl(bool usingLargeTitles)
{
_usingLargeTitles = usingLargeTitles;
}
public override bool Hidden
{
get
{
return base.Hidden;
}
set
{
//hack: ahahah take that UIKit!
//when using pull to refresh with Large tiles sometimes iOS tries to hide the UIRefreshControl
if (_usingLargeTitles && value && Refreshing)
return;
base.Hidden = value;
}
}
public override void BeginRefreshing()
{
base.BeginRefreshing();
if (!_usingLargeTitles)
return;
Hidden = false;
} }
} }
} }