谷歌现在喜欢iOS上的界面
所以,我绝对喜欢Android上Google Now的卡片界面。。最近它甚至出现在iOS上 是否有任何教程或示例项目可以帮助我为iOS应用程序创建卡片界面 根据我的研究,我已经能够使用自定义UICollectionViewFlowLayout在某种程度上复制“堆叠”卡片谷歌现在喜欢iOS上的界面,ios,iphone,objective-c,google-now,Ios,Iphone,Objective C,Google Now,所以,我绝对喜欢Android上Google Now的卡片界面。。最近它甚至出现在iOS上 是否有任何教程或示例项目可以帮助我为iOS应用程序创建卡片界面 根据我的研究,我已经能够使用自定义UICollectionViewFlowLayout在某种程度上复制“堆叠”卡片 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { NSArray *allAttributesInRect = [super layoutAttr
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *allAttributesInRect = [super layoutAttributesForElementsInRect:rect];
CGPoint centerPoint = CGPointMake(CGRectGetMidX(self.collectionView.bounds), CGRectGetMidY(self.collectionView.bounds));
for (UICollectionViewLayoutAttributes *cellAttributes in allAttributesInRect)
{
if (CGRectContainsPoint(cellAttributes.frame, centerPoint))
{
cellAttributes.transform = CGAffineTransformIdentity;
cellAttributes.zIndex = 1.0;
}
else
{
cellAttributes.transform = CGAffineTransformMakeScale(0.75, 0.75);
}
}
return allAttributesInRect;
}
然后我将最小行距设置为负值,使它们看起来“堆叠”
在滚动时,我希望卡片保持在底部,只有一辆车可以放大并在屏幕上居中显示。然后我会把那张卡从屏幕上滚下来,然后从堆栈中的下一张“卡”会从堆栈中向上滚动,并在屏幕上居中。我猜这将是动态调整最小行距?我认为没有任何教程或课程能完全满足您的要求。但是,如果您不介意只针对iOS6及更高版本,您可以使用
UICollectionView
。使用标准的垂直流布局,要实现您想要实现的目标应该不会那么困难。看看:
- WWDC 2012年会议205
UICollectionView
的基本概念,您将能够立即构建卡片布局
更新
我创建了一个快速示例来展示一种处理单元格平移的潜在方法。确保添加必要的代码以从集合视图中删除项目,该视图位于//插入代码以删除此处的单元格
,然后它将填补您通过删除单元格而创建的空白
CLCollectionViewCell.h
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
@interface CLCollectionViewCell : UICollectionViewCell <UIGestureRecognizerDelegate>
@property (assign, setter = setDeleted:) BOOL isDeleted;
@property (strong) UIPanGestureRecognizer *panGestureRecognizer;
@end
#导入
#进口
@接口CLCollectionViewCell:UICollectionViewCell
@属性(assign,setter=setDeleted:)BOOL被删除;
@属性(强)UIPangestureRecognitor*PangestureRecognitor;
@结束
CLCollectionViewCell.m
#import "CLCollectionViewCell.h"
@implementation CLCollectionViewCell
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
// Create a pan gesture recognizer with self set as the delegate and add it the cell
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognizerDidChange:)];
[_panGestureRecognizer setDelegate:self];
[self addGestureRecognizer:_panGestureRecognizer];
// Don't clip to bounds since we want the content view to be visible outside the bounds of the cell
[self setClipsToBounds:NO];
// For debugging purposes only: set the color of the content view
[[self contentView] setBackgroundColor:[UIColor greenColor]];
}
return self;
}
- (void)panGestureRecognizerDidChange:(UIPanGestureRecognizer *)panGestureRecognizer {
if ([self isDeleted]) {
// The cell should be deleted, leave the state of the cell as it is
return;
}
// Percent holds a float value between -1 and 1 that indicates how much the user moved his finger relative to the width of the cell
CGFloat percent = [panGestureRecognizer translationInView:self].x / [self frame].size.width;
switch ([panGestureRecognizer state]) {
case UIGestureRecognizerStateChanged: {
// Create the 'throw animation' and base its current state on the percent
CGAffineTransform moveTransform = CGAffineTransformMakeTranslation(percent * [self frame].size.width, 0.f);
CGAffineTransform rotateTransform = CGAffineTransformMakeRotation(percent * M_PI / 20.f);
CGAffineTransform transform = CGAffineTransformConcat(moveTransform, rotateTransform) ;
// Apply the transformation to the content view
[[self contentView] setTransform:transform];
break;
}
case UIGestureRecognizerStateFailed:
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
// Delete the current cell if the absolute value of the percent is above O.7 or the absolute value of the velocity of the gesture is above 600
if (fabsf(percent) > 0.7f || fabsf([panGestureRecognizer velocityInView:self].x) > 600.f) {
// The direction is -1 if the gesture is going left and 1 if it's going right
CGFloat direction = percent < 0.f ? -1.f : 1.f;
// Multiply the direction to make sure the content view will be removed entirely from the screen
direction *= 1.5f;
// Create the transform based on the direction of the gesture
CGAffineTransform moveTransform = CGAffineTransformMakeTranslation(direction * [self frame].size.width , 0.f);
CGAffineTransform rotateTransform = CGAffineTransformMakeRotation(direction * M_PI / 20.f);
CGAffineTransform transform = CGAffineTransformConcat(moveTransform, rotateTransform);
// Calculate the duration of the animation based on the velocity of the pan gesture recognizer and normalize abnormal high and low values
CGFloat duration = fabsf(1000.f / [panGestureRecognizer velocityInView:self].x);
duration = duration > 2.f ? duration = 2.f : duration;
duration = duration < 0.2f ? duration = 0.2f : duration;
// Animate the 'throwing away' of the cell and update the collection view once it's completed
[UIView animateWithDuration:duration
animations:^(){
[[self contentView] setTransform:transform];
}
completion:^(BOOL finished){
[self setDeleted:YES];
// Insert code to delete the cell here
// e.g. [collectionView deleteItemsAtIndexPaths:@[[collectionView indexPathForCell:self]]];
}];
} else {
// The cell shouldn't be deleted: animate the content view back to its original position
[UIView animateWithDuration:1.f animations:^(){
[[self contentView] setTransform:CGAffineTransformIdentity];
}];
}
break;
}
default: {
break;
}
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
// Return YES to make sure the pan gesture recognizer doesn't interfere with the gesture recognizer of the collection view
return YES;
}
@end
#导入“CLCollectionViewCell.h”
@实现CLCollectionViewCell
-(id)initWithCoder:(NSCoder*)aDecoder{
if(self=[super initWithCoder:aDecoder]){
//创建一个以self set作为代理的平移手势识别器,并将其添加到单元格中
_panGestureRecognizer=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizerDidChange:)];
[\u PangestureRecognitor setDelegate:self];
[自添加GestureRecognitor:_PangestureRecognitor];
//不要剪裁到边界,因为我们希望内容视图在单元格边界之外可见
[自设置ClipsToBounds:否];
//仅用于调试目的:设置内容视图的颜色
[[self-contentView]setBackgroundColor:[UIColor-greenColor]];
}
回归自我;
}
-(void)PangESTURE识别器DIDCHANGE:(UIPangESTURE识别器*)PangESTURE识别器{
如果([自删除]){
//应删除单元格,保持单元格的状态不变
返回;
}
//百分比包含一个介于-1和1之间的浮点值,该值指示用户相对于单元格宽度移动手指的程度
CGFloat百分比=[PangestureRecognitor TranslationView:self].x/[self frame].size.width;
开关([PangestureRecognitor状态]){
案例UIgestureRecognitzerStateChanged:{
//创建“抛出动画”并根据百分比确定其当前状态
CGAffineTransform moveTransform=CGAffineTransformMakeTransform(百分比*[self frame].size.width,0.f);
CGAffineTransform rotateTransform=CGAffineTransformMakeRotation(百分比*M_PI/20.f);
CGAffineTransform transform=CGAffineTransformConcat(移动变换,旋转变换);
//将转换应用于内容视图
[[self-contentView]设置转换:转换];
打破
}
案例UIgestureRecognitzerStateFailed:
案例UIgestureRecognitzerStateEnded:
案例UIgestureRecognitizerState已取消:{
//如果百分比的绝对值大于0.7或手势速度的绝对值大于600,则删除当前单元格
如果(fabsf(百分比)>0.7f | | fabsf([PangestureRecognitor VelocityView:self].x)>600.f){
//如果手势向左,方向为-1,如果手势向右,方向为1
CGFloat方向=百分比<0.f?-1.f:1.f;
//乘以方向以确保内容视图将完全从屏幕上删除
方向*=1.5f;
//基于手势的方向创建变换
CGAffineTransform moveTransform=CGAffineTransformMakeTransform(方向*[自帧]).size.width,0.f);
CGAffineTransform rotateTransform=CGAffineTransformMakeRotation(方向*M_PI/20.f);
CGAffineTransform transform=CGAffineTransformConcat(移动变换,旋转变换);
//根据平移手势识别器的速度计算动画的持续时间,并对异常的高值和低值进行规格化
CGFloat duration=fabsf(1000.f/[pangestureinrecognizer-velocityview:self].x);
持续时间=持续时间>2.f?持续时间=2.f:持续时间;
持续时间=持续时间<0.2f?持续时间=0.2f:持续时间;
//设置单元格“丢弃”的动画,并在完成后更新集合视图
[UIView animateWithDuration:持续时间
动画:^(){
[[self-contentView]设置转换:转换];
}
完成:^(布尔完成){