เพจ UIScrollView ทีละน้อยกว่าขนาดเฟรม


87

ฉันมีมุมมองแบบเลื่อนที่มีความกว้างของหน้าจอ แต่สูงประมาณ 70 พิกเซลเท่านั้น มันมีไอคอนขนาด 50 x 50 จำนวนมาก (มีช่องว่างรอบ ๆ ) ที่ฉันต้องการให้ผู้ใช้สามารถเลือกได้ แต่ฉันต้องการให้มุมมองแบบเลื่อนทำงานในลักษณะเพจหยุดเสมอโดยมีไอคอนอยู่ตรงกลาง

หากไอคอนมีความกว้างของหน้าจอสิ่งนี้จะไม่เป็นปัญหาเพราะการเพจของ UIScrollView จะดูแลมัน แต่เนื่องจากไอคอนเล็ก ๆ ของฉันน้อยกว่าขนาดเนื้อหามากจึงไม่สามารถใช้งานได้

ฉันเคยเห็นพฤติกรรมนี้มาก่อนในแอปเรียก AllRecipes ฉันไม่รู้ว่าจะทำอย่างไร

ฉันจะทำให้เพจตามขนาดไอคอนทำงานได้อย่างไร?

คำตอบ:


123

ลองทำให้ scrollview ของคุณน้อยกว่าขนาดของหน้าจอ (width-wise) แต่ยกเลิกการเลือกช่องทำเครื่องหมาย "Clip Subviews" ใน IB จากนั้นซ้อนทับมุมมองแบบโปร่งใส userInteractionEnabled = NO ที่ด้านบน (ที่ความกว้างเต็ม) ซึ่งจะแทนที่ hitTest: withEvent: เพื่อส่งคืนมุมมองการเลื่อนของคุณ นั่นควรให้สิ่งที่คุณกำลังมองหา ดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม


1
ฉันไม่ค่อยแน่ใจว่าคุณหมายถึงอะไรฉันจะดูคำตอบที่คุณชี้ไป
Henning

8
นี่คือทางออกที่สวยงาม ฉันไม่ได้คิดที่จะลบล้างฟังก์ชัน hitTest: และนั่นเป็นการตัดข้อเสียเพียงอย่างเดียวของแนวทางนี้ออกไป ทำได้ดีมาก
Ben Gotow

ทางออกที่ดี! ช่วยฉันได้จริงๆ
DevDevDev

8
วิธีนี้ใช้งานได้ดีจริงๆ แต่ฉันขอแนะนำให้แทนที่จะคืน scrollView ให้กลับ [scrollView hitTest: point withEvent: event] เพื่อให้เหตุการณ์ต่างๆผ่านไป ตัวอย่างเช่นในมุมมองแบบเลื่อนที่เต็มไปด้วย UIButtons ปุ่มต่างๆจะยังคงทำงานในลักษณะนี้
greenisus

2
โปรดทราบว่าสิ่งนี้จะใช้ไม่ได้กับ tableview หรือ collectionView เนื่องจากจะไม่แสดงสิ่งที่อยู่นอกเฟรม ดูคำตอบของฉันด้านล่าง
vish

63

นอกจากนี้ยังมีวิธีแก้ปัญหาอื่นที่น่าจะดีกว่าการซ้อนทับมุมมองแบบเลื่อนด้วยมุมมองอื่นและแทนที่ hitTest

คุณสามารถ subclass UIScrollView และแทนที่ pointInside ได้ จากนั้นมุมมองแบบเลื่อนสามารถตอบสนองเมื่อสัมผัสนอกกรอบ แน่นอนส่วนที่เหลือก็เหมือนกัน

@interface PagingScrollView : UIScrollView {

    UIEdgeInsets responseInsets;
}

@property (nonatomic, assign) UIEdgeInsets responseInsets;

@end


@implementation PagingScrollView

@synthesize responseInsets;

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    CGPoint parentLocation = [self convertPoint:point toView:[self superview]];
    CGRect responseRect = self.frame;
    responseRect.origin.x -= responseInsets.left;
    responseRect.origin.y -= responseInsets.top;
    responseRect.size.width += (responseInsets.left + responseInsets.right);
    responseRect.size.height += (responseInsets.top + responseInsets.bottom);

    return CGRectContainsPoint(responseRect, parentLocation);
}

