UIScrollView горизонтальный пейджинг, как вкладки Mobile Safari

Mobile Safari позволяет вам переключаться между страницами, введя вид горизонтального представления подкачки UIScrollView с элементом управления страницы внизу.

Я пытаюсь воспроизвести это конкретное поведение, когда прокручиваемый по горизонтали UIScrollView показывает часть содержимого следующего представления.

Пример Apple: PageControl показывает, как использовать UIScrollView для горизонтального поискового вызова, но все представления занимают всю ширину экрана.

Как я могу получить UIScrollView для отображения некоторого содержимого следующего вида, например, для мобильного Safari?

UIScrollView с включенным пейджингом будет останавливаться на кратность его ширины (или высоты). Итак, первый шаг – выяснить, насколько широки вы хотите, чтобы ваши страницы были. Сделайте ширину UIScrollView . Затем установите размеры вашего subview, насколько они нужны вам, и установите их центры на основе кратных ширине UIScrollView .

Затем, так как вы хотите увидеть другие страницы, конечно, установите для clipsToBounds NO значение NO как указано в mhjoy. Теперь уловкой становится заставить ее прокручивать, когда пользователь начинает drag and drop за пределы frameworks кадра UIScrollView . Мое решение (когда мне нужно было это сделать совсем недавно) было следующим:

Создайте подclass UIView (т.е. ClipView ), который будет содержать UIScrollView и его подпункты. По существу, он должен иметь структуру того, что вы предположили бы, что UIScrollView будет иметь нормальные обстоятельства. Поместите UIScrollView в центр ClipView . Убедитесь, что ClipView clipsToBounds установлен в YES если его ширина меньше, чем у его родительского представления. Кроме того, ClipView нуждается в ссылке на UIScrollView .

Последний шаг – переопределить - (UIView *)hitTest:withEvent: внутри ClipView .

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return [self pointInside:point withEvent:event] ? scrollView : nil; } 

Это в основном расширяет область касания UIScrollView до кадра его родительского представления, именно то, что вам нужно.

Другим вариантом будет подclass UIScrollView и переопределить его - (BOOL)pointInside:(CGPoint) point withEvent:(UIEvent *) event , однако для выполнения - (BOOL)pointInside:(CGPoint) point withEvent:(UIEvent *) event вам все равно понадобится вид контейнера, и может быть сложно определить, когда для возврата YES основанного только на кадре UIScrollView .

ПРИМЕЧАНИЕ. Вы также должны взглянуть на hitTest от Juri Pakaste : withEvent: модификация, если у вас возникли проблемы с взаимодействием пользователя subview.

Решение ClipView выше работало для меня, но я должен был сделать другое -[UIView hitTest:withEvent:] . Версия Ed Marty не обеспечивала взаимодействие пользователя с вертикальными прокрутками, которые у меня внутри горизонтального.

Для меня работала следующая версия:

 -(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event { UIView* child = nil; if ((child = [super hitTest:point withEvent:event]) == self) return self.scrollView; return child; } 

Установите размер frameworks scrollView в качестве размера ваших страниц:

 [self.view addSubview:scrollView]; [self.view addGestureRecognizer:mainScrollView.panGestureRecognizer]; 

Теперь вы можете панорамировать на self.view , и содержимое scrollView будет прокручиваться.
Также используйте scrollView.clipsToBounds = NO; для предотвращения отсечения содержимого.

Я закончил работу с пользовательским UIScrollView, поскольку это был самый быстрый и простой способ, который мне показался. Тем не менее, я не видел никакого точного кода, так что я бы разделил его. Мои потребности были для UIScrollView, у которого был небольшой контент, и поэтому сам UIScrollView был мал, чтобы добиться воздействия поискового вызова. Как говорится в сообщениях, вы не можете пронестись. Но теперь можешь.

Создайте class CustomScrollView и подclass UIScrollView. Тогда все, что вам нужно сделать, это добавить это в файл .m:

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { return (point.y >= 0 && point.y <= self.frame.size.height); } 

Это позволяет вам перемещаться из стороны в сторону (по горизонтали). Отрегулируйте границы, чтобы настроить зону касания / прокрутки. Наслаждайтесь!

Я сделал еще одну реализацию, которая может автоматически возвращать scrollview. Таким образом, не нужно иметь IBOutlet, который ограничивает повторное использование в проекте.

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if ([self pointInside:point withEvent:event]) { for (id view in [self subviews]) { if ([view isKindOfClass:[UIScrollView class]]) { return view; } } } return nil; } 

