Hentikan UIWebView dari "memantul" secara vertikal?

225

Apakah ada yang tahu cara menghentikan UIWebView memantul secara vertikal? Maksud saya ketika pengguna menyentuh layar iphone mereka, menyeret jari mereka ke bawah, dan tampilan web menunjukkan tempat kosong di atas halaman web yang saya muat?

Saya telah melihat kemungkinan solusi berikut ini, tetapi tidak ada satupun yang bekerja untuk saya:

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

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

Bagaimana cara menghentikan UIScrollView memantul secara horizontal?

Taman Brad
sumber
1
Saya harap Anda telah mempertimbangkan implikasi kegunaan menonaktifkan fitur itu. Itu ada di sana karena suatu alasan. Yang mengatakan, saya ingin tahu juga, bagaimana Anda akan melakukannya.
Michael Haren
Cara saya menyematkannya di aplikasi saya, tampaknya tidak terlihat dengan beberapa elemen tampilan lain yang saya miliki, dan satu-satunya waktu itu tidak muncul begitu adalah ketika bouncing terjadi .... Pasti poin yang bagus!
Taman Brad

Jawaban:

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

... sepertinya bekerja dengan baik.

Ini akan diterima di App Store juga.

Pembaruan : di iOS 5.x + ada cara yang lebih mudah - UIWebViewmemiliki scrollViewproperti, sehingga kode Anda dapat terlihat seperti ini:

webView.scrollView.bounces = NO;

Sama berlaku untuk WKWebView.

Mirek Rusin
sumber
Berhasil. Tidak diperlukan subklasifikasi dan jika Apple pernah mengubah hierarki UIWebView, itu seharusnya tidak crash.
leolobato
2
Perbaikan ini tampaknya hanya berfungsi di OS 4.1 Simulator saya, bukan pada OS 3.1.3 iPhone saya. Adakah yang tahu jika perbaikan ini hanya berfungsi pada versi OS tertentu?
Dan J
@MirukRusin - Bagaimana Anda dapat menjamin bahwa aplikasi ini akan diterima berdasarkan tiga baris kode? : P
Moshe
@ Mirek - Anda melewatkan poin saya. Bagaimana Anda tahu bahwa tidak ada hal lain di aplikasi yang akan ditolak?
Moshe
6
Ini bekerja dengan baik untuk saya. Untuk kenyamanan, saya menambahkan kategori UIWebViewagar saya dapat menelepon ke [webView setBounces:NO]mana pun saya mau.
zekel
46

Saya sedang melihat sebuah proyek yang membuatnya mudah untuk membuat aplikasi web sebagai aplikasi yang dapat diinstal penuh pada iPhone yang disebut QuickConnect , dan menemukan solusi yang berfungsi, jika Anda tidak ingin layar Anda dapat digulir sama sekali, yang dalam kasus saya Saya tidak melakukannya.

Dalam posting proyek / blog yang disebutkan di atas, mereka menyebutkan fungsi javascript yang dapat Anda tambahkan untuk mematikan bouncing, yang pada dasarnya bermuara pada ini:

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

Jika Anda ingin melihat lebih lanjut tentang bagaimana mereka mengimplementasikannya, cukup unduh QuickConnect dan periksa .... Tapi pada dasarnya yang dilakukannya hanyalah memanggil javascript itu pada pemuatan halaman ... Saya mencoba meletakkannya di kepala dokumen saya, dan tampaknya berfungsi dengan baik.

Taman Brad
sumber
Jawaban ini adalah cara yang benar untuk menghentikan pengguliran vertikal konten dalam UIWebView.
Jessedc
3
Anda dapat memberikan seluruh jawaban, pertama-tama saya tidak ingin mengunduh seluruh kode sumber dari aplikasi lain, dan saya bahkan tidak dapat menemukannya. Jawaban Anda bergantung pada situs web lain yang sama dengan ketika Anda menjawab.
Jonathan.
Jawaban ini & jawaban yang diterima di atas tampaknya diperlukan di kali. Dalam kasus saya, saya menemukan bahwa jika tampilan web belum dimuat, bounciness akan ada sampai JS di atas benar-benar dimuat ke dalam sistem. Jadi jawabannya sepertinya ini dan jawaban yang diterima di atas keduanya, kadang-kadang, diperlukan.
Kalle
3
seperti kata Jessedc, ini akan berhenti menggulir vertikal, tidak hanya memantul. itu berarti jika Anda memiliki div atau lebih yang memerlukan pengguliran, itu tidak akan menggulir.
memical
18