@end

1
ใช่! ยิ่งไปกว่านั้นหากขอบเขตของ scrollview ของคุณเหมือนกันกับพาเรนต์คุณสามารถคืนค่าใช่จากวิธี pointInside ขอบคุณ
cocoatoucher

5
ฉันชอบโซลูชันนี้แม้ว่าฉันจะต้องเปลี่ยน parentLocation เป็น "[self convertPoint: point toView: self.superview]" เพื่อให้ทำงานได้อย่างถูกต้อง
amrox

คุณพูดถูกแล้ว convertPoint ดีกว่าที่ฉันเขียนไว้มาก
แยก

6
return [self.superview pointInside:[self convertPoint:point toView:self.superview] withEvent:event];@amrox @Split โดยตรงคุณไม่ต้องการ responseInsets หากคุณมี superview ที่ทำหน้าที่เป็นมุมมองคลิป
Cœur

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

18

ฉันเห็นวิธีแก้ปัญหามากมาย แต่มันซับซ้อนมาก วิธีที่ง่ายกว่ามากในการมีเพจขนาดเล็ก แต่ยังคงสามารถเลื่อนพื้นที่ทั้งหมดได้คือทำให้การเลื่อนเล็กลงและย้ายscrollView.panGestureRecognizerไปที่มุมมองหลักของคุณ นี่คือขั้นตอน:

  1. ลดขนาด scrollView ของคุณขนาด ScrollView เล็กกว่าระดับบนสุด

  2. ตรวจสอบให้แน่ใจว่ามุมมองการเลื่อนของคุณมีการแบ่งหน้าและไม่ตัดมุมมองย่อย ใส่คำอธิบายภาพที่นี่

  3. ในโค้ดให้ย้ายท่าทางเลื่อนแบบเลื่อนไปยังมุมมองคอนเทนเนอร์หลักที่มีความกว้างเต็ม:

    override func viewDidLoad() {
        super.viewDidLoad()
        statsView.addGestureRecognizer(statsScrollView.panGestureRecognizer)
    }

นี่คือวิธีแก้ปัญหาแบบ greeeeeeat ฉลาดมาก.
matteopuc

นี่คือสิ่งที่ฉันต้องการจริงๆ!
LYM

ฉลาดมาก! คุณช่วยฉันได้หลายชั่วโมง ขอขอบคุณ!
Erik

6

คำตอบที่ได้รับการยอมรับนั้นดีมาก แต่จะใช้ได้ผลกับUIScrollViewชั้นเรียนเท่านั้นและไม่มีผู้สืบทอด ตัวอย่างเช่นหากคุณมีมุมมองจำนวนมากและแปลงเป็น a UICollectionViewคุณจะไม่สามารถใช้วิธีนี้ได้เนื่องจากมุมมองคอลเลคชันจะลบมุมมองที่คิดว่า "มองไม่เห็น" (แม้ว่าจะไม่ถูกตัดออก แต่ก็จะ หายไป).

ความคิดเห็นเกี่ยวกับสิ่งที่กล่าวถึงscrollViewWillEndDragging:withVelocity:targetContentOffset:คือในความคิดของฉันคำตอบที่ถูกต้อง

สิ่งที่คุณทำได้คือภายในวิธีการมอบหมายนี้คุณคำนวณหน้า / ดัชนีปัจจุบัน จากนั้นให้คุณตัดสินใจว่าความเร็วและการชดเชยเป้าหมายเหมาะสมกับการเคลื่อนไหว "หน้าถัดไป" หรือไม่ คุณสามารถเข้าใกล้ไฟล์pagingEnabledพฤติกรรมได้

หมายเหตุ:ฉันมักจะเป็นนักพัฒนา RubyMotion ในทุกวันนี้ดังนั้นใครบางคนโปรดพิสูจน์รหัส Obj-C นี้เพื่อความถูกต้อง ขออภัยสำหรับการผสมผสานระหว่าง camelCase และ snake_case ฉันคัดลอกและวางโค้ดนี้มาก

