Google+ナビゲーション

私は最近、google +アプリケーションをiPadにインストールし、ナビゲーションメニューから新しいものに出会いました。 原則として、ScrollViewのページングを介してフィードを更新することは、あまり新しいテクノロジーではありませんが、上部のテキストバー(ちなみにフォントが興味深いことに変更されます)および周期的な動作との組み合わせで、非常に便利で興味深いように見えます。 Google + iPhoneクライアントでこれがどのように見えるかわからない人のために、以下の画像でこれを想像してみてください。







したがって、同じ便利な制御を行うために数時間を費やすことにしましたが、将来は何度も役立つと思います。 実装は私が個人的に期待したほど単純ではなかったので、このようなコントロールを作成する方法を共有することにしました。多くの開発者がそれを必要とするか、少なくとも通常動作する周期的なscrollViewも興味深いと思います。 ちなみに、私は自然にstackoverflowや他のコードリソースで同様のエンジンを探し始めましたが、見つかりませんでした。 私はデザイン部分にあまり重点を置きませんでした。すべてが原始的ですが、同時に普遍的です。



最初のステップ 。 UIViewControllerが必要です。メイン要素は、左右にスクロールするためのUIScrollView、3つのUIView(ページとして表示されます)、およびフローティングテキストを表示するためのトップバーです。



一般的な説明から始めましょう:

 mainScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; [self.view addSubview:mainScroll]; mainScroll.backgroundColor = [UIColor clearColor]; mainScroll.contentSize = CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height); mainScroll.pagingEnabled = YES; mainScroll.scrollEnabled = YES; mainScroll.delegate = self; scrollBar = [[YOScrollBar alloc] initWithFrame:CGRectMake(0, 0, 320, 27)]; [self.view addSubview:scrollBar]; pages = [[NSMutableArray alloc] initWithCapacity:3]; UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; [mainScroll addSubview:view1]; view1.tag = 0; [pages addObject:view1]; view1.backgroundColor = [UIColor lightGrayColor]; [view1 release]; UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height)]; [mainScroll addSubview:view2]; [pages addObject:view2]; view2.tag = 1; view2.backgroundColor = [UIColor grayColor]; [view2 release]; UIView *view3 = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width*2, 0, self.view.frame.size.width, self.view.frame.size.height)]; [mainScroll addSubview:view3]; [pages addObject:view3]; view3.tag = 2; view3.backgroundColor = [UIColor blackColor]; [view3 release]; pageIndex = (int)[pages count]/2; [mainScroll setContentOffset:CGPointMake(self.view.frame.size.width, 0)];
      
      









ここで問題はないと思います。3ページでページングを有効にしてUIScrollViewを作成します。各UIViewにタグが割り当てられていることに注意してください。将来的にはトップバーに使用されます。 この例では、結果は3ページでテストされましたが、将来の汎用性のためにページの配列が既に存在します。



第2ステップ 。 次に、位置を計算してページを置き換えるために、UIScrollViewからデリゲートを処理する必要があります。 言葉で少し:

UIScrollViewは、mainScroll.frame.size.width * 3に等しい定数contentSizeを保持します

右に移動するときは、次のルールを使用します(アクティブな位置は太字で強調表示されています)。

view1、 view2 、view3、offset

view2、view2、 view3が再カウントされ 、次の構成が得られます

view2、 view3 、view1

左に移動すると、再配置は反対方向に行われます。



