3

最初はそれほど難しくないと思っていましたが、思ったよりも少し難しいことがわかりました。

iOS フォルダを開く

現時点では、私のコードはhttps://github.com/jwilling/JWFoldersに基づいています。ただし、あまりクリーンではありません。最大の問題は、フォルダーが開くたびにスクリーンショットを取得することです (renderInContext: は CPU にかなりの負担をかけるため、非常に低い fps であることがわかります)。それを除けば、この実装は Apple のアニメーションほどきれいで洗練されたものではありません。

Apple は、遅延のないピクセル単位の完璧なアニメーションを実現しています。私も同じようにしたいです!これを行う最善の方法は何ですか/これをどのように行いますか-きれいにコード化され、見栄えがよく、滑らかなアニメーションですか? 現時点では、私のアニメーションにはこれらすべての領域が欠けており、どうすればもっとうまくできるか (Apple のように) 困惑しています。

-

私はコードを懇願しているわけではなく、最善の方法/方法です。しかし、先に進んでコーディングしたい場合は、ノーと言う方法はありません (それは間違いなく価値があるでしょう)!!

4

1 に答える 1

3

Springboardをいくつかのビューに分割します。各ビューは1行のアイコンです。
フォルダアイコンをクリックすると、次のすべてのビューをアニメーション化して上下に移動し、フォルダのコンテンツを配置します。同時に、フォルダのコンテンツを表すサブビューを追加し、必要に応じてそのサイズと位置を同じ速度でアニメーション化します。

画面全体にまたがる背景画像をサポートするために、それを断片に切り取り、この断片を背景画像ビューとして各行のビューに追加します。


アニメーションを任意のタップ位置から開始して、簡単で汚いサンプルコードを作成しました。これは、githubで完全なプロジェクトとしても利用できます。

スクリーンショット

@interface ViewController ()

@property (nonatomic, strong) UIView *upperView;
@property (nonatomic, strong) UIView *lowerView;

@property (nonatomic, strong) UIImageView *upperImageView;
@property (nonatomic, strong) UIImageView *lowerImageView;

@property (nonatomic, strong) UIView *folderContentsView;

@property (nonatomic, assign) CGRect startRect;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIImage *bgImg = [UIImage imageNamed:@"bg.png"];
    self.upperImageView = [[UIImageView alloc] initWithImage:bgImg];
    self.lowerImageView = [[UIImageView alloc] initWithImage:bgImg];
    [self.upperImageView setContentMode:UIViewContentModeTop];
    [self.lowerImageView setContentMode:UIViewContentModeTop];

    self.upperView = [[UIView alloc] initWithFrame:self.upperImageView.frame];
    self.lowerView = [[UIView alloc] initWithFrame:self.lowerImageView.frame];
    [self.upperView addSubview:_upperImageView];
    [self.lowerView addSubview:_lowerImageView];

    [self.view addSubview:_lowerView];
    [self.view addSubview:_upperView];

    UITapGestureRecognizer *upperTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                         action:@selector(openOverlay:)];
    UITapGestureRecognizer *lowerTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                         action:@selector(openOverlay:)];

    [self.upperView setUserInteractionEnabled:YES];
    [self.upperView addGestureRecognizer:upperTapRecognizer];
    [self.upperView setClipsToBounds:YES];

    [self.lowerView setUserInteractionEnabled:YES];
    [self.lowerView addGestureRecognizer:lowerTapRecognizer];
    [self.lowerView setClipsToBounds:YES];

    self.folderContentsView = [[UIView alloc] initWithFrame:CGRectZero];
    self.folderContentsView.backgroundColor = [UIColor redColor];
    UITapGestureRecognizer *closeTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                         action:@selector(closeOverlay:)];
    [self.folderContentsView addGestureRecognizer:closeTapRecognizer];
    [self.view addSubview:self.folderContentsView];

    [self.folderContentsView addSubview:[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bgFolder.png"]]];
    [self.folderContentsView setClipsToBounds:YES];

    self.startRect = [self.upperView frame];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

-(void)openOverlay:(UITapGestureRecognizer *) sender
{
    [self.upperView setUserInteractionEnabled:NO];
    [self.lowerView setUserInteractionEnabled:NO];
    CGPoint location = [sender locationInView:sender.view];

    self.folderContentsView.frame = CGRectMake(0, location.y,
                                    _lowerView.frame.size.width, 0);
    self.lowerView.frame = CGRectMake(0, location.y,
                                      _lowerView.frame.size.width, _lowerView.frame.size.height);
    self.upperView.frame = CGRectMake(0, 0,
                                      _upperView.frame.size.width, location.y);
    self.lowerImageView.frame = CGRectMake(_lowerImageView.frame.origin.x, -location.y,
                                           _lowerImageView.frame.size.width, _lowerImageView.frame.size.height);

    [UIView animateWithDuration:.5 animations:^{
        self.folderContentsView.frame = CGRectMake(0, location.y,
                                    _lowerView.frame.size.width, 200);
        self.lowerView.frame = CGRectOffset(_lowerView.frame, 0, 200);
    }];    
}

-(void) closeOverlay:(UITapGestureRecognizer*) sender
{
    [UIView animateWithDuration:.5 animations:^{
        self.lowerView.frame = CGRectOffset(_lowerView.frame, 0, -200);
        self.folderContentsView.frame = CGRectMake(0, self.folderContentsView.frame.origin.y,
                                        self.folderContentsView.frame.size.width, 0);
    } completion:^(BOOL finished) {
        [self.upperView setUserInteractionEnabled:YES];
        [self.lowerView setUserInteractionEnabled:YES];
        self.upperView.frame = self.startRect;
    }];
}


@end

レイヤーで同じ背景を備えた2つのビュー。タップが検出されると、両方のビューのサイズが変更され、上部のビューはタップのy座標で終了し、下部のビューはそこから開始します。lowerViewに追加されたUIImageViewは反対方向に移動されるため、画像は所定の位置に留まります。

これで、contentViewが追加され、同じ速度でサイズ変更されている間、lowerViewが下にスライドします。

ご覧のとおり、画像のレンダリングやその他の難しいアクションは必要ありません。UIViewアニメーションだけです。

ここに画像の説明を入力してください

于 2012-12-30T13:45:49.203 に答える