- (void) scrollViewWillEndDragging:(UIScrollView *)scrollView
         withVelocity:(CGPoint)velocity
         targetContentOffset:(inout CGPoint *)targetOffset
{
    CGFloat x = targetOffset->x;
    int index = [self convertXToIndex: x];
    CGFloat w = 300f;  // this is your custom page width
    CGFloat current_x = w * [self convertXToIndex: scrollView.contentOffset.x];

    // even if the velocity is low, if the offset is more than 50% past the halfway
    // point, proceed to the next item.
    if ( velocity.x < -0.5 || (current_x - x) > w / 2 ) {
      index -= 1
    } 
    else if ( velocity.x > 0.5 || (x - current_x) > w / 2 ) {
      index += 1;
    }

    if ( index >= 0 || index < self.items.length ) {
      CGFloat new_x = [self convertIndexToX: index];
      targetOffset->x = new_x;
    }
} 

ฮ่าฮ่าตอนนี้ฉันสงสัยว่าฉันไม่ควรพูดถึง RubyMotion - มันทำให้ฉันถูกลงคะแนน! ไม่จริงฉันต้องการให้คะแนนโหวตรวมถึงความเห็นบางส่วนฉันชอบที่จะรู้ว่ามีคนคิดอะไรผิดกับคำอธิบายของฉัน
colinta

คุณสามารถใส่คำจำกัดความของconvertXToIndex:และconvertIndexToX:?
mr5

ไม่สมบูรณ์. เมื่อคุณลากช้าๆและยกมือขึ้นโดยvelocityมีค่าเป็นศูนย์มันจะเด้งกลับซึ่งเป็นเรื่องแปลก งั้นผมมีคำตอบดีกว่า
DawnSong

4
- (void) scrollViewWillEndDragging:(UIScrollView *)scrollView
         withVelocity:(CGPoint)velocity
         targetContentOffset:(inout CGPoint *)targetOffset
{
    static CGFloat previousIndex;
    CGFloat x = targetOffset->x + kPageOffset;
    int index = (x + kPageWidth/2)/kPageWidth;
    if(index<previousIndex - 1){
        index = previousIndex - 1;
    }else if(index > previousIndex + 1){
        index = previousIndex + 1;
    }

    CGFloat newTarget = index * kPageWidth;
    targetOffset->x = newTarget - kPageOffset;
    previousIndex = index;
} 

kPageWidth คือความกว้างที่คุณต้องการให้เพจของคุณเป็น kPageOffset คือถ้าคุณไม่ต้องการให้เซลล์ถูกจัดชิดซ้าย (เช่นถ้าคุณต้องการให้จัดแนวกึ่งกลางให้ตั้งค่านี้เป็นครึ่งหนึ่งของความกว้างของเซลล์ของคุณ) มิฉะนั้นควรเป็นศูนย์

นอกจากนี้ยังอนุญาตให้เลื่อนได้ครั้งละหนึ่งหน้าเท่านั้น


3

ลองดู-scrollView:didEndDragging:willDecelerate:วิธีการบนUIScrollViewDelegate. สิ่งที่ต้องการ:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    int x = scrollView.contentOffset.x;
    int xOff = x % 50;
    if(xOff < 25)
        x -= xOff;
    else
        x += 50 - xOff;

    int halfW = scrollView.contentSize.width / 2; // the width of the whole content view, not just the scroll view
    if(x > halfW)
        x = halfW;

    [scrollView setContentOffset:CGPointMake(x,scrollView.contentOffset.y)];
}

มันไม่สมบูรณ์แบบ - ล่าสุดฉันลองใช้รหัสนี้ฉันมีพฤติกรรมที่น่าเกลียด (กระโดดตามที่ฉันจำได้) เมื่อกลับจากม้วนหนังยาง คุณอาจจะสามารถที่จะหลีกเลี่ยงว่าเพียงแค่การตั้งค่ามุมมองเลื่อนของคุณสมบัติการbouncesNO


3

เนื่องจากดูเหมือนว่าฉันจะไม่ได้รับอนุญาตให้แสดงความคิดเห็นฉันจะเพิ่มความคิดเห็นของฉันในคำตอบของโนอาห์ที่นี่

