我有一个网格视图。该网格中的每个单元格都是可点击的。如果单击单元格,则必须将另一个视图控制器呈现为模态视图控制器。呈现的视图控制器必须从右向左滑入。之后,可以通过幻灯片关闭 modalviewcontroller。我如何实现这一目标?我有一些图片来展示它:
两个视图都是独立的视图控制器。
[解决方案]
马修的回答为我指明了正确的方向。我需要的是一个 UIPanGestureRecognizer。因为 UISwipeGestureRecognizer 只注册一次滑动,我需要视图跟随用户的手指。我做了以下事情来完成它:
如果在我的 UICollectionView 中点击了我的单元格,则需要弹出额外的视图。所以我首先实现了以下代码:
/* The next piece of code represents the action called when a touch event occours on
one of the UICollectionviewCells.
*/
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSString* release_id = releases[indexPath.row][0];
// Next boolean makes sure that only one new view can be seen. In the past, a user can click multiple cells and it allocs multiple instances of ReleaseViewController.
if(releaseViewDismissed) {
// Alloc UIViewController and initWithReleaseID does a request to a server to initialize some data.
ReleaseViewController *releaseViewController = [[ReleaseViewController alloc] initWithReleaseID: release_id];
// Create a new UIView and assign the height and width of the grid
UIView *releaseViewHolder = [[UIView alloc] initWithFrame:CGRectMake(gridSize.width, 0, gridSize.width, gridSize.height)];
// Add the view of the releaseViewController as a subview of the newly created view.
[releaseViewHolder addSubview:releaseViewController.view];
// Then add the UIView with the view of the releaseViewController to the current UIViewController's view.
[self.view addSubview:releaseViewHolder];
// Place the x coordinate of the new view to the same as width of the screen. Then after that get the x to 0 with an animation.
[UIView animateWithDuration:0.3 animations:^{
releaseViewHolder.frame = CGRectMake(0, 0, releaseViewHolder.frame.size.width, releaseViewHolder.frame.size.height);
// This is important. alloc an UIPanGestureRecognizer and set the method that handles those events to handleSwipes.
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipes:)];
// Add the UIPanGestureRecognizer to the created view.
[releaseViewHolder addGestureRecognizer:_panGestureRecognizer];
releaseViewDismissed = NO;
}];
}
}
然后我的handleSwipes如下:
-(void)handleSwipes:(UIPanGestureRecognizer *)sender {
CGPoint translatedPoint = [(UIPanGestureRecognizer*)sender translationInView:self.view];
CGPoint translation = [sender translationInView:sender.view];
CGRect newFrame = [sender view].frame;
[sender setTranslation:CGPointZero inView:sender.view];
if (sender.state == UIGestureRecognizerStateChanged)
{
newFrame.origin.x = newFrame.origin.x + translation.x;
// Makes sure it can't go beyond the left of the screen.
if(newFrame.origin.x > 0) {
[sender view].frame = newFrame;
}
}
if(sender.state == UIGestureRecognizerStateEnded){
CGRect newFrame = [sender view].frame;
CGFloat velocityX = (0.3*[(UIPanGestureRecognizer*)sender velocityInView:self.view].x);
// If the user swipes less then half of the screen, it has to bounce back.
if(newFrame.origin.x < ([sender view].bounds.size.width/2)) {
newFrame.origin.x = 0;
}
// If a user swipes fast, the velocity is added to the new x of the frame.
if(newFrame.origin.x + velocityX > ([sender view].bounds.size.width/2)) {
newFrame.origin.x = [sender view].bounds.size.width + velocityX;
releaseViewDismissed = YES;
}
// Do it all with a animation.
[UIView animateWithDuration:0.25
animations:^{
[sender view].frame = newFrame;
}
completion:^(BOOL finished){
if(releaseViewDismissed) {
// Finally remove the new view from the superView.
[[sender view] removeFromSuperview];
}
}];
}
}