@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