ฉันประสบความสำเร็จด้วยวิธีการที่ Noah Witherspoon อธิบายไว้ ฉันแก้ไขพฤติกรรมการกระโดดโดยไม่เรียกsetContentOffset:เมธอดเมื่อ scrollview อยู่เลยขอบ

         - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
         {      
             // Don't snap when at the edges because that will override the bounce mechanic
             if (self.contentOffset.x < 0 || self.contentOffset.x + self.bounds.size.width > self.contentSize.width)
                 return;

             ...
         }

ฉันยังพบว่าฉันต้องใช้-scrollViewWillBeginDecelerating:วิธีการนี้UIScrollViewDelegateเพื่อจับทุกกรณี


ต้องจับคดีอะไรเพิ่มเติม
chrish

กรณีที่ไม่มีการลากเลย ผู้ใช้ยกนิ้วและการเลื่อนจะหยุดทันที
Jess Bowers

3

ฉันลองใช้วิธีแก้ปัญหาข้างต้นซึ่งซ้อนทับมุมมองโปร่งใสด้วย pointInside: withEvent: overridden สิ่งนี้ได้ผลดีสำหรับฉัน แต่ก็พังในบางกรณี - ดูความคิดเห็นของฉัน ฉันลงเอยด้วยการใช้การเพจตัวเองด้วยการรวมกันของ scrollViewDidScroll เพื่อติดตามดัชนีของเพจปัจจุบันและ scrollViewWillEndDragging: withVelocity: targetContentOffset และ scrollViewDidEndDragging: willDecelerate เพื่อสแน็ปไปยังเพจที่เหมาะสม หมายเหตุวิธีการสิ้นสุดจะใช้ได้เฉพาะ iOS5 + แต่ค่อนข้างน่าสนใจสำหรับการกำหนดเป้าหมายการชดเชยเฉพาะถ้าความเร็ว! = 0 โดยเฉพาะคุณสามารถบอกผู้โทรได้ว่าคุณต้องการให้มุมมองเลื่อนไปที่ใดพร้อมกับภาพเคลื่อนไหวหากมีความเร็วใน ทิศทางเฉพาะ


0

เมื่อสร้างมุมมองเลื่อนตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าสิ่งนี้:

scrollView.showsHorizontalScrollIndicator = false;
scrollView.showsVerticalScrollIndicator = false;
scrollView.pagingEnabled = true;

จากนั้นเพิ่มมุมมองย่อยของคุณไปยัง scroller โดยมีค่าชดเชยเท่ากับดัชนี * ความสูงของ scroller นี่คือสำหรับ scroller แนวตั้ง:

UIView * sub = [UIView new];
sub.frame = CGRectMake(0, index * h, w, subViewHeight);
[scrollView addSubview:sub];

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

จากนั้นใส่สิ่งนี้ในเมธอด viewDidScroll ของคุณ:

    //set vars
    int index = scrollView.contentOffset.y / h; //current index
    float y = scrollView.contentOffset.y; //actual offset
    float p = (y / h)-index; //percentage of page scroll complete (0.0-1.0)
    int subViewHeight = h-240; //height of the view
    int spacing = 30; //preferred spacing between views (if any)

    NSArray * array = scrollView.subviews;

    //cycle through array
    for (UIView * sub in array){

        //subview index in array
        int subIndex = (int)[array indexOfObject:sub];

        //moves the subs up to the top (on top of each other)
        float transform = (-h * subIndex);

        //moves them back down with spacing
        transform += (subViewHeight + spacing) * subIndex;

        //adjusts the offset during scroll
        transform += (h - subViewHeight - spacing) * p;

        //adjusts the offset for the index
        transform += index * (h - subViewHeight - spacing);

        //apply transform
        sub.transform = CGAffineTransformMakeTranslation(0, transform);
    }

เฟรมของมุมมองย่อยยังคงเว้นระยะห่างเราเพียงแค่ขยับเข้าด้วยกันผ่านการแปลงเมื่อผู้ใช้เลื่อน

นอกจากนี้คุณยังสามารถเข้าถึงตัวแปร p ด้านบนซึ่งคุณสามารถใช้สำหรับสิ่งอื่น ๆ เช่นอัลฟาหรือการแปลงภายในมุมมองย่อย เมื่อ p == 1 หน้านั้นจะแสดงอย่างสมบูรณ์หรือค่อนข้างจะเป็น 1


