以小于帧大小的增量分页UIScrollView

Hen*_*ing 84 uiscrollview ios scroll-paging

我有一个滚动视图,它是屏幕的宽度,但只有约70像素高.它包含许多50 x 50图标(周围有空格),我希望用户可以选择.但我总是希望滚动视图以分页的方式运行,始终在正确的中心以图标停止.

如果图标是屏幕的宽度,这不会是一个问题,因为UIScrollView的分页会处理它.但是因为我的小图标远小于内容大小,所以它不起作用.

我之前在应用程序调用AllRecipes中看到过这种行为.我只是不知道该怎么做.

有关如何在每个图标大小的基础上进行分页工作的任何想法?

Ben*_*ieb 119

尝试使您的滚动视图小于屏幕大小(宽度方式),但取消选中IB中的"剪辑子视图"复选框.然后,在它上面覆盖透明的userInteractionEnabled = NO视图(全宽),覆盖hitTest:withEvent:以返回滚动视图.这应该会给你你想要的东西.有关详细信息,请参阅此答案.

  • 这是一个美丽的解决方案.我没有想过要覆盖hitTest:函数,这几乎是这种方法唯一的缺点.做得很好. (8认同)
  • 这非常有效,但我建议不要简单地返回scrollView,返回[scrollView hitTest:指向withEvent:event],以便事件正确通过.例如,在一个充满UIButtons的滚动视图中,按钮仍然可以这样工作. (8认同)
  • 请注意,这不适用于tableview或collectionView,因为它不会在框架外部呈现内容.请参阅下面的答案 (2认同)

Spl*_*lit 63

还有另一个解决方案可能比将滚动视图与另一个视图重叠并覆盖hitTest要好一点.

您可以继承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
Run Code Online (Sandbox Code Playgroud)

  • 直接`return [self.superview pointInside:[self convertPoint:point toView:self.superview] withEvent:event];`@amrox @Split如果您有一个充当剪裁视图的超级视图,则不需要responseInsets. (6认同)
  • 我喜欢这个解决方案,虽然我必须将parentLocation更改为"[self convertPoint:point toView:self.superview]"才能使其正常工作. (5认同)

Ang*_*qui 14

我看到很多解决方案,但它们非常复杂.拥有小页面但仍保持所有区域可滚动的更简单的方法是使滚动更小并移动scrollView.panGestureRecognizer到父视图.这些是步骤:

  1. 减少scrollView大小ScrollView大小小于父级

  2. 确保您的滚动视图已分页,并且不会剪切子视图 在此输入图像描述

  3. 在代码中,将scrollview平移手势移动到全宽的父容器视图:

    override func viewDidLoad() {
        super.viewDidLoad()
        statsView.addGestureRecognizer(statsScrollView.panGestureRecognizer)
    }
Run Code Online (Sandbox Code Playgroud)


col*_*nta 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;
    }
} 
Run Code Online (Sandbox Code Playgroud)


vis*_*ish 5

- (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;
} 
Run Code Online (Sandbox Code Playgroud)

kPageWidth 是您希望页面的宽度。kPageOffset 是如果您不希望单元格左对齐(即,如果您希望它们居中对齐,请将其设置为单元格宽度的一半)。否则,它应该为零。

这也将只允许一次滚动一页。