mli*_*hwa 0 iphone objective-c uiscrollview ios
我正在努力与一些iOS开发,我希望有人能够帮助我提出建议.我想实现一堆看起来像一副牌的UIViews.用户应该可以通过触摸来刷出"卡片".我想到了带有pagingEnabled的UIScrollViews,给人的印象是卡片是分开的.但是,UIScrollView可以从左侧或右侧水平滑动.我希望我的卡片组位于屏幕中间,这样用户就可以从卡片上刷卡而不会看到卡片出现在左侧或右侧.此外,我正在考虑使用触摸方法(touchesBegan,touchesMoved等)来移动视图.它可以工作...但我担心我不能重现卡的正确机制(摩擦,弹跳效果,当滑动短,等等..).
有人可以指点我一个适当的技术或建议一些教程?我已经做了一些研究,但我找不到任何有用的东西.
这是我想要实现的效果的图像.

而我想要实现的是将卡片刷出卡座.
非常感谢!
rob*_*off 13
我想你想要一个滑动来获取堆栈的顶部卡并将其"洗牌"到堆栈的底部,显示堆栈上的第二张卡,如下所示:

现实生活中的动画更加流畅.我不得不使用低帧速率来使动画GIF变小.
一种方法是创建一个UIView管理卡片视图堆栈的子类.我们打电话给经理视图a BoardView.我们将给它两种公共方法:一种用于将顶部卡片移动到底部,另一种用于将底部卡片移动到顶部.
@interface BoardView : UIView
- (IBAction)goToNextCard;
- (IBAction)goToPriorCard;
@end
@implementation BoardView {
BOOL _isRestacking;
}
Run Code Online (Sandbox Code Playgroud)
我们将使用该_isRestacking变量来跟踪电路板视图是否将卡的移动设置为侧面.
A BoardView将其所有子视图视为卡片视图.顶部卡片居中,它将它们堆叠起来.在您的屏幕截图中,您可以通过略微随机的数量来抵消较低的卡片.我们可以通过随机旋转较低的卡片使它看起来更性感.此方法对视图应用小的随机旋转:
- (void)jostleSubview:(UIView *)subview {
subview.transform = CGAffineTransformMakeRotation((((double)arc4random() / UINT32_MAX) - .5) * .2);
}
Run Code Online (Sandbox Code Playgroud)
我们希望将它应用于每个子视图,因为它已添加:
- (void)didAddSubview:(UIView *)subview {
[self jostleSubview:subview];
}
Run Code Online (Sandbox Code Playgroud)
layoutSubviews只要视图的大小发生变化,或者视图已被赋予新的子视图,系统就会发送.我们将利用它来在板视图边界的中间布置堆栈中的所有卡.但是如果视图当前正在为卡片设置动画,我们不想进行布局,因为它会杀死动画.
- (void)layoutSubviews {
if (_isRestacking)
return;
CGRect bounds = self.bounds;
CGPoint center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
UIView *topView = self.subviews.lastObject;
CGFloat offset = 10.0f / self.subviews.count;
for (UIView *view in self.subviews.reverseObjectEnumerator) {
view.center = center;
if (view == topView) {
// Make the top card be square to the edges of the screen.
view.transform = CGAffineTransformIdentity;
}
center.x -= offset;
center.y -= offset;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们已经准备好应对洗牌了.要"转到下一张卡片",我们需要动画将顶部卡片移到侧面,然后将其移动到子视图堆叠顺序的底部,然后将其动画回中间.我们还需要轻推所有其他牌的位置,因为他们都已经靠近堆栈的顶部.
- (void)goToNextCard {
if (self.subviews.count < 2)
return;
Run Code Online (Sandbox Code Playgroud)
首先,我们将顶部卡片的移动设置为侧面.为了使它看起来很性感,我们在移动时旋转卡片.
UIView *movingView = self.subviews.lastObject;
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
_isRestacking = YES;
CGPoint center = movingView.center;
center.x = -hypotf(movingView.frame.size.width / 2, movingView.frame.size.height / 2);
movingView.center = center;
movingView.transform = CGAffineTransformMakeRotation(-M_PI_4);
}
Run Code Online (Sandbox Code Playgroud)
在完成块中,我们将卡移动到堆栈的底部.
completion:^(BOOL finished) {
_isRestacking = NO;
[self sendSubviewToBack:movingView];
Run Code Online (Sandbox Code Playgroud)
然后将现在底部的卡片移回堆叠,并轻推所有其他卡片,我们只需拨打电话layoutSubviews.但是我们不应该layoutSubviews直接调用,所以我们使用适当的API:setNeedsLayout接下来layoutIfNeeded.我们layoutIfNeeded在动画块内部调用,以便将卡片设置为新的位置.
[self setNeedsLayout];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction animations:^{
[self jostleSubview:movingView];
[self layoutIfNeeded];
} completion:nil];
}];
}
Run Code Online (Sandbox Code Playgroud)
那是结束了goToNextCard.我们可以这样做goToPriorCard:
- (void)goToPriorCard {
if (self.subviews.count < 2)
return;
UIView *movingView = [self.subviews objectAtIndex:0];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
_isRestacking = YES;
CGPoint center = movingView.center;
center.x = -movingView.frame.size.height / 2;
movingView.center = center;
movingView.transform = CGAffineTransformMakeRotation(-M_PI_4);
} completion:^(BOOL finished) {
_isRestacking = NO;
UIView *priorTopView = self.subviews.lastObject;
[self bringSubviewToFront:movingView];
[self setNeedsLayout];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction animations:^{
[self jostleSubview:priorTopView];
[self layoutIfNeeded];
} completion:nil];
}];
}
Run Code Online (Sandbox Code Playgroud)
一旦你有了BoardView,你只需要附上一个向其发送goToNextCard消息的轻扫手势识别器,以及另一个向其发送消息的轻扫手势识别器goToPriorCard.而且你需要添加一些子视图来充当卡片.
另一个细节:拿到卡片的边缘时,他们推挤看起来光滑,你需要设置UIViewEdgeAntialiasing到YES你Info.plist.
您可以在此处找到我的测试项目:http://dl.dropbox.com/u/26919672/cardstack.zip
| 归档时间: |
|
| 查看次数: |
1232 次 |
| 最近记录: |