0

ลองใช้คุณสมบัติ contentInset ของ scrollView:

scrollView.pagingEnabled = YES;

[scrollView setContentSize:CGSizeMake(height, pageWidth * 3)];
double leftContentOffset = pageWidth - kSomeOffset;
scrollView.contentInset = UIEdgeInsetsMake(0, leftContentOffset, 0, 0);

อาจต้องใช้เวลาเล่นกับค่าของคุณเพื่อให้ได้เพจที่ต้องการ

ฉันพบว่าสิ่งนี้ทำงานได้อย่างหมดจดกว่าเมื่อเทียบกับทางเลือกอื่นที่โพสต์ ปัญหาในการใช้scrollViewWillEndDragging:วิธีมอบหมายคือการเร่งความเร็วสำหรับการตวัดช้าไม่เป็นธรรมชาติ


0

นี่เป็นวิธีแก้ปัญหาที่แท้จริงเท่านั้น

import UIKit

class TestScrollViewController: UIViewController, UIScrollViewDelegate {

    var scrollView: UIScrollView!

    var cellSize:CGFloat!
    var inset:CGFloat!
    var preX:CGFloat=0
    let pages = 8

    override func viewDidLoad() {
        super.viewDidLoad()

        cellSize = (self.view.bounds.width-180)
        inset=(self.view.bounds.width-cellSize)/2
        scrollView=UIScrollView(frame: self.view.bounds)
        self.view.addSubview(scrollView)

        for i in 0..<pages {
            let v = UIView(frame: self.view.bounds)
            v.backgroundColor=UIColor(red: CGFloat(CGFloat(i)/CGFloat(pages)), green: CGFloat(1 - CGFloat(i)/CGFloat(pages)), blue: CGFloat(CGFloat(i)/CGFloat(pages)), alpha: 1)
            v.frame.origin.x=CGFloat(i)*cellSize
            v.frame.size.width=cellSize
            scrollView.addSubview(v)
        }

        scrollView.contentSize.width=cellSize*CGFloat(pages)
        scrollView.isPagingEnabled=false
        scrollView.delegate=self
        scrollView.contentInset.left=inset
        scrollView.contentOffset.x = -inset
        scrollView.contentInset.right=inset

    }

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        preX = scrollView.contentOffset.x
    }

    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

        let originalIndex = Int((preX+cellSize/2)/cellSize)

        let targetX = targetContentOffset.pointee.x
        var targetIndex = Int((targetX+cellSize/2)/cellSize)

        if targetIndex > originalIndex + 1 {
            targetIndex=originalIndex+1
        }
        if targetIndex < originalIndex - 1 {
            targetIndex=originalIndex - 1
        }

        if velocity.x == 0 {
            let currentIndex = Int((scrollView.contentOffset.x+self.view.bounds.width/2)/cellSize)
            let tx=CGFloat(currentIndex)*cellSize-(self.view.bounds.width-cellSize)/2
            scrollView.setContentOffset(CGPoint(x:tx,y:0), animated: true)
            return
        }

        let tx=CGFloat(targetIndex)*cellSize-(self.view.bounds.width-cellSize)/2
        targetContentOffset.pointee.x=scrollView.contentOffset.x

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: velocity.x, options: [UIViewAnimationOptions.curveEaseOut, UIViewAnimationOptions.allowUserInteraction], animations: {
            scrollView.contentOffset=CGPoint(x:tx,y:0)
        }) { (b:Bool) in

        }

    }


}

0

นี่คือคำตอบของฉัน ในตัวอย่างของฉันcollectionViewซึ่งมีส่วนหัวคือ scrollView ที่เราต้องการให้มีเอisPagingEnabledฟเฟกต์ที่กำหนดเองและความสูงของเซลล์เป็นค่าคงที่

var isScrollingDown = false // in my example, scrollDirection is vertical
var lastScrollOffset = CGPoint.zero

func scrollViewDidScroll(_ sv: UIScrollView) {
    isScrollingDown = sv.contentOffset.y > lastScrollOffset.y
    lastScrollOffset = sv.contentOffset
}

