iPhone - управление сенсорным слайдом в UIViewController - PullRequest
2 голосов
/ 22 июня 2010

Я бы хотел обрабатывать касания (в частности, горизонтальный слайд) в подклассе UIViewController, который я делал, но проблема в том, что представление контроллера содержит UIScrollView, который покрывает весь экран, поэтому события "touchesBegan:" и "touchesEnded:"никогда не вызывается в моем контроллере.Вид прокрутки прокручивается только по вертикали.

Как лучше всего справиться с этими событиями?Сделайте так, чтобы мой UIViewController также наследовал от UIScrollView и обрабатывал касания по мере необходимости (и удалял текущее представление прокрутки), или использовал подкласс UIScrollView вместо моего текущего представления прокрутки, который будет вызывать метод делегата для случаев, в которых я нуждаюсь?Или, может быть, есть другой способ?

Вот мой текущий код:

// View creation and adding to parent
NewViewController* newViewController = [[newViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
[self.view addSubview:newViewController.view];

// NewViewController.h
@interface NewViewController : UIViewController {
    IBOutlet UIScrollView*  scrollView;

    // other outlets and properties
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;

В IB представление NewViewController содержит scrollView, который содержит все другие выходы (метки, кнопки) ...цель состоит в том, чтобы заставить scrollView NewViewController вызывать методы touchViewBegan и touchesEnded в NewViewController.

Обновление: ScrollViewSuite мне очень помогло понять, как обрабатываются обратные вызовы касаний.UIScrollView вызывает их только тогда, когда касания не заставляют его прокручиваться.

Итак, три случая:

  • Наклонный слайд (даже слегка, как только появляется полоса прокрутки): нетtouches метод называется
  • Совершенно горизонтальный слайд (полоса прокрутки не отображается): touchesBegan, touchesMoved и touchesEnded называются
  • Любое касание, которое не вызывает прокрутки (касание без перемещения или горизонтальное перемещение) с последующим слегка вертикальным скольжением: вызываются touchesBegan, touchesMoved и touchesCancelled;

Можно отменить касания, установив UIScrollViewcanCancelContentTouches до FALSE, но, очевидно, это работает только в том случае, если был вызван touchesBegan, что означает, что методы касания все равно не будут вызываться для первого случая.

Но UIScrollView имеет свойство с именем delaysContentTouchesкоторый установлен на TRUE по умолчанию и заставляет его немного подождать, когда начинается касание, чтобы увидеть, заставит ли его прокручиваться.Если для этого параметра установлено значение FALSE, методы касания вызываются, как только начинается касание, и позволяют подклассам обрабатывать их по своему желанию.

TL; DR: То, что кажетсяСамый простой способ для меня (если вы не можете использовать UIGestureRecognizer) - это создать подкласс UIScrollView, установить для его свойства delayContentTouches значение FALSE и переопределить функции касания (touchesShouldBegin / touchesShouldCancel, а также * 1051).* / touchesMoved ...) в соответствии с вашими потребностями.

Ответы [ 2 ]

6 голосов
/ 22 июня 2010

Если вы создаете для iPhone OS 3.2 или выше, вы можете использовать объекты Gesture Recognizer. Из вашего описания это звучит так, как будто вам нужен UIPanGestureRecognizer или UISwipeGestureRecognizer Создайте соответствующий объект, добавьте его в представление вашего viewController с помощью метода [addGestureRecognizer:] и реализуйте методы делегата в вашем viewController.

Для справки:
Руководство по обработке событий iPhone: распознаватели жестов
Справочник по UIGestureRecognizer (абстрактный суперкласс)
Справочник по протоколу UIGestureRecognizerDelegate

1 голос
/ 22 июня 2010

Ваше представление viewController должно быть подпредставлением UIScrollView. Создайте UIScrollView add как подвид окна, затем создайте экземпляр вашего viewController с ползунком и добавьте его в подпредставление scrollView.

UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:[window bounds]];
[window addSubView:scrollView];
UIViewController *vc = [[UIViewController alloc] initWithNibNamed:@"MyVC" bundle:nil];
[scrollView addSubView:[vc view]];

У меня есть подозрение, что вы не получаете события в результате отсутствия соединений в IB или что scrollView пересылает события в суперпредставление представления newViewController.

В документации Apple для свойства UIResponder nextResponder.

Класс UIResponder не сохраняет и не устанавливает следующий респондент автоматически, вместо этого он возвращает nil по умолчанию. Подклассы должны переопределить этот метод для установки следующего респондента. UIView реализует этот метод, возвращая объект UIViewController, который управляет им (если он есть) или его суперпредставлением (если это не так); UIViewController реализует метод, возвращая суперпредставление своего представления; UIWindow возвращает объект приложения, а UIApplication возвращает nil.

Несколько вещей, чтобы попробовать.

  1. В NewViewController.m переопределить canBecomeFirstResponder
    
    - (BOOL)canBecomeFirstResponder
    {
        return YES;
    }
    
  2. Поскольку вы просто добавляете свое новое представление в качестве подпредставления вместо использования навигации или модальных представлений, убедитесь, что суперпредставление newViewController больше не является первым респондентом. Добавлять:
    
    // View creation and adding to parent
    NewViewController* newViewController = [[newViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
    [self.view addSubview:newViewController.view];
    [self.view resignFirstResponder];
    
  3. Убедитесь, что представление `NextViewController`` связано с владельцем файла в IB.
  4. Убедитесь, что свойство userInteractionEnabled имеет значение YES для представления

Посмотрите также пример кода ScrollViewSuite . Я заметил, что контроллер, содержащий представление, которое получает события от scrollView, реализует методы делегата для представления. Подход, который вы можете попробовать, заключается в создании подклассов представлений внутри scrollView и делегировании обработки событий вашему контроллеру в соответствии с примером кода.

Есть также образцы для новых UIGesturizers, обсужденных в других ответах. Обратите внимание, что гостюризаторы добавляются к представлениям, а обработка гостюризаторов делегируется другому объекту (обычно это контроллер представления)

Вы указали, что кнопки и метки добавляются как подпредставления прокрутки в IB. Кажется, вы должны иметь UIView в качестве контейнера для ваших кнопок и меток. Просто мысль, которую я не могу понять из фрагмента кода.

UIScrollView
  -> UIView
      ->UIButton
      ->UILabel
      ..
      ..
...