1

本のページ間を左右にスライドできるアプリを作成しています (カード デッキのようにカバーまたは表示)。上下にスライドすると、設定ページが下にスライド (およびカバー) または上にスライド (および明らかにする)本の詳細情報に。

基本的に、これは「カードデッキ」のスライド機能であり、使用を検討しているこのプロジェクトhttps://github.com/sweetmandm/CardSliderView-for-iOSに似ていますが、垂直と水平の両方の「カードデッキ」スライド機能が必要です.

私が探しているスライド/左カバー/公開効果の別の例を示すために、記事間をスライドできる新しい CNN アプリを見てください。

UIPageViewController の使用も検討しましたが、これは探している「スライドと表示/スライドとカバー」トランジションをサポートしておらず、「左または右にスライド」トランジションのみをサポートしているため、何らかの方法でハックする必要があります。 UIPageViewController からのジェスチャだけを使用して、ユーザーがスワイプできるように、複数の UIPageViewControllers を使用して、「表示してカバーする」効果を機能させます。

私はUIScrollviewのdirectionalLockEnabledプロパティに精通していますが、私が探している効果を得るための全体的な最良のアプローチは何か、垂直と水平の両方をサポートするもの、UIScrollViewはまだ疑問に思っていますか? UIPageViewController? ネストされた UIScrollviews? directionalLockEnabled プロパティをいじる代わりに?他の何か?

私が提供しようとしている正確なユーザー エクスペリエンスを実現するための最良の方法は何ですか?

4

3 に答える 3

1

わかりました、ネストされた UIScrollViews を使用して、自分の質問に対する解決策を見つけました。また、非常に大まかなソリューションをプロジェクトとして github に追加しました: https://github.com/cohen72/InfiniteDeckScroller

水平スクロールの場合、3 つの水平スクロール ビューがあり、一方が他方にネストされています。UIScrollview は、それぞれの適切なスクロールを自動的に処理します。コンテンツのオフセットとスクロールされているスクロールビューに応じて、ネストされたスクロールビューを「再配置/再注文」する方法を知っています。

これが私が思いついたソリューションのスニペットです。

この特定のソリューションでは、上にスライドして明らかにすることができますが、下にスライドしてカバーする方法はまだ実装していませんが、これを行うには、水平ソリューションと同じアプローチを使用します。

#define BOTTOM 1
#define MIDDLE 2
#define TOP 3
#define VERTICAL_SUB 4

- (void)viewDidLoad{

    [super viewDidLoad];

    UIScrollView *scroll1 = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    UIScrollView *scroll2 = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    UIScrollView *scroll3 = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    UIScrollView *scroll4 = [[UIScrollView alloc] initWithFrame:self.view.bounds];

    scroll1.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height * 1);
    scroll1.tag = BOTTOM;
    scroll1.pagingEnabled = YES;
    scroll1.bounces = NO;
    scroll1.delegate = self;
    [scroll1 addSubview:[self labelForScrollView:scroll1 withBgColor:[UIColor redColor]]];
    [scroll1 setContentOffset:CGPointMake(0, 0)];

    scroll2.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height * 1);
    scroll2.tag = MIDDLE;
    scroll2.pagingEnabled = YES;
    scroll2.bounces = NO;
    scroll2.delegate = self;
    [scroll2 addSubview:[self labelForScrollView:scroll2 withBgColor:[UIColor orangeColor]]];
    [scroll2 setContentOffset:CGPointMake(0, 0)];

    scroll3.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height * 1);
    scroll3.tag = TOP;
    scroll3.pagingEnabled = YES;
    scroll3.bounces = NO;
    scroll3.delegate = self;
    [scroll3 addSubview:[self labelForScrollView:scroll3 withBgColor:[UIColor yellowColor]]];
    [scroll3 setContentOffset:CGPointMake(320, 0)];

    scroll4.contentSize = CGSizeMake(self.view.frame.size.width * 1, self.view.frame.size.height * 2);
    scroll4.delegate = self;
    scroll4.bounces = NO;
    scroll4.pagingEnabled = YES;
    scroll4.alwaysBounceVertical = NO;
    scroll4.tag = VERTICAL_SUB;

    [scroll4 addSubview:scroll1];
    [scroll1 addSubview:scroll2];
    [scroll2 addSubview:scroll3];
    [self.view addSubview:scroll4];

}

