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


86

มีตัวเลือกใน IB เพื่อยกเลิกการเลือกการเลื่อนแนวตั้งบนมุมมองแบบเลื่อน แต่ดูเหมือนจะไม่ได้ผล

จะตั้งค่า scrollview ให้เลื่อนในแนวนอนเท่านั้นไม่ใช่แนวตั้งในโค้ดแทน IB ได้อย่างไร


คำตอบ:


121

ลองตั้งค่าความสูงของ contentSize เป็นความสูงของ scrollView จากนั้นควรปิดการเลื่อนแนวตั้งเพราะจะไม่มีอะไรให้เลื่อนในแนวตั้ง

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,scrollView.frame.size.height);

คุณช่วยฉันประหยัดเวลาได้มากในการแก้ไขปัญหาแปลก ๆ นี้ ขอบคุณ!
jpm

2
@fabb จะรู้ได้อย่างไรว่าเมื่อเฟรมเปลี่ยนไป?
แซม

138

ตั้งแต่ iOS7:

อันดับแรก: ความกว้างของขนาดเนื้อหาต้องเท่ากับความกว้างของมุมมองแบบเลื่อนของคุณ

วินาที: ใน initWithNibName ของคุณ:

self.automaticallyAdjustsScrollViewInsets = NO;

แค่นั้นแหละ.


ทางออกที่ยอดเยี่ยม ทำงานอย่างมีเสน่ห์ จะมีผลต่อขนาดของมุมมองที่เหลือใน ViewController ของฉันหรือไม่ (ปุ่มป้ายกำกับ .. ) ฉันหมายถึง "ตัวเอง" เป็น UIViewController ในกรณีของฉัน
voghDev

@voghDev ไม่มีผลต่อมุมมองย่อยใน scrollview ของคุณ
Mirko Brunner

Amazing เพิ่มสิ่งนี้ลงในเมธอด viewdidload บนตัวควบคุมมุมมองของฉันที่มีปัญหา
StackRunner

หากคุณใช้ navigationController และ scrollview ของคุณอยู่หลังชื่อ navigationBar เช่นการใช้ของฉันภายใต้เมธอด viewDidLoad มันแก้
EFE

1
คุณสามารถทำสิ่งเดียวกันนี้ได้ในการตั้งค่าสตอรีบอร์ดโดยตรงโดยไม่ต้องมีโค้ดบรรทัดใด ๆ เพียงเลือกตัวควบคุมมุมมองการเลื่อนและยกเลิกการเลือก "Adjust Scroll View Insets" ในตัวตรวจสอบแอตทริบิวต์
Morpheus78

49

ใช่คำตอบของ pt2ph8 ถูกต้อง

แต่ถ้าด้วยเหตุผลแปลก ๆ contentSize ของคุณควรสูงกว่า UIScrollView คุณสามารถปิดใช้งานการเลื่อนแนวตั้งโดยใช้วิธีโปรโตคอล UIScrollView

 -(void)scrollViewDidScroll:(UIScrollView *)aScrollView;

เพียงเพิ่มสิ่งนี้ใน UIViewController ของคุณ

float oldY; // here or better in .h interface

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, oldY)];
    // or if you are sure you wanna it always on top:
    // [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, 0)];
}

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


6
พระเจ้า! โปรดอย่าประกาศตัวแปร oldY ในไฟล์. m เช่นfloat oldY;อ้างถึงโค้ดด้านบน นั่นคือสัญลักษณ์ตัวแปรรูปแบบ C สำหรับต่อแอ็พพลิเคชันตัวแปรต้องถูกประกาศให้เป็นสมาชิกอินสแตนซ์ของคลาสคอนโทรลเลอร์
Itachi

21

รวมวิธีการดังต่อไปนี้

-(void)viewDidLayoutSubviews{
    self.automaticallyAdjustsScrollViewInsets = NO;
}

และตั้งค่าความกว้างขนาดเนื้อหาของมุมมองเลื่อนให้เท่ากับความกว้างของมุมมองเลื่อน


1
คุณสามารถทำได้ใน Storyboard โดยเลือก View Controller และยกเลิกการเลือกคุณสมบัติที่นั่น
justColbs

1
ฉันไม่ชอบสิ่งนี้เพราะมันตั้งค่าไว้สำหรับมุมมองแบบเลื่อนทั้งหมด ... หวังว่าคุณจะเจาะจงมุมมองเลื่อนเดียวบนไดอะแกรมโดยไม่ต้องสร้างคลาส ScrollView ใหม่ ฯลฯ
visc

20

คุณต้องผ่าน 0 ในขนาดเนื้อหาเพื่อปิดใช้งานในทิศทางที่คุณต้องการ

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

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,0);

เพื่อปิดใช้งานการเลื่อนแนวนอน

scrollView.contentSize = CGSizeMake(0,scrollView.contentSize.height);

1
สิ่งนี้จะตั้งค่า contentSize ของมุมมองให้มี 0 บนแกนที่คุณตั้งไว้ ContentSize หมายถึงขนาดของเนื้อหาดังนั้นเราจึงต้องการส่งผ่านความสูงของหน้าจอเพื่อปิดใช้งานการเลื่อนในแนวตั้งนอกเหนือจากกรอบนั้น วิธีแก้ปัญหาที่ระบุว่าถูกต้องถูกต้อง
ระบบ