Yah semua yang saya lakukan untuk mencapai ini adalah:

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 

}

Bekerja dengan baik untuk saya ... Juga, jawaban untuk pertanyaan ini adalah yang akan ditolak oleh Apple jika Anda menggunakannya di aplikasi iphone Anda.

Zigglzworth
sumber
3
Ini adalah cara terbaik dan paling sederhana. Ini harus menjadi jawaban yang diterima! +1
PostCodeism
3
Jangan lakukan itu - aplikasi saya ditolak karena menggunakan baris pertama. Buang begitu banyak waktu untukku. saya menggunakan [[webView.subviews lastObject] setScrollEnabled: NO]; dan apel mengatakan itu adalah API pribadi dan karenanya menolaknya; Saya akan mengirim ulang sekarang tetapi menggunakan "userInteractionEnabled: TIDAK" karena saya tidak memerlukan tautan aktif di aplikasi.
Veeru
UIWebView mewarisi dari UIView. UIView memiliki subview properti. Apa yang pribadi di sini? Semua ini dapat Anda temukan di developer.apple.com
Valerii Pavlov
3
Saya memiliki sekitar 4 aplikasi di appstore yang menggunakan ini. Aplikasi Anda jelas ditolak karena alasan lain. ini bukan API pribadi.
Zigglzworth
4
Ini benar-benar bukan ide yang bagus. Anda mengandalkan fakta bahwa UIScrollViewini adalah subview pertama UIWebViewyang mungkin berlaku untuk saat ini tetapi ini dapat dengan mudah berubah di masa depan (bahkan minor) pembaruan untuk iOS atau konfigurasi tertentu. Anda harus benar-benar melakukan foriterasi subviewsuntuk benar-benar menemukan UIScrollView(itu sebenarnya tidak banyak pekerjaan dan setidaknya Anda dijamin untuk mendapatkan UIScrollViewdan tidak crash program Anda ...
Jonathan Ellis
17

Di iOS 5 SDK Anda dapat mengakses tampilan gulir yang terkait dengan tampilan web secara langsung daripada mengulang melalui subview-nya.

Jadi untuk menonaktifkan 'memantul' di tampilan gulir, Anda dapat menggunakan:

myWebView.scrollView.bounces = NO;

Lihat Referensi Kelas UIWebView .

(Namun jika Anda perlu mendukung versi SDK sebelum 5.0, Anda harus mengikuti saran Mirek Rusin .)

Jstr
sumber
12

Cepat 3

webView.scrollView.bounces = false
Ego Slayer
sumber
9

Peringatan. Saya menggunakan setAllowsRubberBanding: di aplikasi saya, dan Apple menolaknya, menyatakan bahwa fungsi API non-publik tidak diperbolehkan (cite: 3.3.1)

Raf
sumber
4

Di Swift untuk menonaktifkan bouncing

webViewObj.scrollView.bounces = false
Jugal K Balara
sumber
3

Metode Brad bekerja untuk saya. Jika Anda menggunakannya, Anda mungkin ingin membuatnya sedikit lebih aman.

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

Jika apel mengubah sesuatu, maka pantulan akan kembali - tetapi setidaknya aplikasi Anda tidak akan macet.

Gavin Maclean
sumber
3

Di iOS5 hanya jika Anda berencana untuk membiarkan pengguna memperbesar konten tampilan web (mis: ketuk dua kali) pengaturan bouncing tidak cukup. Anda perlu mengatur juga properti alwaysBounceHorizontal dan alwaysBounceVertical ke TIDAK, jika tidak mereka zoom-out (ketuk dua kali lain ...) ke default akan memantul lagi.

il Malvagio Dottor Prosciutto
sumber
2

Saya melintasi koleksi subview UIWebView dan mengatur latar belakangnya menjadi [UIColor blackColor], warna yang sama dengan latar belakang halaman web. Tampilan akan tetap terpental tetapi tidak akan menunjukkan latar belakang abu-abu gelap yang jelek.

pedro
sumber
1
Sebenarnya ini sangat buruk, karena jika Apple pernah mengubah internal UIWebView, peretasan ini bisa pecah.
bpapa
2

Sepertinya saya seperti UIWebView memiliki UIScrollView. Anda dapat menggunakan API yang terdokumentasi untuk ini, tetapi bouncing diatur untuk kedua arah, bukan secara individual. Ini ada dalam dokumen API. UIScrollView memiliki properti bouncing, jadi sesuatu seperti ini berfungsi (tidak tahu apakah ada lebih dari satu 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;
    }
}
spymaster
sumber
2

