西海岸より

つらつらざつざつと

ドラッグ可能なAlertView

UIKitでは、UIViewを継承することで簡単にタッチイベントを拾い、独自に実装することが可能、ってことでAlertViewもできるか試してみました。
(審査に通るかはとても怪しいので利用しない方がよいと思います)

  • DraggableAlertView.h
#import <UIKit/UIKit.h>

@interface DraggableAlertView : UIAlertView {
	CGPoint touchBeganPoint;		//ドラッグ開始座標
	CGPoint touchBeganCenterPoint;	//ドラッグ開始時のAlertViewの中心座標
}
@end
  • DraggableAlertView.m
#import "DraggableAlertView.h"

@interface DraggableAlertView ()
- (CGPoint) touchesToPoint:(NSSet *)touches;
@end

@implementation DraggableAlertView

- (id)initWithFrame:(CGRect)frame {
  if ((self = [super initWithFrame:frame])) {
      // Initialization code
  }
  [self setExclusiveTouch:YES];
  [self setUserInteractionEnabled:YES];
  return self;
}

//ドラッグ開始 - ドラッグ開始点を記録
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  touchBeganPoint = [self touchesToPoint:touches];
  touchBeganCenterPoint = self.center;
}

//ドラッグ中 - ドラッグ開始点と差分を計算してViewの座標を変更
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  CGPoint touchPoint = [self touchesToPoint:touches];
  CGPoint newViewCenter;
  newViewCenter.x = touchBeganCenterPoint.x + (touchPoint.x - touchBeganPoint.x);
  newViewCenter.y = touchBeganCenterPoint.y + (touchPoint.y - touchBeganPoint.y);
  self.center = newViewCenter;
}

- (CGPoint) touchesToPoint:(NSSet *)touches {
  for(id touch in touches) {
    return [touch locationInView:[self superview]];
  }
  assert(NO);
}

- (void)dealloc {
  [super dealloc];
}
@end

あとは、ViewControllerに普通のAlertViewのように書けば出来上がり。

  DraggableAlertView *draggableAlertView = [[DraggableAlertView alloc] 
                                            initWithTitle:@"DraggableAlertView"
                                            message:@"ドラッグできるAlertView"
                                            delegate:nil
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:nil];
  [draggableAlertView show];
  [draggableAlertView release];