очень первый вопрос SO после долгого скрытия. Я преподавал разработку iOS с использованием C# под Xamarin с Visual Studio.UIScrollView не регистрирует события, пока ViewController Segue
Мое заявление о проблемах: Почему мое прокручивание работает только, то есть регистрирует такие события, как перетаскивание, ПОСЛЕ того, чтобы использовать ViewController segue для другого вида и обратно? В то же время, используя прокрутку через PageControl работает отлично в любое время?
Я успешно использовал широкий диапазон образцов кода, найденных как здесь, так и на сайте Xamarin и в других местах (включая некоторые образцы, написанные в Swift, которые я перевел на C# - Objective-C, также может быть Minoan Linear B).
Это также работало без проблем во всех вариантах, пока я не начал добавлять AutoLayout в уравнение. Использование FluentLayout упростило это, и теперь у меня в целом есть хорошо продуманный пользовательский интерфейс именно так, как я хочу, на всех моделях iPhone.
Существенный код шаблона работал нормально, когда он все еще был застрял в ViewDidLoad корневого viewcontroller, но теперь, когда я сломал все это на «чистые» классы, он показывает это странное поведение.
Одна из проблем, с которой мне пришлось столкнуться, заключалась в том, что изображение было правильно изменено в кадре UIImageView, когда размер не доступен до тех пор, пока ограничения компоновки не будут завершены. Как я понимаю теперь, концепция ViewDidLayoutSubViews().
Таким образом, мой корень VS кода:
namespace ScrollTest.iOS
{
public partial class RootViewController : UIViewController
{
...
public override void ViewDidLoad()
{
base.ViewDidLoad();
View = new MainView();
}
public override void ViewDidLayoutSubviews()
{
base.ViewDidLayoutSubviews();
CGRect pageFrame = SharedStatic.ScrollView.Frame;
SharedStatic.ScrollView.ContentSize = new CGSize(pageFrame.Width * 2, pageFrame.Height);
SharedStatic.ImageView.Frame = pageFrame;
SharedStatic.ImageView.Image = UIImage.FromFile("toothless.jpg").Scale(pageFrame.Size);
SharedStatic.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;
pageFrame.X += SharedStatic.ScrollView.Frame.Width;
SharedStatic.TableView.Frame = pageFrame;
SharedStatic.TableView.ContentMode = UIViewContentMode.ScaleAspectFit;
}
...
}
Из класса MainView() на вниз У меня есть иерархия взглядов, которые экземпляры, а затем установить ограничение макета, например, так:
namespace ScrollTest.iOS
{
[Register("MainView")]
internal class MainView : UIView
{
public MainView()
{
Initialise();
}
public MainView(CGRect frame) : base(frame)
{
Initialise();
}
private void Initialise()
{
SharedStatic.MainView = this;
var navView = new NavView();
Add(navView);
var contentView = new ContentView();
Add(contentView);
var pagerView = new PagerView();
Add(pagerView);
var toolView = new ToolView();
Add(toolView);
var buttonView = new ButtonView();
Add(buttonView);
const int padding = 1;
var navHeight = 32;
var pageControlHeight = 25;
var toolHeight = 25;
var buttonHeight = 20;
this.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
this.AddConstraints
(
... other view constraints...
contentView.Below(navView, padding),
contentView.AtLeftOf(this),
contentView.WithSameWidth(this),
contentView.Bottom().EqualTo().TopOf(pagerView),
pagerView.Above(toolView, padding),
pagerView.AtLeftOf(this),
pagerView.WithSameWidth(this),
pagerView.Height().EqualTo(pageControlHeight),
...
);
}
}
}
Фактический класс ScrollView выглядит так: обработчики событий просто подключаются к отладке вывода для этого теста.
namespace ScrollTest.iOS
{
[Register("ContentView")]
internal class ContentView : UIScrollView
{
private ContainerView _containerView;
public ContentView()
{
Initialise();
}
public ContentView(CGRect frame) : base(frame)
{
Initialise();
}
private void Initialise()
{
SharedStatic.ScrollView = this;
_containerView = ContainerView.Instance;
Add(_containerView);
PagingEnabled = true;
ScrollEnabled = true;
Bounces = false;
DirectionalLockEnabled = true;
DecelerationEnded += scrollView_DecelerationEnded;
Scrolled += delegate { Console.WriteLine("scrolled"); };
DecelerationStarted += delegate { Console.WriteLine("deceleration started"); };
DidZoom += delegate { Console.WriteLine("did zoon"); };
DraggingEnded += delegate { Console.WriteLine("dragging ended"); };
DraggingStarted += delegate { Console.WriteLine("dragging started"); };
ScrollAnimationEnded += delegate { Console.WriteLine("Scroll animation ended"); };
ScrolledToTop += delegate { Console.WriteLine("Scrolled to top"); };
WillEndDragging += delegate { Console.WriteLine("will end dragging"); };
ZoomingEnded += delegate { Console.WriteLine("zooming ended"); };
ZoomingStarted += delegate { Console.WriteLine("zooming started"); };
this.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
this.AddConstraints
(
_containerView.AtLeftOf(this),
_containerView.AtRightOf(this),
_containerView.AtTopOf(this),
_containerView.AtBottomOf(this)
);
}
private void scrollView_DecelerationEnded(object sender, EventArgs e)
{
Console.WriteLine("Done changing page");
nfloat x1 = SharedStatic.ImageView.Frame.X;
nfloat x2 = SharedStatic.TableView.Frame.X;
nfloat x = this.ContentOffset.X;
if (x == x1)
{
Console.WriteLine("flip");
SharedStatic.PageControl.CurrentPage = 0;
}
else
{
Console.WriteLine("flop");
SharedStatic.PageControl.CurrentPage = 1;
}
}
}
}
И «после» это вид контейнера, который удерживает мое изображение и таблицу, от моего понимания прошивки кодирования практики является способом сделать это (кроме класса одноплодного, который был результатом тестирования что-то еще).
namespace ScrollTest.iOS
{
[Register("ContainerView")]
internal sealed class ContainerView : UIView
{
private UIImageView _imageView;
private UITableView _tableView;
private static readonly Lazy<ContainerView> lazy = new Lazy<ContainerView>(() => new ContainerView());
public static ContainerView Instance { get { return lazy.Value; } }
private ContainerView()
{
Initialise();
}
private ContainerView(CGRect frame) : base(frame)
{
Initialise();
}
private void Initialise()
{
SharedStatic.ContainerView = this;
Console.WriteLine("setting up scrolling stuff");
_imageView = new UIImageView();
Add(_imageView);
SharedStatic.ImageView = _imageView;
_tableView = new UITableView();
Add(_tableView);
SharedStatic.TableView = _tableView;
this.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
this.AddConstraints
(
_imageView.AtLeftOf(this),
_imageView.AtTopOf(this),
_imageView.AtBottomOf(this),
_imageView.WithSameWidth(this),
_tableView.Left().EqualTo().RightOf(_imageView),
_tableView.WithSameTop(_imageView),
_tableView.WithSameBottom(_imageView),
_tableView.WithSameWidth(_imageView)
);
}
}
}
На верхней части моего экрана находится панель навигации с кнопкой гамбургера, который вызовет переход к другому ViewController, который по дороге отвечает за выскакивает экран Параметры. Он содержит еще одну кнопку гамбургера, чтобы уволить себя и вернуться на главный экран. Это работает без проблем:
_navBar.SetItems(new UINavigationItem[] { new UINavigationItem { LeftBarButtonItem = new UIBarButtonItem(UIImage.FromFile("hamburger32x32.png"), UIBarButtonItemStyle.Plain, BringUpOptions) } }, false);
И обработчик события:
internal async void BringUpOptions(object s, EventArgs e)
{
Console.WriteLine("Options clicked");
var board = UIStoryboard.FromName("MainStoryboard", null);
var optionController = board.InstantiateViewController("OptionsViewController");
optionController.ModalTransitionStyle = UIModalTransitionStyle.FlipHorizontal;
await this.Window.RootViewController.PresentViewControllerAsync(optionController, true);
}
Я использую раскадровку редактор только для моих двух контроллеров зрения и Segue. Все остальные элементы управления/представления программно генерируются, как и макеты.
Вводя это вместе, результаты в правильно выложенном пользовательском интерфейсе, правильно работающем сегменте на экране параметров, правильном увольнении/возврате.
Также работает щелчок по элементу управления страницей: перелистывание назад и вперед между изображением и представлением таблицы.
Однако этот пейджинг не работает при попытке перетащить изображение в режим просмотра таблицы! Не при запуске приложения! Отладка показывает, что никаких событий не обнаружено.
До тех пор, пока я не перейду на экран параметров хотя бы один раз, а затем обратно! Затем все работает так, как ожидалось: контроль страниц flip/flops и scrollview свитки вперед и назад.
У меня полная потеря, почему это будет так! Что такое инициализация начального сегмента, которая, по-видимому, необходима для работы scrollview? Я оштукатурил свой код с отладочным выходом и одним нажал на отвлечение. Я просто не могу его найти. Может быть, это ошибка в Xamarin?
Есть ли какие-то настройки или звонки, которые мне нужно сделать из классов вида, о которых я просто не знаю, потому что они обычно скрыты при использовании редакторов раскадровки? Я был над досье класса UIScrollView от Xamarin, но на меня ничего не выпрыгивает.
Я думал, что мое несколько неудобное использование этого общего статического класса может быть проблемой, но я не знаю, как получить информацию о макете на разных классах (поэтому сбой изображений не получается). Мое намерение состояло в том, чтобы погрузиться в это и удалить кладж однажды я решил эту мой остановлю всю работу:
namespace ScrollTest.iOS
{
internal static class SharedStatic
{
internal static MainView MainView { get; set; }
internal static UIPageControl PageControl { get; set; }
internal static ContentView ScrollView { get; set; }
internal static ContentView ContentView => ScrollView;
internal static ContainerView ContainerView { get; set; }
internal static UIImageView ImageView { get; set; }
internal static UITableView TableView { get; set; }
}
}
С кодом так близко к прекрасно работает, я действительно думал, что я что-то достаточно прямо отсутствую -вперед. Некоторая ошибка новичка, с которой никто не сталкивается при использовании раскадровки, но которая как-то кусает меня.
Спасибо!
EDIT 20150828: После некоторых дальнейших исследований я добавил переопределение для SendEvent для UIApplication:
[Register("TestApp")]
class TestApp : UIApplication
{
public override void SendEvent(UIEvent uievent)
{
base.SendEvent(uievent);
Console.WriteLine("event hit");
}
}
И затем изменил Main.cs на:
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
UIApplication.Main(args, "TestApp", "AppDelegate");
}
}
В результате я действительно может см., что прикосновения/перетаскивания/прокрутки приводят к хитам событий, но что они не определены/категоризированы должным образом. Свернув в отладчик, я смог увидеть, что UIScrollView получает «хиты», но просто ничего не делает с ними! По сути, они полностью игнорируют их - пока я не выполнил этот первый сеанс контроллера segue, тогда все события срабатывают правильно.
Это начинает приносить ошибку, но я просто не знаю достаточно, чтобы быть уверенным, что это не где-то в моем коде или на самом деле в Xamarin.