次に、適切なコードを作成します。 まず、UIScrollViewからデリゲートを使用します

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { float indexF = (mainScroll.contentOffset.x / mainScroll.frame.size.width); int indexI = (int)indexF; float rez = indexF - (float)indexI; if (rez == 0.f) { //   } [scrollBar scroll:mainScroll.contentOffset]; }
      
      











なぜそのような異常なロジックですか? 回答:ページが完全にドラッグアンドドロップされて320pxになったときにのみ「ページ変更」などのイベントが発生します。 roundf、truncf、ceilfをどのように使用しても、必要な結果を得ることができませんでした。 これで、最後のページが中央になり、UIView順列を実行し、ページ配列を並べ替え、UIScrollViewの位置を中央に戻すことができる瞬間をキャッチできます。 上記のすべては、以下のコードで説明されています。



 int newPageIndex = indexI; int center; if (newPageIndex < pageIndex) { //     for (int i=0; i < [pages count]-1; i++) { UIView *moveView = [pages objectAtIndex:i]; moveView.frame = CGRectMake(moveView.frame.origin.x + moveView.frame.size.width, moveView.frame.origin.y, moveView.frame.size.width, moveView.frame.size.height); }//       UIView *moveView = [pages lastObject]; moveView.frame = CGRectMake(0, moveView.frame.origin.y, moveView.frame.size.width, moveView.frame.size.height); //   view for (int i=[pages count]-1; i > 0; i--) [pages exchangeObjectAtIndex:i-1 withObjectAtIndex:i]; //     center = (int)[pages count]/2; //    pageIndex = center; newPageIndex = pageIndex; //       UIView *view = [pages objectAtIndex:center]; [scrollBar changePage:view.tag]; [mainScroll setContentOffset:CGPointMake(center*mainScroll.frame.size.width, 0) animated:NO]; }else if (newPageIndex > pageIndex) { //     for (int i=1; i < [pages count]; i++) { UIView *moveView = [pages objectAtIndex:i]; moveView.frame = CGRectMake(moveView.frame.origin.x - moveView.frame.size.width, moveView.frame.origin.y, moveView.frame.size.width, moveView.frame.size.height); } UIView *moveView = [pages objectAtIndex:0]; moveView.frame = CGRectMake(([pages count]-1)*moveView.frame.size.width, moveView.frame.origin.y, moveView.frame.size.width, moveView.frame.size.height); //   view for (int i=0; i < [pages count]-1; i++) [pages exchangeObjectAtIndex:i withObjectAtIndex:i+1]; //     center = (int)[pages count]/2; //    pageIndex = center; newPageIndex = pageIndex; //       UIView *view = [pages objectAtIndex:center]; [scrollBar changePage:view.tag]; [mainScroll setContentOffset:CGPointMake(center*mainScroll.frame.size.width, 0) animated:NO]; }
      
      











2番目のステップは終了し、左右に周期的にスクロールできる3ページのUIScrollViewが完全に機能しています。



第3ステップ 。 テキストを変更してトップバーを追加します。 ここで、トリックと誤算が始まります。 この瞬間は現在ほとんどの座標にバインドされており、普遍的ではありません。3、4、または別の数の浮動ラベルの構成を作成する場合は、計算ロジックを変更する必要があります。



実装に移りましょう。 ヘッダーファイル:



 @interface YOScrollBar : UIView { UIImageView *background; NSMutableArray *labels; UILabel *labelLeft, *labelCenter, *labelRight, *labelMirrowLeft, *labelMirrowRight; float step; } - (void)scroll:(CGPoint)point; - (void)changePage:(int)pageIndex; - (void)selectCenter; @end
      
      











ミラーリングには5つのUILabel 3プライマリと2つの補助が必要です。それらの間のステップは120になります。セマンティックロードを運ぶのはフレームと碑文のみで、中央の碑文のフォントはHelvetica 14、残りはHelveticaです。 12



 labelMirrowLeft = [[UILabel alloc] initWithFrame:CGRectMake(-109, 5, 60, 14)]; labelMirrowLeft.text = @""; labelLeft = [[UILabel alloc] initWithFrame:CGRectMake(9, 5, 60, 14)]; labelLeft.text = @""; labelCenter = [[UILabel alloc] initWithFrame:CGRectMake(129, 5, 60, 14)]; labelCenter.text = @""; labelRight = [[UILabel alloc] initWithFrame:CGRectMake(249, 5, 60, 14)]; labelRight.text = @""; labelMirrowRight = [[UILabel alloc] initWithFrame:CGRectMake(369, 5, 60, 14)]; labelMirrowRight.text = @"";
      
      











主な移動方法に移ります。



 - (void)scroll:(CGPoint)point { float k = step/320; CGPoint pointT = CGPointMake(-(point.x-320)*k, 0); float fontT = (step - abs((int)pointT.x))/step*2; if (pointT.x > 0) { //   labelLeft.font = [UIFont fontWithName:@"Helvetica" size:14.f-fontT]; }else if (pointT.x < 0) { //   labelRight.font = [UIFont fontWithName:@"Helvetica" size:14.f-fontT]; } labelCenter.font = [UIFont fontWithName:@"Helvetica" size:12.f+fontT]; labelLeft.frame = CGRectMake(9 + pointT.x, labelLeft.frame.origin.y, labelLeft.frame.size.width, labelLeft.frame.size.height); labelCenter.frame = CGRectMake(129 + pointT.x, labelCenter.frame.origin.y, labelCenter.frame.size.width, labelCenter.frame.size.height); labelRight.frame = CGRectMake(249 + pointT.x, labelRight.frame.origin.y, labelRight.frame.size.width, labelRight.frame.size.height); labelMirrowLeft.frame = CGRectMake(-111 + pointT.x, labelMirrowLeft.frame.origin.y, labelMirrowLeft.frame.size.width, labelMirrowLeft.frame.size.height); labelMirrowRight.frame = CGRectMake(369 + pointT.x, labelMirrowRight.frame.origin.y, labelMirrowRight.frame.size.width, labelMirrowRight.frame.size.height); }
      
      











そして、私たちがやるべきことは、この時点でcontentOffsetが置き換えられるため、テキストの変更を完全なページシフトで規定することだけです。



 - (void)changePage:(int)pageIndex { if (pageIndex == 0) { labelMirrowLeft.text = @""; labelLeft.text = @""; labelCenter.text = @""; labelRight.text = @""; labelMirrowRight.text = @""; }else if (pageIndex == 1) { labelMirrowLeft.text = @""; labelLeft.text = @""; labelCenter.text = @""; labelRight.text = @""; labelMirrowRight.text = @""; }else if (pageIndex == 2) { labelMirrowLeft.text = @""; labelLeft.text = @""; labelCenter.text = @""; labelRight.text = @""; labelMirrowRight.text = @""; } }
      
      











最後に、Google +に劣らない完全なエンジンを入手しました。

下のビデオで結果を見ることができます。 スクリーンキャプチャデモを使用して申し訳ありません。 私がいつも使っていたScreen Flickが有料になったので、代替ソリューションを探す必要がありました。







ソースプロジェクトはこちらからダウンロードできます: https : //github.com/katleta3000/Google-Navi



All Articles