หยุด 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
ฉันหวังว่าคุณจะพิจารณาความหมายของการใช้งานของการปิดใช้งานคุณลักษณะนั้น มันมีเหตุผล ที่กล่าวว่าฉันอยากรู้อยากเห็นเช่นกันว่าคุณจะทำอย่างไร
46432 Michael Haren

วิธีที่ฉันฝังมันไว้ในแอปของฉันดูเหมือนจะดูเหมือนกับองค์ประกอบมุมมองอื่น ๆ ที่ฉันมีและเวลาเดียวที่มันไม่ปรากฏขึ้นก็คือเมื่อมีการตีกลับเกิดขึ้น .... เป็นจุดที่ดีอย่างแน่นอน!
s Brad 's เมื่อ

คำตอบ:


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 Simulator ไม่ใช่บน iPhone OS 3.1.3 มีใครรู้บ้างว่าการแก้ไขนี้ใช้ได้เฉพาะกับระบบปฏิบัติการเวอร์ชันใด ๆ
Dan J

@MirukRusin - คุณจะรับประกันได้อย่างไรว่าแอปนี้จะได้รับการยอมรับตามรหัสสามบรรทัด? : P
Moshe

@Mirek - คุณพลาดจุดของฉัน คุณจะรู้ได้อย่างไรว่าไม่มีสิ่งใดในแอปที่จะได้รับมันปฏิเสธ?
Moshe

6
มันใช้ได้ดีสำหรับฉัน เพื่อความสะดวกฉันได้เพิ่มหมวดหมู่ไว้UIWebViewเพื่อที่ฉันจะสามารถโทรไป[webView setBounces:NO]ที่ไหนก็ได้ที่ฉันต้องการ
zekel

46

ฉันกำลังดูโครงการที่ทำให้การสร้างเว็บแอปเป็นแอปพลิเคชั่นที่ติดตั้งได้อย่างสมบูรณ์บน iPhone ชื่อQuickConnectและพบวิธีแก้ปัญหาที่ใช้งานได้หากคุณไม่ต้องการให้หน้าจอเลื่อนได้เลยซึ่งในกรณีของฉัน ฉันไม่ได้

ในการโพสต์โครงการ / บล็อกดังกล่าวข้างต้นพวกเขากล่าวถึงฟังก์ชั่นจาวาสคริปต์ที่คุณสามารถเพิ่มเพื่อปิดการตีกลับซึ่งเป็นหลัก boils ลงนี้:

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

หากคุณต้องการดูเพิ่มเติมเกี่ยวกับวิธีการใช้งานเพียงดาวน์โหลด QuickConnect และตรวจสอบออก .... แต่โดยพื้นฐานแล้วสิ่งที่เรียกว่าจาวาสคริปต์ในการโหลดหน้าเว็บ ... ฉันพยายามวางมันไว้ในหัวเอกสารของฉัน และดูเหมือนว่าจะทำงานได้ดี


คำตอบนี้เป็นวิธีที่ถูกต้องในการหยุดเลื่อนแนวตั้งของเนื้อหาภายใน UIWebView
Jessedc

3
คุณอาจได้รับคำตอบทั้งหมดตอนแรกฉันไม่ต้องการดาวน์โหลดโค้ด scource ทั้งหมดของแอพอื่นและฉันไม่สามารถหามันเจอ คำตอบของคุณขึ้นอยู่กับเว็บไซต์อื่นที่เหมือนกับเมื่อคุณตอบ
โจนาธาน

คำตอบนี้ & คำตอบที่ได้รับการยอมรับข้างต้นดูเหมือนจะต้องการในบางครั้ง ในกรณีของฉันฉันพบว่าถ้ามุมมองเว็บยังไม่โหลดความต่อเนื่องจะอยู่ที่นั่นจนกว่าจะโหลด JS ด้านบนเข้าสู่ระบบจริง ดังนั้นคำตอบน่าจะเป็นเช่นนี้และคำตอบที่ได้รับการยอมรับข้างต้นมีความจำเป็น
Kalle