У меня есть еще одна потенциально полезная модификация для реализации ClipView hitTest. Мне не нравилось предоставлять ссылку на UIScrollView для ClipView. Моя реализация ниже позволяет вам повторно использовать class ClipView для расширения области тестирования при тестировании, и не нужно указывать ссылку.

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { if (([self pointInside:point withEvent:event]) && (self.subviews.count >= 1)) { // An extended-hit view should only have one sub-view, or make sure the // first subview is the one you want to expand the hit test for. return [self.subviews objectAtIndex:0]; } return nil; } 

Я реализовал вышеперечисленное предложение выше, но UICollectionView я использовал что-то из кадра, чтобы отключиться от экрана. Это привело к тому, что соседние ячейки выходили за пределы, когда пользователь прокручивал их, что не было идеальным.

То, что я закончил, – это эмуляция поведения scrollview, добавив метод ниже к делегату (или UICollectionViewLayout ).

 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity { if (velocity.x > 0) { proposedContentOffset.x = ceilf(self.collectionView.contentOffset.x / pageSize) * pageSize; } else { proposedContentOffset.x = floorf(self.collectionView.contentOffset.x / pageSize) * pageSize; } return proposedContentOffset; } 

Это позволяет полностью исключить делегирование действия салфетки, что также является бонусом. UIScrollViewDelegate имеет аналогичный метод scrollViewWillEndDragging:withVelocity:targetContentOffset: который можно использовать для отображения UITableViews и UIScrollViews.

Включить события срабатывания на дочерние представления прокрутки, поддерживая технику этого вопроса SO. Использует ссылку на просмотр прокрутки (self.scrollView) для удобства чтения.

 - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = nil; NSArray *childViews = [self.scrollView subviews]; for (NSUInteger i = 0; i < childViews.count; i++) { CGRect childFrame = [[childViews objectAtIndex:i] frame]; CGRect scrollFrame = self.scrollView.frame; CGPoint contentOffset = self.scrollView.contentOffset; if (childFrame.origin.x + scrollFrame.origin.x < point.x + contentOffset.x && point.x + contentOffset.x < childFrame.origin.x + scrollFrame.origin.x + childFrame.size.width && childFrame.origin.y + scrollFrame.origin.y < point.y + contentOffset.y && point.y + contentOffset.y < childFrame.origin.y + scrollFrame.origin.y + childFrame.size.height ){ hitView = [childViews objectAtIndex:i]; return hitView; } } hitView = [super hitTest:point withEvent:event]; if (hitView == self) return self.scrollView; return hitView; } 

Добавьте это в представление вашего ребенка, чтобы зафиксировать событие касания:

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 

(Это вариант для решения user1856273. Убирается для удобства чтения и исправляется ошибка Bartserk. Я думал о редактировании ответа пользователя1856273, но это было слишком большое изменение.)

моя версия Нажатие кнопки, лежащей на свитке – work =)

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView* child = nil; for (int i=0; i<[[[[self subviews] objectAtIndex:0] subviews] count];i++) { CGRect myframe =[[[[[self subviews] objectAtIndex:0] subviews]objectAtIndex:i] frame]; CGRect myframeS =[[[self subviews] objectAtIndex:0] frame]; CGPoint myscroll =[[[self subviews] objectAtIndex:0] contentOffset]; if (myframe.origin.x < point.x && point.x < myframe.origin.x+myframe.size.width && myframe.origin.y+myframeS.origin.y < point.y+myscroll.y && point.y+myscroll.y < myframe.origin.y+myframeS.origin.y +myframe.size.height){ child = [[[[self subviews] objectAtIndex:0] subviews]objectAtIndex:i]; return child; } } child = [super hitTest:point withEvent:event]; if (child == self) return [[self subviews] objectAtIndex:0]; return child; } 

но только [[self subviews] objectAtIndex: 0] должен быть прокруткой

  • Обнаружить, если некоторые UIView были затронуты среди других UIViews
  • Перемещение UIView (изображение и текст)
  • Как использовать UIButton в качестве тумблера
  • Текстовые библиотеки для iPhone
  • Как исправить «неудачную проверку кода» проекта iPhone?
  • Когда происходит освобождение связанного объекта?
  • Как создать UITableViewCell с прозрачным фоном
  • Управление несколькими асинхронными соединениями NSURLConnection
  • Основной ключ первичных данных
  • Как обнаружить, когда UIScrollView завершил прокрутку
  • Хранение UIImage в базовых данных с новым флагом внешнего хранилища
  • Interesting Posts

    Вопрос о поведении C для неподписанного целого нижнего streamа

    Как можно объединить две строки?

    Смарт-карты для хранения ключей gpg / ssh (Linux) – что мне нужно?

    Должны ли быть объявлены методы в интерфейсе Java с модификатором открытого доступа или без него?

    Обновление Windows 8.1 приводит к зеленому экрану смерти, зафиксированному только путем изменения пользователя

    Как читать и записывать файл в C #

    Как я могу поделиться Wi-Fi-соединением ноутбука через его порт Ethernet?

    ViewModels в ViewModelLocator MVVM Light

    Почему «dd conv = разреженный» не сэкономил место, как я ожидал?

    Конец файла в C ++

    Доступ к синтаксической ошибке SQL при использовании OleDbCommandBuilder

    Какие шрифты поддерживают приложения для iPhone?

    Весенняя безопасность: добавление «При успешном прослушивании событий входа в систему»

    Сравнение строк сходства в Java

    Как удалить файлы и папки, которые нельзя удалить?

    Давайте будем гением компьютера.