Saya kesal mengetahui bahwa UIWebView bukan tampilan gulir, jadi saya membuat subkelas kustom untuk mendapatkan tampilan gulir tampilan web. Suclass ini berisi tampilan gulir sehingga Anda dapat menyesuaikan perilaku tampilan web Anda. The punchlines dari kelas ini adalah:

@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;

}

Kemudian, saat Anda membuat tampilan web khusus, Anda dapat menonaktifkan bouncing dengan:

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

Ini adalah cara tujuan umum yang bagus untuk membuat tampilan web dengan perilaku pengguliran yang dapat disesuaikan. Ada beberapa hal yang harus diperhatikan:

  • seperti halnya tampilan apa pun, Anda juga harus mengganti - (id) initWithCoder: jika Anda menggunakannya di Interface Builder
  • ketika Anda awalnya membuat tampilan web, ukuran kontennya selalu sama dengan ukuran bingkai tampilan. Setelah Anda menggulir web, ukuran konten mewakili ukuran konten web aktual di dalam tampilan. Untuk menyiasatinya, saya melakukan sesuatu yang gila - memanggil -setContentOffset: CGPointMake (0,1) animasi: YES untuk memaksa perubahan yang tidak terlalu mencolok yang akan mengatur ukuran konten yang tepat dari tampilan web.
Rolf Hendriks
sumber
2

Datang mencari jawaban ini dan saya akhirnya hanya beruntung pada jawaban saya sendiri dengan mengacaukannya. aku melakukannya

[[webview scrollView] setBounces:NO];

dan itu berhasil.

Luke
sumber
2

Ini bekerja untuk saya, dan juga indah (saya menggunakan phonegap dengan webView)

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

atau

[[webView scrollView] setScrollEnabled:NO];
Jason G
sumber
1

Saya mencoba pendekatan yang sedikit berbeda untuk mencegah objek UIWebView bergulir dan memantul: menambahkan pengenal isyarat untuk mengesampingkan gerakan lain.

Tampaknya, UIWebView atau sub -scroller-nya menggunakan pengenal gerakan pan sendiri untuk mendeteksi pengguliran pengguna. Tetapi menurut dokumentasi Apple ada cara yang sah untuk mengganti satu pengenal isyarat dengan yang lain. Protokol UIGestureRecognizerDelegate memiliki metode gestureRecognizer: seharusnyaRecognizeSecara bersamaanWithGestureRecognizer: - yang memungkinkan untuk mengontrol perilaku setiap pengenal gesture yang bertabrakan.

Jadi, yang saya lakukan adalah

dalam metode viewDidLoad view controller:

// 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]; 

lalu, metode override gesture:

// 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;                                                                                                                                        
}              

Tentu saja, metode delegasi ini dapat membuat saya lebih kompleks dalam aplikasi nyata - kita dapat menonaktifkan pengenal lain secara selektif, menganalisis otherGestureRecognizer.view dan membuat keputusan berdasarkan tampilan apa itu.

