Остановить «подпрыгивание» UIWebView по вертикали?


225

Кто-нибудь знает, как остановить вертикальный отскок UIWebView? Я имею в виду, когда пользователь касается экрана своего iphone, тянет его пальцем вниз, и веб-просмотр показывает пустое место над загруженной веб-страницей?

Я рассмотрел следующие возможные решения, но ни одно из них не помогло мне:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/996-turn-off-scrolling-bounces-uiwebview.html

http://forums.macrumors.com/showthread.php?t=619534

Как мне остановить UIScrollView от горизонтального подпрыгивания?


1
Я надеюсь, что вы рассмотрели возможные последствия отключения этой функции. Это там по причине. Тем не менее, мне тоже интересно, как ты это сделаешь.
Майкл Харен

То, как я встроил его в свое приложение, кажется, что оно выглядит безразлично с некоторыми другими элементами представления, которые у меня есть, и единственный раз, когда он не появляется, это когда происходит отскок ... Хотя, безусловно, хороший момент!
Брэд Паркс

Ответы:


424
for (id subview in webView.subviews)
  if ([[subview class] isSubclassOfClass: [UIScrollView class]])
    ((UIScrollView *)subview).bounces = NO;

... кажется, работает нормально.

Он также будет принят в App Store.

Обновление : в iOS 5.x + есть более простой способ - UIWebViewесть scrollViewсвойство, поэтому ваш код может выглядеть так:

webView.scrollView.bounces = NO;

То же самое и для WKWebView.


Оно работает. Подклассы не требуются, и если Apple когда-либо изменит иерархию UIWebView, это не должно привести к сбою.
leolobato

2
Это исправление работает только в моем симуляторе OS 4.1, а не в iPhone OS 3.1.3. Кто-нибудь знает, работает ли это исправление только на определенных версиях ОС?
Дэн Джей

@MirukRusin - Как вы можете гарантировать, что это приложение будет принято на основе трех строк кода? : P
Моше

@Mirek - Ты упустил мою точку зрения. Откуда вы знаете, что больше ничего в приложении не получит отклонения?
Моше

6
Это работало нормально для меня. Для удобства я добавил категорию, UIWebViewчтобы я мог звонить [webView setBounces:NO]куда угодно.
Zekel

46

Я смотрел на проект, который облегчает создание веб-приложений как полноценных устанавливаемых приложений на iPhone под названием QuickConnect , и нашел решение, которое работает, если вы не хотите, чтобы ваш экран вообще прокручивался, что в моем случае Я не

В вышеупомянутом сообщении о проекте / блоге они упоминают функцию javascript, которую вы можете добавить, чтобы отключить подпрыгивание, что по сути сводится к следующему:

    document.ontouchmove = function(event){
        event.preventDefault();
    }

Если вы хотите узнать больше о том, как они это реализуют, просто скачайте QuickConnect и проверьте его .... Но в основном все, что он делает, это вызывает этот javascript при загрузке страницы ... Я попытался просто поместить его в заголовок моего документа, и, кажется, работает нормально.


Этот ответ является правильным способом остановить вертикальную прокрутку содержимого в UIWebView.
Jessedc

3
Вы могли бы дать полный ответ, во-первых, я не хочу загружать весь исходный код другого приложения, и я даже не могу его найти. Ваш ответ основан на том, что другой веб-сайт совпадает с вашим ответом.
Джонатан.

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

3
как сказал Jessedc, это остановит вертикальную прокрутку, а не только подпрыгивание. это означает, что если у вас есть div или около того, что требует прокрутки, он не будет прокручиваться.
воспоминание

18

Ну, все, что я сделал для достижения этой цели:

UIView *firstView = [webView.subviews firstObject];

if ([firstView isKindOfClass:[UIScrollView class]]) {

    UIScrollView *scroll = (UIScrollView*)firstView;
   [scroll setScrollEnabled:NO];  //to stop scrolling completely
   [scroll setBounces:NO]; //to stop bouncing 

}

У меня отлично работает ... Кроме того, ответ на этот вопрос отмечен галочкой, который Apple отклонит, если вы используете его в своем приложении для iphone.


3
Это самый лучший и самый простой способ. Это должен быть принятый ответ! +1
PostCodeism

3
Не делайте этого - мое приложение было отклонено за использование первой строки. Потратил так много времени для меня. я использовал [[webView.subviews lastObject] setScrollEnabled: NO]; и apple сказал, что это частный API и поэтому отверг его; Я собираюсь повторить сейчас, но использовал «userInteractionEnabled: NO», так как мне не нужны какие-либо активные ссылки в приложении.
Veeru

UIWebView наследует от UIView. У UIView есть свойства subviews. Что здесь частного? Все это вы можете найти на developer.apple.com
Валерий Павлов

