如何制作像iPhone文件夹这样的东西?

时间:2010-12-20 20:51:22

标签: iphone objective-c cocoa-touch transform directory

我想知道是否有办法将视图转换为iPhone文件夹。换句话说,我希望我的视图在中间的某处分开并在其下面显示一个视图。这可能吗?

alt text

修改 根据下面的建议,我可以通过这样做截取我的应用程序的屏幕截图:

UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

不知道该怎么办。

修改:2 我已经想出如何为我的视图添加一些阴影,这就是我已经实现的目标(裁剪以显示相关部分):

alt text

修改:3

http://github.com/jwilling/JWFolders

3 个答案:

答案 0 :(得分:6)

基本的想法是拍摄你当前的状态并将其分割到某个地方。然后通过设置新框架为两个部分设置动画。我不知道如何以编程方式截取屏幕截图,因此我无法提供示例代码...

编辑:嘿,嘿,它看起来不太好,但它有效^^

// wouldn't be sharp on retina displays, instead use "withOptions" and set scale to 0.0
// UIGraphicsBeginImageContext(self.view.bounds.size);
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *f = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

CGRect fstRect = CGRectMake(0, 0, 320, 200);
CGRect sndRect = CGRectMake(0, 200, 320, 260); // was 0,200,320,280


CGImageRef fImageRef = CGImageCreateWithImageInRect([f CGImage], fstRect);
UIImage *fCroppedImage = [UIImage imageWithCGImage:fImageRef];
CGImageRelease(fImageRef);

CGImageRef sImageRef = CGImageCreateWithImageInRect([f CGImage], sndRect);
UIImage *sCroppedImage = [UIImage imageWithCGImage:sImageRef];
CGImageRelease(sImageRef);


UIImageView *first = [[UIImageView alloc]initWithFrame:fstRect];
first.image = fCroppedImage;
//first.contentMode = UIViewContentModeTop;
UIImageView *second = [[UIImageView alloc]initWithFrame:sndRect];
second.image = sCroppedImage;
//second.contentMode = UIViewContentModeBottom;

UIView *blank = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)];
blank.backgroundColor = [UIColor darkGrayColor];

[self.view addSubview:blank];
[self.view addSubview:first];
[self.view addSubview:second];

[UIView animateWithDuration:2.0 animations:^{
    second.center = CGPointMake(second.center.x, second.center.y+75);
}];

您可以取消注释两个.contentMode行,质量会提高,但在我的情况下,子视图的偏移量为10px左右(您可以通过为两个子视图设置背景颜色来查看)

//编辑2:确定发现了这个bug。已经使用了整个320x480屏幕,但不得不切断状态栏,所以它应该是320x460,一切都很好;)

答案 1 :(得分:2)

您可以为每行图标使用单独的视图,而不是拍摄视图的快照。你需要做更多的工作来重新定位东西,但是当文件夹打开时行不会是静态的(换句话说,它们会根据需要不断重绘)。

答案 2 :(得分:1)

我将relikd's代码作为基础并使其更具动态性。

您可以在调用函数时指定拆分位置和方向,并为分割图像添加了一个边框。

#define splitAnimationTime 0.5
- (void)split:(SplitDirection)splitDirection
 atYPostition:(int)splitYPosition
withRevealedViewHeight:(int)revealedViewHeight{

    // wouldn't be sharp on retina displays, instead use "withOptions" and set scale to 0.0
    // UIGraphicsBeginImageContext(self.view.bounds.size);
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *f = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGRect fullScreenRect = [self getScreenFrameForCurrentOrientation];

    CGRect upperSplitRect = CGRectMake(0, 0,fullScreenRect.size.width, splitYPosition);
    CGRect lowerSplitRect = CGRectMake(0, splitYPosition, fullScreenRect.size.width, fullScreenRect.size.height-splitYPosition);


    CGImageRef upperImageRef = CGImageCreateWithImageInRect([f CGImage], upperSplitRect);
    UIImage *upperCroppedImage = [UIImage imageWithCGImage:upperImageRef];
    CGImageRelease(upperImageRef);

    CGImageRef lowerImageRef = CGImageCreateWithImageInRect([f CGImage], lowerSplitRect);
    UIImage *lowerCroppedImage = [UIImage imageWithCGImage:lowerImageRef];
    CGImageRelease(lowerImageRef);


    UIImageView *upperImage = [[UIImageView alloc]initWithFrame:upperSplitRect];
    upperImage.image = upperCroppedImage;
    //first.contentMode = UIViewContentModeTop;

    UIView *upperBoarder = [[UIView alloc]initWithFrame:CGRectMake(0, splitYPosition, fullScreenRect.size.width, 1)];
    upperBoarder.backgroundColor = [UIColor whiteColor];
    [upperImage addSubview:upperBoarder];


    UIImageView *lowerImage = [[UIImageView alloc]initWithFrame:lowerSplitRect];
    lowerImage.image = lowerCroppedImage;
    //second.contentMode = UIViewContentModeBottom;

    UIView *lowerBoarder = [[UIView alloc]initWithFrame:CGRectMake(0, 0, fullScreenRect.size.width, 1)];
    lowerBoarder.backgroundColor = [UIColor whiteColor];
    [lowerImage addSubview:lowerBoarder];

    int reveledViewYPosition = splitYPosition;

    if(splitDirection==SplitDirectionUp){
        reveledViewYPosition = splitYPosition - revealedViewHeight;
    }


    UIView *revealedView = [[UIView alloc]initWithFrame:CGRectMake(0, reveledViewYPosition, fullScreenRect.size.width, revealedViewHeight)];
    revealedView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];


    [self.view addSubview:revealedView];
    [self.view addSubview:upperImage];
    [self.view addSubview:lowerImage];

    [UIView animateWithDuration:splitAnimationTime animations:^{
        if(splitDirection==SplitDirectionUp){
            upperImage.center = CGPointMake(upperImage.center.x, upperImage.center.y-revealedViewHeight);
        } else { //assume down
            lowerImage.center = CGPointMake(lowerImage.center.x, lowerImage.center.y+revealedViewHeight);
        }
    }];
}

这意味着我可以这样称呼它:

[self split:SplitDirectionUp atYPostition:500 withRevealedViewHeight:200];

我在更新的拆分功能中使用了这些Conveniance函数:

- (CGRect)getScreenFrameForCurrentOrientation {
    return [self getScreenFrameForOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

- (CGRect)getScreenFrameForOrientation:(UIInterfaceOrientation)orientation {

    UIScreen *screen = [UIScreen mainScreen];
    CGRect fullScreenRect = screen.bounds;
    BOOL statusBarHidden = [UIApplication sharedApplication].statusBarHidden;

    //implicitly in Portrait orientation.
    if(orientation == UIInterfaceOrientationLandscapeRight || orientation ==  UIInterfaceOrientationLandscapeLeft){
        CGRect temp = CGRectZero;
        temp.size.width = fullScreenRect.size.height;
        temp.size.height = fullScreenRect.size.width;
        fullScreenRect = temp;
    }

    if(!statusBarHidden){
        CGFloat statusBarHeight = 20;
        fullScreenRect.size.height -= statusBarHeight;
    }

    return fullScreenRect;
}

和这个枚举:

typedef enum SplitDirection
{
    SplitDirectionDown,
    SplitDirectionUp
}SplitDirection;

添加返回到normaal函数并添加箭头将是一个很好的补充。