// 实现 isPagingEnabled 效果
func scrollViewWillEndDragging(_ sv: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    let realHeaderHeight = headerHeight + collectionViewLayout.sectionInset.top
    guard realHeaderHeight < targetContentOffset.pointee.y else {
        // make sure that user can scroll to make header visible.
        return // 否则无法手动滚到顶部
    }

    let realFooterHeight: CGFloat = 0
    let realCellHeight = cellHeight + collectionViewLayout.minimumLineSpacing
    guard targetContentOffset.pointee.y < sv.contentSize.height - realFooterHeight else {
        // make sure that user can scroll to make footer visible
        return // 若有footer,不在此处 return 会导致无法手动滚动到底部
    }

    let indexOfCell = (targetContentOffset.pointee.y - realHeaderHeight) / realCellHeight
    // velocity.y can be 0 when lifting your hand slowly
    let roundedIndex = isScrollingDown ? ceil(indexOfCell) : floor(indexOfCell) // 如果松手时滚动速度为 0,则 velocity.y == 0,且 sv.contentOffset == targetContentOffset.pointee
    let y = realHeaderHeight + realCellHeight * roundedIndex - collectionViewLayout.minimumLineSpacing
    targetContentOffset.pointee.y = y
}

0

UICollectionViewโซลูชันเวอร์ชัน Swift ที่ปรับปรุงใหม่:

  • จำกัด หนึ่งหน้าต่อการกวาดนิ้ว
  • มั่นใจได้ว่าจะเลื่อนไปที่หน้าได้อย่างรวดเร็วแม้ว่าการเลื่อนของคุณจะช้า
override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.decelerationRate = .fast
}

private var dragStartPage: CGPoint = .zero

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
    dragStartOffset = scrollView.contentOffset
}

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    // Snap target offset to current or adjacent page
    let currentIndex = pageIndexForContentOffset(dragStartOffset)
    var targetIndex = pageIndexForContentOffset(targetContentOffset.pointee)
    if targetIndex != currentIndex {
        targetIndex = currentIndex + (targetIndex - currentIndex).signum()
    } else if abs(velocity.x) > 0.25 {
        targetIndex = currentIndex + (velocity.x > 0 ? 1 : 0)
    }
    // Constrain to valid indices
    if targetIndex < 0 { targetIndex = 0 }
    if targetIndex >= items.count { targetIndex = max(items.count-1, 0) }
    // Set new target offset
    targetContentOffset.pointee.x = contentOffsetForCardIndex(targetIndex)
}

0

กระทู้เก่า แต่ควรค่าแก่การกล่าวถึงสิ่งนี้:

import Foundation
import UIKit

class PaginatedCardScrollView: UIScrollView {

    convenience init() {
        self.init(frame: CGRect.zero)
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        _setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        _setup()
    }

    private func _setup() {
        isPagingEnabled = true
        isScrollEnabled = true
        clipsToBounds = false
        showsHorizontalScrollIndicator = false
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        // Asume the scrollview extends uses the entire width of the screen
        return point.y >= frame.origin.y && point.y <= frame.origin.y + frame.size.height
    }
}

ด้วยวิธีนี้คุณสามารถ a) ใช้ความกว้างทั้งหมดของ scrollview เพื่อเลื่อน / ปัดและ b) สามารถโต้ตอบกับองค์ประกอบที่อยู่นอกขอบเขตเดิมของ scrollview


0

สำหรับปัญหา UICollectionView (ซึ่งสำหรับฉันคือ UITableViewCell ของคอลเลกชันของการ์ดเลื่อนแนวนอนที่มี "สัญลักษณ์" ของการ์ดที่กำลังจะมาถึง / ก่อนหน้านี้) ฉันต้องยอมแพ้กับการใช้เพจเนทีฟของ Apple โซลูชัน githubของ Damien ทำงานได้ดีสำหรับฉัน คุณสามารถปรับขนาดทิกเกอร์ได้โดยเพิ่มความกว้างของส่วนหัวและปรับขนาดเป็นศูนย์แบบไดนามิกเมื่ออยู่ที่ดัชนีแรกเพื่อที่คุณจะได้ไม่ต้องมีขอบว่างขนาดใหญ่

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