3
ดังที่ Jessedc กล่าวว่าสิ่งนี้จะหยุดการเลื่อนแนวตั้งไม่ใช่เพียงแค่กระดอน นั่นหมายความว่าถ้าคุณมี div หรือดังนั้นที่ต้องมีการเลื่อนมันจะไม่เลื่อน
memical

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]; และแอปเปิลบอกว่ามันเป็น API ส่วนตัวและด้วยเหตุนี้จึงปฏิเสธ กำลังจะส่งอีกครั้งในขณะนี้ แต่ใช้ "userInteractionEnabled: NO" เนื่องจากฉันไม่ต้องการลิงก์ที่ใช้งานในแอป
Veeru

UIWebView สืบทอดมาจาก UIView UIView มีคุณสมบัติย่อย ที่นี่เป็นส่วนตัวคืออะไร ทั้งหมดนี้คุณสามารถพบได้บน developer.apple.com
Valerii Pavlov

3
ฉันมีสิ่งที่ชอบ 4 แอพใน appstore โดยใช้สิ่งนี้ แอปของคุณถูกปฏิเสธอย่างชัดเจนด้วยเหตุผลอื่น นี่ไม่ใช่ API ส่วนตัว
Zigglzworth

4
นี่ไม่ใช่ความคิดที่ดีจริงๆ คุณพึ่งพาข้อเท็จจริงที่ว่าUIScrollViewนี่เป็นมุมมองย่อยแรกUIWebViewซึ่งอาจเป็นกรณีสำหรับตอนนี้ แต่สิ่งนี้อาจเปลี่ยนแปลงได้ง่ายในอนาคต (แม้แต่รายย่อย) อัปเดตเป็น iOS หรือการกำหนดค่าเฉพาะ คุณควรทำforซ้ำsubviewsเพื่อค้นหาจริง ๆUIScrollView(มันไม่ได้ทำงานมากและอย่างน้อยคุณรับประกันว่าจะได้รับUIScrollViewและไม่ผิดพลาดโปรแกรมของคุณ ...
Jonathan Ellis

17

ใน iOS 5 SDK คุณสามารถเข้าถึงมุมมองเลื่อนที่เชื่อมโยงกับมุมมองเว็บโดยตรงแทนที่จะวนซ้ำผ่านการดูย่อย

ดังนั้นหากต้องการปิดใช้งาน 'การตีกลับ' ในมุมมองการเลื่อนคุณสามารถใช้:

myWebView.scrollView.bounces = NO;

ดูUIWebView ชั้นอ้างอิง

(อย่างไรก็ตามหากคุณต้องการรองรับเวอร์ชั่น SDK ก่อน 5.0 คุณควรทำตามคำแนะนำของ Mirek Rusin )



9

คำเตือน. ฉันใช้ setAllowsRubberBanding: ในแอปของฉันและ Apple ปฏิเสธว่าไม่อนุญาตให้ใช้ฟังก์ชั่น API ที่ไม่ใช่แบบสาธารณะ (อ้างอิง: 3.3.1)



3

วิธีการของแบรดทำงานให้ฉัน ถ้าคุณใช้มันคุณอาจต้องการทำให้ปลอดภัยขึ้นเล็กน้อย

id scrollView = [yourWebView.subviews objectAtIndex: 0];
ถ้า ([scrollView ตอบสนองต่อ SelectSelector: @selector (setAllowsRubberBanding :)])
{
    [scrollView performselector: @selector (setAllowsRubberBanding :) ด้วยObject: NO];
}

ถ้าแอปเปิ้ลเปลี่ยนอะไรบางอย่างการตีกลับก็จะกลับมา แต่อย่างน้อยแอปของคุณจะไม่ผิด


3

บน iOS5 เฉพาะเมื่อคุณวางแผนที่จะให้ผู้ใช้ซูมเนื้อหาเว็บวิว (ei: แตะสองครั้ง) การตั้งค่าการตีกลับไม่เพียงพอ คุณจำเป็นต้องตั้งค่าคุณสมบัติ BounceH แนวนอนและ BounceVertical เป็น NO เสมอทุกครั้งที่พวกเขาซูมออก (แตะอีกสองครั้ง ... ) เป็นค่าเริ่มต้นมันจะเด้งกลับมาอีกครั้ง


2

ฉันสำรวจชุดข้อมูลย่อยของ UIWebView และตั้งค่าพื้นหลังเป็น [UIColor blackColor] ซึ่งเป็นสีเดียวกับพื้นหลังของเว็บเพจ มุมมองจะยังคงเด้ง แต่จะไม่แสดงพื้นหลังสีเทาเข้มที่น่าเกลียด


1
ที่จริงแล้วมันค่อนข้างแย่เพราะถ้าแอปเปิ้ลเคยเปลี่ยน internals ของ UIWebView แฮ็คนี้อาจแตก
bpapa

2

ดูเหมือนว่าฉันจะ UIWebView มี UIScrollView คุณสามารถใช้ API ที่ทำเป็นเอกสารสำหรับสิ่งนี้ แต่ตั้งค่าการตีกลับสำหรับทั้งสองทิศทางไม่ใช่ทีละรายการ นี่คือเอกสาร API UIScrollView มีคุณสมบัติการตีกลับดังนั้นสิ่งนี้จึงใช้ได้ (ไม่ทราบว่ามี 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 ไม่ใช่มุมมองการเลื่อนดังนั้นฉันจึงสร้างคลาสย่อยที่กำหนดเองเพื่อไปที่มุมมองการเลื่อนของมุมมองเว็บ suclass นี้มีมุมมองเลื่อนเพื่อให้คุณสามารถปรับแต่งพฤติกรรมของมุมมองเว็บของคุณ Punchlines ของชั้นนี้คือ:

@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) เป็นภาพเคลื่อนไหว: YES เพื่อบังคับให้มีการเปลี่ยนแปลงที่ไม่สามารถสังเกตเห็นได้ซึ่งจะกำหนดขนาดเนื้อหาที่เหมาะสมของมุมมองเว็บ

2

มาค้นหาคำตอบนี้และในที่สุดฉันก็โชคดีที่คำตอบของฉันเองโดยทำเรื่องยุ่ง ๆ ฉันทำ

[[webview scrollView] setBounces:NO];

และมันก็ใช้งานได้


2

สิ่งนี้ใช้ได้สำหรับฉันและสวยงามเช่นกัน (ฉันใช้ phonegap กับ webView)

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

หรือ

[[webView scrollView] setScrollEnabled:NO];

1

ฉันลองวิธีที่แตกต่างกันเล็กน้อยเพื่อป้องกันไม่ให้วัตถุUIWebViewเลื่อนและกระดอน: เพิ่มตัวรู้จำท่าทางเพื่อแทนที่ท่าทางอื่น ๆ

มันดูเหมือน, UIWebViewหรือมุมมองย่อยของ scroller ใช้ตัวจดจำท่าทางเลื่อนของตัวเองเพื่อตรวจจับการเลื่อนผู้ใช้ แต่ตามเอกสารของ Apple มีวิธีที่ถูกต้องในการเอาชนะตัวรู้จำท่าทางด้วยวิธีอื่นอย่างถูกกฎหมาย UIGestureRecognizerDelegateโปรโตคอลมีรูปแบบวิธีท่าทาง Recognizer: ควรRecognizeSimพร้อมกันด้วย GestureRecognizer: - ซึ่งช่วยให้การควบคุมพฤติกรรมของตัวจดจำท่าทางการชนใด ๆ

ดังนั้นสิ่งที่ฉันทำคือ

ในวิธีการ 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 แต่ฉันเชื่อว่าฉันไม่ได้ใช้อะไรที่ไม่มีเอกสารจนถึงตอนนี้ ... หากใครพบมันเป็นอย่างอื่นโปรดแจ้งฉัน


1

นี่เป็นวิธีแก้ปัญหาที่เป็นไปได้สองแบบใหม่ เห็นได้ชัดว่าคุณสามารถใช้ jqtouch หรือ pastrykit เพื่อปิดการใช้งานการเลื่อน อย่างไรก็ตามฉันไม่ได้รับการทำงานเหล่านี้ คุณอาจมีความสามารถมากกว่า

ปิดการเลื่อนแนวตั้ง

ขุดลงในขนมอบ



1

(ตัวอย่าง Xcode 5 iOS 7 SDK) นี่คือตัวอย่างแอพสากลที่ใช้ฟังก์ชั่น scrollview setBounces มันเป็นโครงการ / ตัวอย่างแบบโอเพนซอร์ซตั้งอยู่ที่นี่: ลิงก์ไปยัง SimpleWebView (ตัวอย่างซิปโครงการและซอร์สโค้ด)


0

หนึ่งใน subviews ของที่ควรจะเป็นUIWebView UIScrollViewตั้งค่าscrollEnabledคุณสมบัติเป็นNOและมุมมองเว็บจะปิดใช้งานการเลื่อนทั้งหมด

หมายเหตุ: นี่เป็นการใช้งานเทคนิคส่วนตัว API และทำให้แอปของคุณอาจถูกปฏิเสธหรือผิดพลาดในอนาคตระบบปฏิบัติการ ใช้@tryและrespondsToSelector


ฉันลองสิ่งนี้และมันผิดพลาดเมื่อฉันลอง ... น่าแปลกที่ฉันสามารถเข้าถึงและตั้งค่า scrollView.bounces (โดยไม่มีผลกระทบ) แต่เมื่อฉันลองและตั้งค่า scrollEnabled มันผิดพลาด ...
Brad Parks

ฉันเชื่อว่ามุมมองย่อยเรียกว่า UIScroller ไม่ใช่ UIScrollView UIScroller เป็นคลาสที่ไม่มีเอกสารและไม่สนับสนุนซึ่งมีการใช้งานร่วมกันมากกับ UIScrollView แต่คุณไม่สามารถพึ่งพาทุกสิ่งที่ทำงานในลักษณะเดียวกันและไม่เปลี่ยนแปลงในเวอร์ชันระบบปฏิบัติการในอนาคต
Marco

ฉันทำสิ่งนี้บนแอป iPad (ไม่ใช่ iPhone) ที่ใช้ iOS 3.2 และสามารถเอา UIScrollView ออกจาก UIWebView ของฉันได้ ฉันปรับแต่งมุมมองนี้ให้ประสบความสำเร็จเพื่อเปลี่ยนมากกว่าพฤติกรรมการกระเด้งกระดอนเพื่อให้สามารถเป็นพยานในการทำงานบน iPad แอพของฉันไม่ผ่านแอพสโตร์ แต่ฉันไม่คิดว่าจะมีปัญหากับ API ที่ไม่มีเอกสารของที่นี่ ส่วนที่ฉลาดสำหรับการแก้ปัญหานี้คือคุณเพียงแค่ผ่านลำดับชั้นของ UIView และใช้ UIScrollView ซึ่งทั้งสองอย่างนั้นเป็นเพียวเพียว
Rolf Hendriks

0

มองเข้าไปในทรัพย์สินของbounces UIScrollViewสิ่งที่ Apple เอกสาร:

หากค่าของคุณสมบัติคือYES(ค่าเริ่มต้น) มุมมองเลื่อนจะกระดอนเมื่อพบขอบเขตของเนื้อหา การสะท้อนด้วยสายตาแสดงให้เห็นว่าการเลื่อนมาถึงขอบของเนื้อหาแล้ว หากมีค่าการNOเลื่อนจะหยุดทันทีที่ขอบเขตเนื้อหาโดยไม่ต้องกระดอน

UIScrollViewให้แน่ใจว่าคุณกำลังใช้สิทธิ ผมไม่แน่ใจว่าสิ่งที่ลำดับชั้นดูเหมือนหาแต่มุมมองเลื่อนอาจจะเป็นพ่อแม่ไม่ได้เด็กของUIWebViewUIWebView


0

หากต้องการปิดการUIWebViewเลื่อนคุณสามารถใช้บรรทัดของรหัสต่อไปนี้:

[ObjWebview setUserInteractionEnabled:FALSE];

ในตัวอย่างนี้เป็นประเภทObjWebviewUIWebView


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.