【问题标题】:How to make something like iPhone Folders?如何制作类似 iPhone 文件夹的东西?
【发布时间】:2011-05-28 11:42:57
【问题描述】:

我想知道是否有一种方法可以将我的视图转换为类似于 iPhone 文件夹的东西。换句话说,我希望我的视图在中间的某个地方分裂,并在它下面显示一个视图。这可能吗?

编辑: 根据以下建议,我可以通过以下方式截取我的应用程序的屏幕截图:

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

不过,不知道该怎么办。

编辑:2 我已经想出了如何在我的视图中添加一些阴影,这就是我所取得的成就(裁剪以显示相关部分):

编辑:3

http://github.com/jwilling/JWFolders

【问题讨论】:

  • 啊,好吧,我在 cocoacontrols.com 上找到了你,我的好伙伴 ^^。开源 FTW! =)
  • 你确实做到了。首先感谢您帮助我开始做这件事。 ;)
  • 你可以看看OGActionChooser ;) 但他们目前似乎有服务器问题:(

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


【解决方案1】:

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

编辑:嘿嘿,它看起来不太好,但它可以工作^^

// 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:好的,发现了那个错误。使用了整个 320x480 屏幕,但不得不切断状态栏,所以它应该是 320x460 并且一切正常;)

【讨论】:

  • 我认为 CoreGraphics 或 Cocos2d 应该可以工作,但如果您可以指定要捕获的区域/或者如果您将使用 UIImageView,您可以将自动调整大小设置为始终保持在上/下角,然后稍微切掉框架
  • 感谢您的辛勤工作,它看起来不错。完成此操作后如何返回主视图?
  • 我认为 xD 有数百万种方法,但最简单的方法是删除 3 个子视图(如果变得复杂,则删除更多)。例如,如果用户触摸了外面的某个地方,我会在 touchesBegan:withEvent: 中处理它
  • [UIView animateWithDuration:2.0 动画:^{ second.center = CGPointMake(second.center.x, second.center.y-75); }];并且仅在动画周期之后将其从超级视图中删除
  • comon 将子视图保存在类变量中并不难;)顺便说一句,我会为此创建一个完整的 ViewController
【解决方案2】:

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

【讨论】:

  • 戴夫,感谢您的评论!我实际上并不想要这些图标(应该在我的回答中澄清),但我只是想将视图分成两半。
【解决方案3】:

我以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];

我在更新的拆分功能中使用了这些便利功能:

- (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;

添加返回正常功能并添加箭头将是一个很好的补充。

【讨论】:

  • 您可能有兴趣查看我不久前编写的包含所有这些内容的库。 github.com/jwilling/JWFolders
  • 嘿,是的,对不起,我应该把它贴出来。在这里,请点赞作为安慰。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 1970-01-01
  • 2020-09-23
  • 1970-01-01
  • 2010-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多