Iphone 垂直视图?
我正在努力开发iOS,我希望有人能给我一个建议。我想实现一个UIView堆栈,看起来就像一副牌。用户应该能够用触摸刷出“卡片”。我想到了带分页的UIScrollView,它能给人一种卡片是分开的印象。但是,UIScrollView可以从左侧或右侧显示内容的位置水平滑动。我想把我的牌牌放在屏幕中间,这样用户就可以从卡片上刷卡而不看卡出现在左边或右边。 此外,我还考虑使用触摸方法(touchsbegind、touchsmoved等)来移动视图。它可以工作。。。但我担心我无法重现卡的正确机制(摩擦、刷短时的反弹效应等等) 有人能给我指一个合适的技巧或者一些指导吗?我已经做了一些研究,但是我找不到任何有用的东西 这是我想要达到的效果的图像 我想要实现的是把牌从牌堆里刷出来Iphone 垂直视图?,iphone,objective-c,ios,uiscrollview,Iphone,Objective C,Ios,Uiscrollview,我正在努力开发iOS,我希望有人能给我一个建议。我想实现一个UIView堆栈,看起来就像一副牌。用户应该能够用触摸刷出“卡片”。我想到了带分页的UIScrollView,它能给人一种卡片是分开的印象。但是,UIScrollView可以从左侧或右侧显示内容的位置水平滑动。我想把我的牌牌放在屏幕中间,这样用户就可以从卡片上刷卡而不看卡出现在左边或右边。 此外,我还考虑使用触摸方法(touchsbegind、touchsmoved等)来移动视图。它可以工作。。。但我担心我无法重现卡的正确机制(摩擦、刷
非常感谢 Icarousel使用UIImageView实现了精确的内置滚动
。这里有几个不同的效果,我忘了你描述的那个的名字 我想你需要一次刷卡,将牌堆顶部的牌“洗牌”到牌堆底部,露出牌堆上的第二张牌,如下所示: 动画在现实生活中要平滑得多。我不得不使用低帧速率使动画GIF变小 一种方法是创建
UIView
的子类来管理卡片视图的堆栈。让我们将经理视图称为一个BoardView
。我们将给它两种公开的方法:一种用于将顶部的牌洗牌到底部,另一种用于将底部的牌洗牌到底部
@interface BoardView : UIView
- (IBAction)goToNextCard;
- (IBAction)goToPriorCard;
@end
@implementation BoardView {
BOOL _isRestacking;
}
我们将使用\u isRestacking
变量跟踪board视图是否正在设置卡向一侧移动的动画
BoardView
将其所有子视图视为卡片视图。它负责将它们堆叠起来,顶部的卡片居中。在您的屏幕截图中,您以稍微随机的数量偏移较低的卡。我们可以通过随机旋转较低的卡片使它看起来更性感。此方法对视图应用小的随机旋转:
- (void)jostleSubview:(UIView *)subview {
subview.transform = CGAffineTransformMakeRotation((((double)arc4random() / UINT32_MAX) - .5) * .2);
}
我们希望在添加子视图时将其应用于每个子视图:
- (void)didAddSubview:(UIView *)subview {
[self jostleSubview:subview];
}
每当视图的大小发生变化或视图被赋予新的子视图时,系统都会发送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;
}
}
现在我们准备好处理洗牌了。要“转到下一张卡”,我们需要设置动画,将顶部卡移到一边,然后将其移动到子视图堆叠顺序的底部,然后将其设置回中间。我们还需要轻推所有其他卡牌的位置,因为它们都已移到接近堆栈顶部的位置
- (void)goToNextCard {
if (self.subviews.count < 2)
return;
completion:^(BOOL finished) {
_isRestacking = NO;
[self sendSubviewToBack:movingView];
在完成块中,我们将卡移动到堆栈的底部
- (void)goToNextCard {
if (self.subviews.count < 2)
return;
completion:^(BOOL finished) {
_isRestacking = NO;
[self sendSubviewToBack:movingView];
要将现在最底部的卡移回堆栈,并轻推所有其他卡,我们只需调用layoutSubviews
。但是我们不应该直接调用layoutSubviews
,因此我们使用适当的API:setNeedsLayout
,后跟layoutifneed
。我们在动画块中调用layoutifneedd
,以便将卡片动画化到其新位置
[self setNeedsLayout];
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction animations:^{
[self jostleSubview:movingView];
[self layoutIfNeeded];
} completion:nil];
}];
}
这就是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];
}];
}
-(无效)GoToPriorioCard{
if(self.subviews.count<2)
回来
UIView*movingView=[self.subviews objectAtIndex:0];
[UIView animateWithDuration:1延迟:0选项:UIViewAnimationOptionCurveEaseInOut动画:^{
_isRestacking=是;
CGPoint center=movingView.center;
center.x=-movingView.frame.size.height/2;
movingView.center=中心;
movingView.transform=CGAffineTransformMakeRotation(-M_PI_4);
}完成:^(布尔完成){
_isRestacking=否;
UIView*priorTopView=self.subviews.lastObject;
[self-BringSubview to Front:movingView];
[self-setNeedsLayout];
[UIView animateWithDuration:1延迟:0选项:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionLowUserInteraction动画:^{
[自碰撞子视图:优先级视图];
[需要自行布局];
}完成:无];
}];
}
一旦你有了BoardView,你只需要附加一个滑动手势识别器,它向你发送goToNextCard
信息,另一个滑动手势识别器向你发送goToPriorCard
信息。您需要添加一些子视图来充当卡片
另一个细节:要使卡的边缘在碰撞时看起来平滑,需要在Info.plist
中将uiviewedgeanialiasing
设置为YES
你可以在这里找到我的测试项目:在读了三四遍之后,我仍然不确定你的问题是什么。对我来说,不清楚你想要实现什么(尽管我没有否决你的问题)。也许一个插图可以帮助解释你想看到的效果。当然。。。图示马上就到。抱歉搞混了。那么,有什么问题吗?你有代表一副牌的视图吗?在该视图上放置一个UIImageView,该视图将表示顶部卡。对于您的视图,实现用户交互方法(或UIgestureRecognitor)。用户在视图上滑动后,更改UIImageView(表示顶部卡的imageview)图像。为什么不使用lay