Reputation: 3836
I am trying to achieve something like flash cards for iPhone requirement. Where text contents will be in the center of card and left side (previous card), right side (next card) partially visible.
So far I tried with nicklockwood/SwipeView from github . But I failed to meet left /right side cards partial visibility requirement.
Is there any workaround / library? Please let me know here.
Upvotes: 4
Views: 2220
Reputation: 45
For my after of hours of try and try with hitTest and not get positive results i found this way.
class PassThruScrollView: UIScrollView {
var passThruViewRef: UIView?
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return point.y > passThruViewRef?.frame.height ?? 0
}
}
Just I had use this class in the component scroll view that i have inside the container view and everything was good.
Image like i had use my class
Upvotes: 1
Reputation: 2521
As my scrollview is very small (only 100p tall), the hitTest
method gets the whole ViewController which is not what I want. This solution covers any size of ScrollView and is done using 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)
}
}
The first Guard
returns the default UIView
hitTest
if the hit is outside of its boundaries.
The second one returns the UIScrollView
if the hit is inside of my container but outside of the ScrollView (which is exactly the objective of this question).
And if the hit is inside of the ScrollView, there is no need to do anything different, just let UIView handle it with its default implementation.
The only thing that needs to be handled is when your touch is inside of the container but outside of the scrollview.
This code can be reduced to only one guard
, but I thought that this way was clearer to explain the logic.
Upvotes: 1
Reputation: 1450
I would simply use a UICollectionView.
Snapping behaviour: UICollectionView with paging - setting page width
layout:
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(200, 400);
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
The cool thing about this is, you can easily implement centering behaviour when the user taps on the left or right partially visible cell (this is not so easy with some of the UIScrollView hacks out there):
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[self.collectionView scrollToItemAtIndexPath:indexPath
atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
animated:YES];
}
Upvotes: 3
Reputation: 2870
If you want to achieve this with the available UIScrollView
pagination api there is a simple trick. Besides from setting pagingEnabled
to YES
, also ensure that clipsToBounds
is set to NO
.
UIScrollView *scrollView = [UIScrollView new];
self.scrollView.pagingEnabled = YES;
self.scrollView.clipsToBounds = NO;
You now need to set the size of the scroll view to the size of your page. The scroll view will draw outside its bounds, revealing the other pages.
To be able to also start dragging outside the scroll view, you need to create a container view that contains the scroll view. You then override hitTest:
in this container view, returning the scroll view all the time:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return self.scrollView;
}
If the container view has clipToBounds
set to YES
, this will be the area where the scroll view is visible.
Upvotes: 1