3
У меня есть что-то вроде 4 приложений в магазине приложений, использующих это. Ваше приложение было явно отклонено по другой причине. это не частный API.
Зигглсворт,

4
Это действительно не очень хорошая идея. Вы полагаетесь на тот факт, что UIScrollViewэто первое подпредставление, UIWebViewкоторое вполне может иметь место на данный момент, но это может легко измениться в будущих (даже незначительных) обновлениях iOS или определенных конфигураций. Вы должны действительно выполнить forитерацию, subviewsчтобы действительно найти UIScrollView(это действительно не так уж много работы, и, по крайней мере, вы гарантированно получите UIScrollViewи не разбиваете свою программу ...
Джонатан Эллис,

17

В iOS 5 SDK вы можете получить доступ к представлению прокрутки, связанному с веб-представлением, напрямую, а не итерировать его подпредставления.

Таким образом, чтобы отключить «подпрыгивание» в представлении прокрутки, вы можете использовать:

myWebView.scrollView.bounces = NO;

Смотрите описание класса UIWebView .

(Однако, если вам нужно поддерживать версии SDK до 5.0, вы должны следовать совету Мирека Русина .)



9

Предупреждение. Я использовал setAllowsRubberBanding: в моем приложении Apple отклонила его, заявив, что непубличные функции API недопустимы (цитируем: 3.3.1)



3

Метод Брэда работал на меня. Если вы используете его, вы можете сделать его немного безопаснее.

id scrollView = [yourWebView.subviews objectAtIndex: 0];
если ([scrollView RespondsToSelector: @selector (setAllowsRubberBanding :)])
{
    [scrollView executeSelector: @selector (setAllowsRubberBanding :) withObject: NO];
}

Если яблоко что-то изменит, отскок вернется, но по крайней мере ваше приложение не рухнет.


3

На iOS5 только в том случае, если вы планируете позволить пользователям увеличивать содержимое веб-просмотра (например, двойное нажатие), настройки отказов недостаточно. Вам также необходимо установить для свойств AlwaysBounceHor Horizontal и AlwaysBounceVertical значение NO, в противном случае, когда они уменьшаются (еще один двойной щелчок ...) по умолчанию, они снова будут отскакивать.


2

Я просмотрел коллекцию подпредставлений UIWebView и установил их фоны [UIColor blackColor], того же цвета, что и фон веб-страницы. Вид будет по-прежнему подпрыгивать, но не будет отображать этот уродливый темно-серый фон.


1
На самом деле это довольно плохо, потому что если Apple когда-либо изменит внутреннее содержимое UIWebView, этот хак может сломаться.
бапа

2

Мне кажется, что UIWebView имеет UIScrollView. Для этого вы можете использовать документированные API-интерфейсы, но отскок устанавливается для обоих направлений, а не по отдельности. Это в документации по API. UIScrollView имеет свойство bounce, поэтому что-то вроде этого работает (не знаю, существует ли более одного scrollview):

NSArray *subviews = myWebView.subviews;
NSObject *obj = nil;
int i = 0;
for (; i < subviews.count ; i++)
{
    obj = [subviews objectAtIndex:i];

    if([[obj class] isSubclassOfClass:[UIScrollView class]] == YES)
    {
        ((UIScrollView*)obj).bounces = NO;
    }
}

2

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

@class CustomWebView : UIWebview
...

- (id) initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
// WebViews are subclass of NSObject and not UIScrollView and therefore don't allow customization.
// However, a UIWebView is a UIScrollViewDelegate, so it must CONTAIN a ScrollView somewhere.
// To use a web view like a scroll view, let's traverse the view hierarchy to find the scroll view inside the web view.
for (UIView* v in self.subviews){
    if ([v isKindOfClass:[UIScrollView class]]){
        _scrollView = (UIScrollView*)v; 
        break;
    }
}
return self;

}

Затем, когда вы создаете пользовательское веб-представление, вы можете отключить подпрыгивание с помощью:

customWebView.scrollView.bounces = NO; //(or customWebView.scrollView.alwaysBounceVertically = NO)

Это отличный универсальный способ создания веб-представления с настраиваемым режимом прокрутки. Есть только несколько вещей, на которые стоит обратить внимание:

  • как и в любом представлении, вам также необходимо переопределить - (id) initWithCoder: если вы используете его в Интерфейсном Разработчике
  • когда вы изначально создаете веб-представление, размер его содержимого всегда совпадает с размером фрейма представления. После прокрутки в Интернете размер содержимого соответствует размеру реального веб-содержимого в представлении. Чтобы обойти это, я сделал что-то хакерское - вызвал -setContentOffset: CGPointMake (0,1) animated: YES, чтобы вызвать незаметное изменение, которое установит правильный размер содержимого веб-представления.

2

