Bezdepbonusu7Программирование: статьи и ответы

Вопрос

IPhone - обработка сенсорного слайда в UIViewController

Автор вопроса: JukurrpaОтветов: 2

Я хотел бы обрабатывать прикосновения (в частности, горизонтальный слайд) в подклассе 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 для вызова методов touchesBegan и touchesEnded NewViewController.

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

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

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

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

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

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

  • Где вы устанавливаете свойство contentSize scrollView? falconcreek 23.06.2010
  • В представлении NewViewController в viewDidLoad. Я размещаю свои розетки в соответствии с их размером, а в конце устанавливаю высоту содержимого scrollView. Но с этой прокруткой кода проблема только в том, что методы касаний не вызываются. Jukurrpa 23.06.2010

iphonecocoa-touchuiscrollviewuiviewcontroller

Ответы

Ответ 1 · рейтинг 6 · Endemic

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

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

Ответ 2 · рейтинг 1 · falconcreek

Представление вашего viewController должно быть подвидом UIScrollView. Создайте UIScrollView add как subView окна, затем создайте экземпляр вашего viewController, у которого есть ползунок, и добавьте в subview 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 возвращает ноль.

Пара вещей, которые стоит попробовать.

  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 и делегировать обработку событий вашему контроллеру в соответствии с образцом кода.

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

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы