UIPopoverPresentationController

 

@interfaceOXPopoverViewController :UIViewController

<

   OXCalendarScrollViewControllerDelegate,

   UIPopoverPresentationControllerDelegate

>

 

 

 


- (IBAction)didSelectButton:(UIButton *)sender
{
    if (sender == _dateButton) {
        
        OXCalendarScrollViewController *vc = [[OXCalendarScrollViewController alloc] init];
        vc.delegate = self;
        vc.scrollDirection = (_segmentedControl.selectedSegmentIndex == 0)?
            UICollectionViewScrollDirectionVertical:
                UICollectionViewScrollDirectionHorizontal;
        
        if (![_dateButton.currentTitle isEqualToString:@"date"]) {
            vc.setDateString = _dateButton.currentTitle;
        }
        
        [self presentPopOverWithViewController:vc sourceView:sender];
        return;
    }
    
    
    [self dismissViewControllerAnimated:YES completion:nil];
}

 

 

/**
 *  ポップオーバーを表示する
 *  @param vc UIViewControllerインスタンス
 *  @param sourceView 表示元UIView
 *  @return 無し
 */
- (void)presentPopOverWithViewController:(UIViewController *)vc sourceView:(UIView *)sourceView
{
    vc.modalPresentationStyle = UIModalPresentationPopover;
    vc.preferredContentSize = vc.view.frame.size;
    
    UIPopoverPresentationController *presentationController = vc.popoverPresentationController;
    presentationController.delegate = self;
    presentationController.permittedArrowDirections = UIPopoverArrowDirectionUp;
    presentationController.sourceView = sourceView;
    presentationController.sourceRect = sourceView.bounds;
    
    [self presentViewController:vc animated:YES completion:NULL];
}

 

 

--------------

 

- (IBAction)didSelectButton:(UIButton *)sender
{
    if (sender == _closeButton) {
        
        [self dismissViewControllerAnimated:YES completion:nil];
    
    } else if (sender == _popoverButton) {
        
        OXCalendarScrollViewController *vc = [[OXCalendarScrollViewController alloc] init];
        vc.delegate = self;
        if (![_popoverButton.currentTitle isEqualToString:@"Popover"]) {
            vc.setDateString = _popoverButton.currentTitle;
        }
        
        [self presentPopOverWithViewController:vc sourceView:sender permittedArrowDirections:UIPopoverArrowDirectionAny popoverPresentationControllerDelegate:self completion:nil];
    }
}

 

#pragma mark - UIPopoverPresentationControllerDelegate

/**

* ポップオーバー消去時に呼ばれる

* @param popoverPresentationController UIPopoverPresentationControllerインスタンス

* @return 無し

*/

- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController*)popoverPresentationController

{

}

 

 

/**

* 使用する表示スタイルを返す

* @param controller UIPresentationControllerインスタンス

* @return 無し

*/

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController*)controller

{

   returnUIModalPresentationNone;// これがないと、iPhoneではポップオーバーが表示されない

}

 

 

#pragma mark - CalendarScrollViewControllerDelegate

/**

* 日付選択時に呼ばれる

* @param dateString 日付文字列(@"yyyy/MM/dd")

* @return 無し

*/

- (void)didSelectCalendarScrollDate:(NSString*)dateString

{

   [_popoverButtonsetTitle:dateStringforState:UIControlStateNormal];

}

 

 

 

 

 

 

 

 

//

//  OXCalendarScrollViewController.h

//  OXcode7Viewer

//

//

 

#import <UIKit/UIKit.h>

#import "OXCalendarCell.h"

 

 

/**

*  カレンダースクロール表示管理デリゲート

*/

@protocol OXCalendarScrollViewControllerDelegate <NSObject>

 

/**

*  日付選択時に呼ばれる

*  @param dateString 日付文字列(@"yyyy/MM/dd")

*  @return 無し

*/

- (void)didSelectCalendarScrollDate:(NSString *)dateString;

@end

 

 

 

/**

*  カレンダースクロール表示管理

*/

@interface OXCalendarScrollViewController : UIViewController

 

/// カレンダースクロール表示

@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;

/// 前年ボタン

@property (weak, nonatomic) IBOutlet UIButton *lastYearButton;

/// 今月ボタン

@property (weak, nonatomic) IBOutlet UIButton *presentButton;

/// 来年ボタン

@property (weak, nonatomic) IBOutlet UIButton *nextYearButton;

 

/// デリゲート

@property (weak, nonatomic) id <OXCalendarScrollViewControllerDelegate> delegate;

/// スクロール方向

@property (assign, nonatomic) UICollectionViewScrollDirection scrollDirection;

/// カレンダー表示データ一覧

@property (strong, nonatomic) NSMutableArray *collectionItems;

/// 今月を示すインデックス

@property (assign, nonatomic) NSInteger presentMonthIndex;

/// 設定日

@property (strong, nonatomic) NSString *setDateString;

/// 祝日情報

@property (strong, nonatomic) NSMutableDictionary *holidayInfo;

 

#pragma mark - IBAction

/**

*  ボタン選択時に呼ばれる

*  @param sender UIButtonインスタンス

*  @return 無し

*/

- (IBAction)didSelectButton:(UIButton *)sender;

 

@end

 

 

 

 

 

 

 

 

 

 

//

// OXCalendarScrollViewController.m

// OXcode7Viewer

//

 

#import"OXCalendarScrollViewController.h"

 

@interfaceOXCalendarScrollViewController()

 

@end

 

@implementationOXCalendarScrollViewController

 

/**

* ロード時に呼ばれる

* @param 無し

* @return 無し

*/

- (void)viewDidLoad

{

   [superviewDidLoad];

   // Do any additional setup after loading the view from its nib.

    

#if TRUE

    

   // レイアウト変更(水平方向)

   UICollectionViewFlowLayout*flowLayout = (UICollectionViewFlowLayout*)[_collectionViewcollectionViewLayout];

   flowLayout.scrollDirection=_scrollDirection;

    

#else

   //   UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];

   UICollectionViewFlowLayoutEx *flowLayout = [[UICollectionViewFlowLayoutEx alloc] init];

    

   flowLayout.itemSize = CGSizeMake(350,400);

   flowLayout.minimumLineSpacing =5.0f;     //セクションとアイテムの間隔

   flowLayout.minimumInteritemSpacing =5.0f; //アイテム同士の間隔

   flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

   _collectionView.collectionViewLayout = flowLayout;

#endif

    

   // コレクション設定(再利用)

   NSString *className = NSStringFromClass([OXCalendarCell class]);

   [_collectionView registerNib:[UINib nibWithNibName:className bundle:nil] forCellWithReuseIdentifier:className];

   _collectionView.decelerationRate = UIScrollViewDecelerationRateFast;

    

   // 祝日情報

   _holidayInfo = [NSMutableDictionary dictionary];

   _holidayInfo[@"2016/03/21"] =@"春分の日(振替)";

   _holidayInfo[@"2016/04/29"] =@"昭和の日";

   _holidayInfo[@"2016/05/03"] =@"憲法記念日";

   _holidayInfo[@"2016/05/04"] =@"みどりの日";

   _holidayInfo[@"2016/05/05"] =@"こどもの日";

    

    

   NSString*setYearMonth =@"";

   if(_setDateString.length) {

       // 設定日の年月(文字列)

       NSArray*values = [_setDateStringcomponentsSeparatedByString:@"/"];

       if(values.count==3) {

           setYearMonth = [NSStringstringWithFormat:@"%@/%@", values[0], values[1]];

       }

   }

    

   // 今月の年月(文字列)

   NSDate*now = [NSDatedate];

   NSDateFormatter*dateFormat = [[NSDateFormatter alloc]init];

   [dateFormatsetDateFormat:@"yyyy/MM"];

   NSString*presentYearMonth = [dateFormatstringFromDate:now];

    

    

   // カレンダー一覧表示データ作成

   NSIntegerstartYear =2010;

   NSIntegerendYear =2020;

   NSIntegersetMonthIndex = -1;

    

   NSIntegercnt =0;

   _collectionItems= [NSMutableArray array];

    

   for(NSIntegeri = startYear; i < endYear; i++) {

       for(NSIntegerj =0; j <12; j++) {

           NSString*str = [NSStringstringWithFormat:@"%ld/%02ld", (long)i, (long)j+1];

            

           if([strisEqualToString:setYearMonth]) {

               setMonthIndex = cnt;

           }

            

           if([strisEqualToString:presentYearMonth]) {

               _presentMonthIndex= cnt;

           }

            

           [_collectionItemsaddObject:str];

           cnt++;

       }

   }

    

   NSIntegertoRow =0;

   if(setMonthIndex > -1) {

       toRow = setMonthIndex;

        

   }else{

       toRow =_presentMonthIndex;

   }

    

   // 設定日の月、または今月へ移動する

   NSIndexPath*toIndexPath = [NSIndexPath indexPathForItem:toRowinSection:0];

   [selfscrollAtIndexPath:toIndexPath];

    

    

   // 通知登録(日付選択)

   NSNotificationCenter*nc = [NSNotificationCenter defaultCenter];

   [ncaddObserver:selfselector:@selector(didSelectDate:)name:OXCalendarViewDidSelectDateNotificationobject:nil];

}

 

 

/**

* メモリ警告時に呼ばれる

* @param 無し

* @return 無し

*/

- (void)didReceiveMemoryWarning

{

   [superdidReceiveMemoryWarning];

   // Dispose of any resources that can be recreated.

}

 

 

/**

* 解放時に呼ばれる

* @param 無し

* @return 無し

*/

- (void)dealloc

{

   // 通知解除(日付選択)

   [[NSNotificationCenter defaultCenter]removeObserver:selfname:OXCalendarViewDidSelectDateNotificationobject:nil];

}

 

 

/*

#pragma mark - Navigation

 

// In a storyboard-based application, you will often want to do a little preparation before navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

// Get the new view controller using [segue destinationViewController].

// Pass the selected object to the new view controller.

}

*/

 

 

/**

* 指定位置へスクロールする

* @param indexPath NSIndexPathインスタンス

* @return 無し

*/

- (void)scrollAtIndexPath:(NSIndexPath*)indexPath

{

   UICollectionViewScrollPositionscrollPosition = (_scrollDirection==UICollectionViewScrollDirectionVertical)?

UICollectionViewScrollPositionCenteredVertically:

   UICollectionViewScrollPositionCenteredHorizontally;

   [_collectionViewselectItemAtIndexPath:indexPathanimated:YESscrollPosition:scrollPosition];

}

 

 

/**

* 日付選択時に呼ばれる

* @param notification NSNotificationインスタンス

* @return 無し

*/

- (void)didSelectDate:(NSNotification*)notification

{

   NSString*dateString = (NSString*)notification.object;

    

   [_delegate didSelectCalendarScrollDate:dateString];

    

   _setDateString= dateString;

   [_collectionViewreloadData];

    

#if FALSE

    

   UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"確認"

                                                                            message:dateString

                                                                     preferredStyle:UIAlertControllerStyleAlert];

   UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK"

                                                    style:UIAlertActionStyleDefault

                                                  handler:^(UIAlertAction *action) {

                                                      //                                                     [self dismissViewControllerAnimated:YES completion:nil];

                                                  }];

   [alertController addAction:action];

   [selfpresentViewController:alertController

                      animated:YES

                    completion:^{

                    }];

#endif

}

 

 

#pragma mark - IBAction

/**

* ボタン選択時に呼ばれる

* @param sender UIButtonインスタンス

* @return 無し

*/

- (IBAction)didSelectButton:(UIButton*)sender

{

   NSArray*indexPaths =_collectionView.indexPathsForVisibleItems;

   NSIndexPath*indexPath = indexPaths[0];

   NSIntegercurrentRow = indexPath.row;

   NSIntegercount =_collectionItems.count;

   NSIntegertoRow;

    

   if(sender ==_lastYearButton) {

       // 前年へ移動する

       toRow = currentRow -12;

       toRow = (count <0)?0: toRow;

   }elseif(sender ==_presentButton) {

       // 今月へ移動する

       toRow =_presentMonthIndex;

   }else{

       // 来年へ移動する

       toRow = currentRow +12;

       toRow = (count > toRow)? toRow: count-1;

   }

    

   if(toRow <0) {

       return;

   }

    

   NSIndexPath*toIndexPath = [NSIndexPath indexPathForItem:toRowinSection:0];

   [selfscrollAtIndexPath:toIndexPath];

}

 

 

#pragma mark - UICollectionViewDataSource

/**

* セクション数を返す

* @param collectionView 対象UICollectionView

* @return セクション数

*/

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)collectionView

{

   return1;

}

 

 

/**

* 要素数を返す

* @param collectionView 対象UICollectionView

* @return 要素数

*/

- (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section

{

   return[_collectionItemscount];

}

 

 

/**

* 表示対象セルを返す

* @param collectionView 対象UICollectionView

* @param indexPath インデックス情報

* @return 表示対象セル

*/

- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView

                 cellForItemAtIndexPath:(NSIndexPath*)indexPath

{

   NSString*className =NSStringFromClass([OXCalendarCellclass]);

   OXCalendarCell*cell = [collectionViewdequeueReusableCellWithReuseIdentifier:className

                                                                    forIndexPath:indexPath];

   cell.calendarView.setDateString=_setDateString;

   cell.calendarView.holidaysInfo=_holidayInfo;

   cell.dateString=_collectionItems[indexPath.row];

    

    

   returncell;

}

 

 

#pragma mark - UICollectionViewDelegate

/**

* セル選択時に呼ばれる

* @param collectionView 対象UICollectionView

* @param indexPath インデックス情報

* @return 無し

*/

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath

{

}

 

 

#pragma mark - UIScrollViewDelegate

/**

* スクロール時に呼ばれる

* @param scrollView UIScrollViewインスタンス

* @return 無し

*/

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

{

   NSIndexPath *indexPath = [_collectionView indexPathForItemAtPoint:scrollView.contentOffset];

   if(indexPath) {

       _lastYearButton.enabled = (indexPath.row >11);

       NSInteger diff = _collectionItems.count - indexPath.row;

       _nextYearButton.enabled = (diff >12);

   }

}

 

 

/**

* ドラッグ終了時に呼ばれる

* @param scrollView UIScrollViewインスタンス

* @param velocity タップリリース時のスクロール速度

* @param targetContentOffset 対象オフセット値

* @return 無し

*/

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inoutCGPoint *)targetContentOffset

{

   //   NSLog(@"%@", NSStringFromCGPoint(velocity));

    

   // セル単位に表示するように位置を調整する

   UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)[_collectionView collectionViewLayout];

   CGSize itemSize = flowLayout.itemSize;

   CGFloat contentInsetTop = _collectionView.contentInset.top;

    

   if(flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) {

       CGFloat diff = itemSize.width + flowLayout.minimumInteritemSpacing;

       CGFloat targetContentOffsetX = roundf((targetContentOffset->x + contentInsetTop) / diff) * diff - contentInsetTop;

       targetContentOffset->x = targetContentOffsetX;

   }else{

       CGFloat diff = itemSize.height + flowLayout.minimumLineSpacing;

       CGFloat targetContentOffsetY = roundf((targetContentOffset->y + contentInsetTop) / diff) * diff - contentInsetTop;

       targetContentOffset->y = targetContentOffsetY;

   }

}

 

@end

 

 

 

 

 

 

 

 

 

 

 

 

#import

@interface UIViewController (Popover)

- (void)presentPopOverWithViewController:(UIViewController *)vc
                              sourceView:(UIView *)sourceView
                permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections
   popoverPresentationControllerDelegate:(id )delegate
                              completion:(void (^)(void))completion;

@end

 

 

#import "UIViewController+Popover.h"

@implementation UIViewController (Popover)

- (void)presentPopOverWithViewController:(UIViewController *)vc
                              sourceView:(UIView *)sourceView
                permittedArrowDirections:(UIPopoverArrowDirection)permittedArrowDirections
   popoverPresentationControllerDelegate:(id )delegate
                              completion:(void (^)(void))completion
{
    vc.modalPresentationStyle = UIModalPresentationPopover;
    vc.preferredContentSize = vc.view.frame.size;
    
    UIPopoverPresentationController *presentationController = vc.popoverPresentationController;
    presentationController.delegate = delegate;
    presentationController.permittedArrowDirections = permittedArrowDirections;
    presentationController.sourceView = sourceView;
    presentationController.sourceRect = sourceView.bounds;
    
    [self presentViewController:vc animated:YES completion:completion];
}


@end

最終更新:2019年05月28日 22:49