- (UILabel*)labelForScrollView:(UIScrollView*)scrollView withBgColor:(UIColor*)color{
    UILabel *lbl = [[UILabel alloc] initWithFrame:scrollView.bounds];
    lbl.textAlignment = NSTextAlignmentCenter;
    lbl.backgroundColor = color;
    lbl.text = [NSString stringWithFormat:@"ScrollView: %d", scrollView.tag];
    return lbl;
}

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{

    NSLog(@"content offset: %f, tag: %d ", scrollView.contentOffset.x, scrollView.tag);

    UIScrollView *newMiddleScrollView, *newBottomScrollView, *newTopScrollView;

    // swipe left

    if (scrollView.contentOffset.x == 0 && scrollView.tag == TOP) {
        newMiddleScrollView = (UIScrollView*)[self.view viewWithTag:TOP];
        newTopScrollView = (UIScrollView*)[self.view viewWithTag:BOTTOM];
        newBottomScrollView = (UIScrollView*)[self.view viewWithTag:MIDDLE];
    }

    // swipe right

    else if (scrollView.contentOffset.x == 320 && scrollView.tag == MIDDLE) {
        newMiddleScrollView = (UIScrollView*)[self.view viewWithTag:BOTTOM];
        newTopScrollView = (UIScrollView*)[self.view viewWithTag:MIDDLE];
        newBottomScrollView = (UIScrollView*)[self.view viewWithTag:TOP];
    }
    else {
        return;
    }

    newMiddleScrollView.tag = MIDDLE;
    newBottomScrollView.tag = BOTTOM;
    newTopScrollView.tag = TOP;

    newBottomScrollView.contentOffset = CGPointMake(0, 0);
    newMiddleScrollView.contentOffset = CGPointMake(0, 0);
    newTopScrollView.contentOffset = CGPointMake(320, 0);

    UIScrollView *verticalScrollView_sub = (UIScrollView*)[self.view viewWithTag:VERTICAL_SUB];

    [verticalScrollView_sub addSubview:newBottomScrollView];
    [newBottomScrollView addSubview:newMiddleScrollView];
    [newMiddleScrollView addSubview:newTopScrollView];

}
于 2012-12-24T14:42:55.437 に答える
0

それは良い質問です - ここで間違っている場合は訂正してください。ただし、左から右に任意の数のページ/カードがあるように聞こえますが、上または下からは数枚の標準カードしか入っていないようです (設定と詳細パネル)。

その場合は、UIPageControllerいくつかのジェスチャ認識機能と一緒に、線に沿ったものに固執することをお勧めします。ページ コントローラー (または目的のカード アニメーションを実現するために最終的に使用する任意のコントローラー) をセットアップし、上にスワイプするためと下にスワイプするための 2 つのジェスチャ認識機能を追加します。

UIPageViewControllersこれらのジェスチャを受け取ったときに、詳細/設定ビューをアニメーション化して、複数のビューやスクロール ビューに煩わされることなく、カードのようなインターフェイスを提供できます。

このアプローチは、横方向と縦方向の両方に任意の数のカードが必要な場合にはあまり適していませんが、そうではないように思えます。

于 2012-12-23T17:39:01.290 に答える
0

さまざまなコントローラーを相互にどのように関連付けるかに応じて、これを実現するさまざまな方法があります。スライドのトランジション自体は非常にシンプルです。メソッドを呼び出すコントローラーのスーパークラスであるコントローラーで、この方法で実装しました。

-(void)SlideInController:(RDSlideController *) next {
    next.presentingVC = self;
    next.view.frame = CGRectMake(self.view.frame.origin.x + 320, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
    [self.view.window addSubview:next.view];
    [UIView animateWithDuration:1 animations:^{
        next.view.frame = self.view.frame;
    } completion:^(BOOL finished) {
        self.view.window.rootViewController = next;
    }];
}

次に、新しく提示されたコントローラーから、このメソッドを呼び出して戻ることができます。

-(void)SlideOut {
    UIViewController *prev = self.presentingVC;
    prev.view.frame = self.view.frame;
    [self.view.window insertSubview:prev.view belowSubview:self.view];
    [UIView animateWithDuration:1 animations:^{
        self.view.frame = CGRectMake(self.view.frame.origin.x + 320, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
    } completion:^(BOOL finished) {
        self.view.window.rootViewController = prev;
    }];
}
于 2012-12-24T04:16:17.377 に答える