Зупинити 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
Це виправлення, здається, працює тільки в моєму ОС 4.1 Симулятор, а не в моїй ОС 3.1.3 iPhone. Хтось знає, чи працює ця поправка лише на певних версіях ОС?
Dan J

@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
як сказав Джесседк, це зупинить вертикальне прокручування, а не лише підстрибування. це означає, що якщо у вас є 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: НЕТ]; і Apple сказав, що це приватний API, а тому відхилив його; я збираюся знову подати заявку, але використовую "userInteractionEnabled: NO", оскільки мені не потрібні активні посилання в додатку.
Веру

UIWebView успадковує від UIView. UIView має перегляди властивостей. Що тут приватного? Все це ви можете знайти на developer.apple.com
Валерій Павлов

3
У мене є що-небудь на зразок 4-х додатків у appstore, використовуючи це. Ви з додаткової причини відхилили ваш додаток. це не приватний API.
Zigglzworth

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

17

У SDK iOS 5 ви можете отримати доступ до подання прокрутки, пов’язаного з веб-переглядом безпосередньо, а не ітерації через його підгляди.

Отже, щоб вимкнути "підстрибування" у вікні прокрутки, ви можете використовувати:

myWebView.scrollView.bounces = NO;

Дивіться посилання на клас UIWebView .

(Однак якщо вам потрібно підтримувати версії SDK до 5.0, слід дотримуватися порад Mirek Rusin .)



9

Увага. Я використовував setAllowsRubberBanding: у своєму додатку, і Apple відхилила його, заявивши, що непублічні функції API заборонені (цитуйте: 3.3.1)



3

Метод Бреда працював на мене. Якщо ви використовуєте його, можливо, ви хочете зробити його трохи безпечнішим.

id scrollView = [yourWebView.subviews objectAtIndex: 0];
if ([scrollView respondsToSelector: @selector (setAllowsRubberBanding :)])
{
    [scrollView performSelector: @selector (setAllowsRubberBanding :) withObject: NO];
}

Якщо яблуко щось змінить, відмов повернеться - але принаймні ваш додаток не вийде з ладу.


3

На iOS5, лише якщо ви плануєте дозволити користувачам масштабувати вміст веб-перегляду (ei: подвійне торкання), налаштування відмов недостатньо. Вам також потрібно встановити властивості alwaysBounceHorizontal і alwaysBounceVertical на NO, інакше коли вони зменшаться (ще один подвійний торкніться ...) за замовчуванням, він знову відскочить.


2

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


1
Насправді це досить погано, тому що якщо Apple коли-небудь змінить внутрішнє середовище UIWebView, цей злом може зламатися.
bpapa

2

Мені здається, що UIWebView має UIScrollView. Для цього можна використовувати документовані API, але підстрибування встановлюється в обох напрямках, а не окремо. Це в документах API. UIScrollView має властивість відмов, тому щось подібне працює (не знаю, чи є більше одного перегляду прокрутки):

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: якщо ви використовуєте його в Interface Builder
  • коли ви спочатку створюєте веб-перегляд, його розмір вмісту завжди такий самий, як розмір кадру перегляду. Після прокрутки в Інтернеті розмір вмісту відображає розмір фактичного веб-вмісту всередині перегляду. Щоб обійти це, я зробив щось покірне - викликав -setContentOffset: CGPointMake (0,1) анімований: ТАК, щоб примусити непомітні зміни, які встановлять належний розмір вмісту веб-перегляду.

2

Натрапив на це, шукаючи відповідь, і я врешті-решт просто пощастив за власною відповіддю, возившись. я зробила

[[webview scrollView] setBounces:NO];

і це спрацювало.


2

Це працювало для мене, і дуже красиво (я використовую фонегап з webView)

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

або

[[webView scrollView] setScrollEnabled:NO];

1

Я спробував дещо інший підхід, щоб запобігти прокрученню та відскоку об’єктів UIWebView : додавання розпізнавача жестів для зміни інших жестів.

Здається, UIWebView або його підрозділ прокрутки використовує власний розпізнавальник жестів панорами для виявлення прокрутки користувача. Але згідно з документацією Apple, існує законний спосіб перекрити один розпізнавальник жестів іншим. Протокол UIGestureRecognizerDelegate має метод gestureRecognizer: shouldRecognizeSim istovremenoWithGestureRecognizer: - який дозволяє контролювати поведінку будь-яких розпізнавальників жестів, що стикаються.

Отже, те, що я зробив

у методі 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має бути a UIScrollView. Встановіть його scrollEnabledвластивість, NOа веб-перегляд буде повністю відключений.

Примітка. Це технічно за допомогою приватного API, і тому ваш додаток може бути відхилено або збій у майбутніх випусках ОС. Використовуйте @tryіrespondsToSelector


Я спробував це, і він помиляється, коли я його спробую ... Дивно, я можу отримати доступ і встановити scrollView.bounces (без ефекту), але коли я намагаюся встановити scrollEnabled, він помиляється ...
Brad Parks

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

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

0

Загляньте у bouncesвласність с UIScrollView. Виправте документи Apple:

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

Переконайтеся, що ви користуєтесь правом UIScrollView. Я не впевнений, як виглядає ієрархія для UIWebView, але подання прокрутки може бути батьківським, а не дитиною UIWebView.


0

Щоб вимкнути UIWebViewпрокрутку, ви можете використовувати такий рядок коду:

[ObjWebview setUserInteractionEnabled:FALSE];

У цьому прикладі ObjWebviewє тип UIWebView.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.