Наткнулся на это в поисках ответа, и я, в конце концов, просто ударил свой собственный ответ, возиться с ним. я сделал

[[webview scrollView] setBounces:NO];

и это сработало.


2

Это работало для меня, и прекрасно тоже (я использую PhoneGap с WebView)

[[webView.webView scrollView] setScrollEnabled:NO];

или

[[webView scrollView] setScrollEnabled:NO];

1

Я попробовал немного другой подход, чтобы предотвратить прокрутку и отскок объектов UIWebView : добавление распознавателя жестов для переопределения других жестов.

Похоже, что UIWebView или его подпредставление прокрутки использует собственный распознаватель жестов панорамирования для обнаружения пользовательской прокрутки. Но согласно документации Apple, существует законный способ заменить один распознаватель жестов другим. Протокол UIGestureRecognizerDelegate имеет метод gestRecognizer: shouldRecognizeSim одновременноouslyWithGestureRecognizer: -, который позволяет контролировать поведение любых распознавателей столкновения жестов.

Итак, что я сделал

в методе viewDidLoad контроллера представления:

// Install a pan gesture recognizer                                                                                        // We ignore all the touches except the first and try to prevent other pan gestures                                                     
// by registering this object as the recognizer's delegate                                                                                        
UIPanGestureRecognizer *recognizer;                                                                                                               
recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanFrom:)];                                                   
recognizer.delegate = self;                                                                                                                       
recognizer.maximumNumberOfTouches = 1;                                                                                                            
[self.view addGestureRecognizer:recognizer];                                                                                                          
self.panGestureFixer = recognizer;                                                                                                                  
[recognizer release]; 

затем метод переопределения жестов:

// Control gestures precedence                                                                                                                            
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer                                                                                        
        shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer                                                  
{                                                                                                                                                         
        // Prevent all panning gestures (which do nothing but scroll webViews, something we want to disable in                                          
        // the most painless way)                                                                                                                         
        if ([otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]])                                                                        
        {
            // Just disable every other pan gesture recognizer right away                                                                             
            otherGestureRecognizer.enabled = FALSE;
        }                                                                                                                                                  
        return NO;                                                                                                                                        
}              

Конечно, этот метод делегата может быть более сложным в реальном приложении - мы можем выборочно отключить другие распознаватели, анализируя otherGestureRecognizer.view и принимая решение на основе того, что это за представление.

И, наконец, ради полноты, метод, который мы зарегистрировали как обработчик панорамирования:

- (void)handlePanFrom:(UIPanGestureRecognizer *)recognizer 
{ 
    // do nothing as of yet
}

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

Пока что я просто экспериментирую со всем этим, и кажется, что он работает более или менее так, как я этого хочу. Я пока не пытался отправить какие-либо приложения в iStore. Но я считаю, что до сих пор я не использовал ничего недокументированного ... Если кто-то найдет это иначе, пожалуйста, сообщите мне.





0

Одним из подпредставлений UIWebViewдолжно быть UIScrollView. Установите для этого scrollEnabledсвойства значение, NOи прокрутка будет полностью отключена.

Примечание: технически это использует частный API, и, следовательно, ваше приложение может быть отклонено или аварийно завершено в будущих версиях ОС. Используйте @tryиrespondsToSelector


Я попробовал это, и он ошибается, когда я пытаюсь ... Странно, я могу получить доступ и установить scrollView.bounces (без эффекта), но когда я пытаюсь установить scrollEnabled, он выходит из строя ...
Брэд Паркс,

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

Я сделал это в приложении для iPad (не iPhone) под управлением iOS 3.2 и смог получить UIScrollView из моего UIWebView. Я успешно настроил это представление так, чтобы оно изменило не только подпрыгивающее поведение, чтобы я мог засвидетельствовать эту работу на iPad. Мое приложение не прошло через магазин приложений, но я не думаю, что здесь будут проблемы с недокументированными API. Умная часть этого решения заключается в том, что вы просто пересекаете иерархию UIView и используете UIScrollView - оба из них совершенно кошерны.
Рольф Хендрикс

0

Посмотрите в bouncesсобственность UIScrollView. Quot Apple документы:

Если значение свойства YES(по умолчанию), представление прокрутки отскакивает, когда оно встречает границу содержимого. Визуальный отскок означает, что прокрутка достигла края контента. Если значение равно NO, прокрутка немедленно останавливается на границе содержимого без отскока.

Убедитесь, что вы используете право UIScrollView. Я не уверен, как выглядит иерархия для a UIWebView, но представление прокрутки может быть родительским, а не дочерним UIWebView.


0

Чтобы отключить UIWebViewпрокрутку, вы можете использовать следующую строку кода:

[ObjWebview setUserInteractionEnabled:FALSE];

В этом примере ObjWebviewимеет тип UIWebView.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.