iOS滑动视图,部分可见的下一个和上一个视图

4
我正在尝试实现类似于 iPhone 上的 闪卡 的需求。其中文本内容将位于卡片中心,左侧(上一张卡片)、右侧(下一张卡片)部分可见。

enter image description here

到目前为止,我已经尝试使用来自github的nicklockwood/SwipeView。但是我无法满足左/右侧卡片部分可见的要求。是否有任何解决方法或库?请在此处告诉我。
4个回答

3
我会简单地使用UICollectionView。
对齐行为:UICollectionView分页-设置页面宽度 布局:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(200, 400);
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

好处在于,当用户点击左边或右边部分可见的单元格时,您可以轻松实现居中行为(这在某些UIScrollView hack中并不容易实现):

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [self.collectionView scrollToItemAtIndexPath:indexPath
                                atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
                                        animated:YES];
}

我可以证实这种方法非常有效。这些类大多只是UIScrollView的子类,因此可以通过迭代它们的子视图直到获取到UIScrollView来进行相当自定义。 - user916367
@stefreak - 哇!这是个好主意。我一定会尝试一下。谢谢回复。 - byJeevan
1
@Rollo UICollectionViewUIScrollView 的子类,无需遍历其子视图。 - stefreak
1
@jeekOnline 哈哈,没问题!我什么都用UICollectionView,因为它太棒了! - stefreak

1
如果您想使用可用的UIScrollView分页API来实现此操作,有一个简单的技巧。除了将pagingEnabled设置为YES之外,还要确保将clipsToBounds设置为NO
UIScrollView *scrollView = [UIScrollView new];
self.scrollView.pagingEnabled = YES;
self.scrollView.clipsToBounds = NO;

你现在需要将滚动视图的大小设置为页面的大小。滚动视图会绘制超出其边界的部分,显示其他页面。
为了能够在滚动视图外部开始拖动,你需要创建一个包含滚动视图的容器视图。然后在此容器视图中覆盖 hitTest: 方法,始终返回滚动视图。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    return self.scrollView;
}

如果容器视图的clipToBounds设置为YES,这将是滚动视图可见的区域。

1

由于我的滚动视图非常小(仅100像素高),因此hitTest方法获取整个视图控制器,这不是我想要的。这个解决方案适用于任何大小的ScrollView,并使用Swift 4完成:

class ScrollViewContainer: UIView {

@IBOutlet weak var scrollView: UIScrollView!

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

    guard self.bounds.contains(point) else {
        return super.hitTest(point, with: event)
    }

    guard self.scrollView.frame.contains(point) else {
        return self.scrollView
    }

    return super.hitTest(point, with: event)
   }
}

第一个Guard如果点击在其范围之外,则返回默认的UIViewhitTest
第二个Guard如果点击在容器内但在ScrollView之外,则返回UIScrollView(这正是此问题的目标)。
如果点击在ScrollView内部,则不需要进行任何不同的操作,只需让UIView使用其默认实现处理即可。
唯一需要处理的是当您的触摸位于容器内但位于滚动视图之外时。
此代码可以缩减为只有一个Guard,但我认为这种方式更清晰地解释了逻辑。

1
正是我所需要的!如果有人拥有一个包含一个UIScrollView的容器,并且想将事件传递给UIScrollView事件,如果您不触摸它,则使用此代码! - Yetispapa

1

在尝试多次使用hitTest并未获得积极结果之后,我找到了这种方法。

class PassThruScrollView: UIScrollView {

    var passThruViewRef: UIView?

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {

        return point.y > passThruViewRef?.frame.height ?? 0        
    }    
}

我刚刚在容器视图中的滚动视图组件中使用了这个类,一切都很好。

就像我使用我的类一样

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接