Dan, akhirnya, demi kelengkapan, metode yang kami daftarkan sebagai pan handler:

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

itu bisa kosong jika semua yang kita inginkan adalah membatalkan pengguliran dan pemantulan tampilan web, atau itu bisa berisi kode kita sendiri untuk mengimplementasikan jenis gerakan panci dan animasi yang benar-benar kita inginkan ...

Sejauh ini saya hanya bereksperimen dengan semua hal ini, dan tampaknya berfungsi kurang lebih seperti yang saya inginkan. Saya belum mencoba mengirimkan aplikasi apa pun ke iStore. Tapi saya yakin saya belum menggunakan apa pun yang tidak terdokumentasi sejauh ini ... Jika ada yang menemukan sebaliknya, mohon informasikan kepada saya.

PP-RD
sumber
1

Inilah dua solusi potensial yang lebih baru. Rupanya, Anda dapat menggunakan jqtouch atau pastrykit untuk menonaktifkan pengguliran. Namun, saya belum dapat menggunakannya. Anda mungkin lebih kompeten.

mematikan pengguliran vertikal

menggali ke dalam pastrykit

cannyboy
sumber
0

Salah satu subview dari UIWebViewharus a UIScrollView. Setel scrollEnabledpropertinya NOdan tampilan web akan menonaktifkan sepenuhnya scrolling.

Catatan: ini secara teknis menggunakan API pribadi dan dengan demikian aplikasi Anda dapat ditolak atau macet dalam rilis OS mendatang. Gunakan @trydanrespondsToSelector

rpetrich
sumber
Saya mencoba ini, dan itu salah ketika saya mencobanya ... Anehnya, saya dapat mengakses dan mengatur scrollView.bounces (tanpa efek), tetapi ketika saya mencoba dan mengatur scrollEnabled, itu salah ...
Brad Parks
Saya percaya subview ini disebut UIScroller, bukan UIScrollView. UIScroller adalah kelas tanpa dokumen dan tidak didukung yang memiliki banyak kesamaan dengan UIScrollView, tetapi Anda tidak dapat bergantung pada semua yang bekerja dengan cara yang sama dan tidak berubah di versi OS yang akan datang.
Marco
Saya melakukan ini pada aplikasi iPad (bukan iPhone) yang menjalankan iOS 3.2, dan bisa mendapatkan UIScrollView dari UIWebView saya. Saya berhasil mengubahsuaikan tampilan ini untuk mengubah lebih dari sekadar perilaku memantulnya sehingga saya dapat bersaksi tentang ini berfungsi di iPad. Aplikasi saya tidak melalui app store, tapi saya rasa tidak akan ada masalah dengan API tidak berdokumen di sini. Bagian yang pintar untuk solusi ini adalah Anda hanya melintasi hierarki UIView dan menggunakan UIScrollView - keduanya sangat halal.
Rolf Hendriks
0

Lihatlah ke dalam bouncesproperti UIScrollView. Quoth the Apple docs:

Jika nilai properti adalah YES(default), tampilan gulir memantul ketika bertemu batas konten. Memantul secara visual menunjukkan bahwa pengguliran telah mencapai batas konten. Jika nilainya NO, gulir berhenti segera di batas konten tanpa memantul.

Pastikan Anda menggunakan yang benar UIScrollView. Saya tidak yakin seperti apa hirarki itu untuk UIWebView, tetapi tampilan gulir bisa menjadi orangtua, bukan anak, dari UIWebView.

Alex
sumber
0

Untuk menonaktifkan UIWebViewpengguliran, Anda dapat menggunakan baris kode berikut:

[ObjWebview setUserInteractionEnabled:FALSE];

Dalam contoh ini, ObjWebviewadalah tipe UIWebView.

Sandip Patel - SM
sumber
0

webView.scrollView.scrollEnabled = TIDAK; webView.scrollView.bounces = TIDAK;

Kumaresan P
sumber