นี้ทำงานได้ดีสำหรับฉัน. การตั้งค่าความสูงเป็นความสูงของ contentSize ยังคงทำให้ฉันเลื่อนแนวตั้งได้
KoreanXcodeWorker

1
สิ่งนี้ไม่ได้ผลสำหรับฉัน ยังพยายามด้วยตนเองโดยอัตโนมัติAdjustsScrollViewInsets
StackRunner

นี่ไง! การตั้งค่าความสูงของ Scroll View ไม่ได้ผลสำหรับฉัน แต่สิ่งนี้ทำได้
Echizzle

18

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

อาจจะมีคนมีปัญหานี้เหมือนกัน


คุณช่วยฉันไว้. เนื้อหาของฉันขนาดและกรอบเหมือนกันและฉันไม่สามารถเข้าใจได้ตลอดชีวิตว่ามีอะไรผิดปกติ ขอบคุณมาก !!
yuf

2
คำตอบของคุณคือทำไมฉันถึงชอบ stackoverflow! :-) ควันศักดิ์สิทธิ์ ... นี่ทำให้ฉันบ้า! คุณพูดถูก มันคือเอฟเฟกต์ตีกลับ ฉันต้องการเอฟเฟกต์ตีกลับ แต่ไม่ใช่เมื่อไม่จำเป็นต้องเลื่อนดังนั้นฉันจะต้องการปิด / เปิดใช้งานเอฟเฟกต์นั้นอีกครั้งในโค้ดโดยขึ้นอยู่กับว่าจำเป็นต้องเลื่อนหรือไม่
Erik van der Neut

2
โอเคเปิด / ปิดการตีกลับบน UIScrollView ที่รันไทม์ได้ง่ายมาก ในกรณีของฉันฉันสนใจเฉพาะความสูงของเนื้อหาในการเลื่อนเท่านั้นและนี่ก็เป็นเคล็ดลับ: self.scrollView.bounces = (BOOL) (self.scrollView.contentSize.height> self.scrollView.frame.size.height);
Erik van der Neut

12
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x,0)];

}

คุณต้องได้รับการยืนยัน UIScrollViewDelegate

aScrollView.delegate = self;

4

เพียงตั้งค่า y ให้อยู่ด้านบนเสมอ ต้องสอดคล้องกับ UIScrollViewDelegate

func scrollViewDidScroll(scrollView: UIScrollView) {
        scrollView.contentOffset.y = 0.0
}

สิ่งนี้จะรักษาเอฟเฟกต์การชะลอตัว / การเร่งความเร็วของการเลื่อน


4

บน iOS 11 โปรดอย่าลืมเพิ่มสิ่งต่อไปนี้หากคุณสนใจที่จะสร้างมุมมองแบบเลื่อนที่ยึดติดกับขอบเขตหน้าจอแทนที่จะเป็นพื้นที่ปลอดภัย:

if (@available(iOS 11.0, *)) {
    [self.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}

1
หลังจากนั้น. ขอบคุณพันครั้งครับ! คุณบันทึกวันของฉัน
ha100

1

จากiOS11เราสามารถใช้คุณสมบัติต่อไปนี้

let frameLayoutGuide: UILayoutGuide

หากคุณตั้งข้อ จำกัด สำหรับframeLayoutGuide.topAnchorและframeLayoutGuide.bottomAnchorเพื่อเบรกเดียวกันของบางsubviewคุณscrollviewแล้วเลื่อนแนวตั้งจะเป็นคนพิการและความสูงของscrollviewจะเท่ากับความสูงของ subview ของตน


1

วิธีแก้ไขที่ชัดเจนที่สุดคือห้ามไม่ให้มีการเปลี่ยนแปลงพิกัด y ในคลาสย่อยของคุณ

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: newValue.x, y: 0)
  }
}

นี่เป็นทางออกเดียวที่เหมาะสมในสถานการณ์เมื่อ:

  1. คุณไม่ได้รับอนุญาตหรือไม่ต้องการใช้ผู้รับมอบสิทธิ์
  2. ความสูงของเนื้อหาของคุณมากกว่าความสูงของคอนเทนเนอร์

1
นี่คือคำตอบที่ดีที่สุด! ควรเลือกเป็นน้ำยา! ขอบคุณเพื่อนที่ช่วยวันของฉัน!
เหมือน

@imike วิธีแก้ปัญหาที่ฉันชอบคือการใช้ swizzling (: ตรวจสอบgithub.com/iwheelbuy/UIPanGestureRecognizerDirection repo
iWheelBuy

0

คำตอบมากมายรวมถึงการตั้งค่าเป็นcontentOffset0 ฉันมีกรณีที่ฉันต้องการให้มุมมองภายใน scrollView อยู่ตรงกลาง สิ่งนี้ได้ผลสำหรับฉัน:

public func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = -scrollView.contentInset.top
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.