我们经常在IPhone中涉及到开发通过触摸移动自己的按钮或视图。例如下面3个图:通过手指触摸屏幕移动灰色按钮:
下面具体讲解一下实现此效果的过程:
1.首先我们自定义一个按钮MyButton 继承自UIButton
#import
@interface MyButton : UIButton
{
CGFloat xDistance; //触摸点和中心点x方向移动的距离
CGFloat yDistance; //触摸点和中心点y方向移动的距离
}
@end
注意:
(1).CGPoint 只是typdef 过的一个struct结构体,是值类型,千万不能加星号(*)
struct CGPoint {
CGFloat x;
CGFloat y;
};
typedef struct CGPoint CGPoint;
# define CGFLOAT_TYPE float
typedef CGFLOAT_TYPE CGFloat;
2.在MyButton.m中添加代码
//手指按下开始触摸
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//获得触摸在按钮的父视图中的坐标
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.superview];
xDistance = self.center.x - currentPoint.x;
yDistance = self.center.y - currentPoint.y;
}
//手指按住移动过程
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if(isDrag)
{
//获得触摸在按钮的父视图中的坐标
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.superview];
//移动按钮到当前触摸位置
CGPoint newCenter = CGPointMake(currentPoint.x + xDistance, currentPoint.y + yDistance);
self.center = newCenter;
}
}
解释:因为我们的MyButton继承自UIButton,而UIButton继承自UIControl,UIControl继承自UIView,UIView继承自UIResponder
UIResponder类提供了响应用户交互的一些事件,以上两个就在其中。这些函数都是系统回调函数,也就是说当程序和用户发生交互时,系统自动调用执行,无需程序员手动调用和响应。
最后只需在UIViewController中实例化MyButton,编译运行就可以实现功能了。
注:从响应事件event中也能获得所有触摸的触摸点集合:
NSSet *myTouches = [eventtouchesForView:self.view];
下面简单介绍下IOS中的交互事件响应链:
响应者: |UIImageView
|UIApplication|UILabel |UIButton
| ||UISlider
NSObject-----UIResponder------|UIView-------------------------|UIControl-----------------|
| ||UISwitch
|UIViewController|UIWindow |UITextField
|UIScrollView
在IOS中当前接受触摸的响应者对象被称为第一响应者,即表示当前该对象正在与用户交互,它是响应者链的开端。
响应者链表示一系列的响应者对象。事件被交由第一响应者对象处理,如果第一响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者。一般来说,第一响应者是个视图对象或者其子类对象,当其被触摸后事件被交由它处理,如果它不处理,事件就会被传递给它的视图控制器对象(如果存在),然后是它的父视图(superview)对象(如果存在),以此类推,直到顶层视图。接下来会沿着顶层视图(top view)到窗口(UIWindow对象)再到程序(UIApplication对象)。如果整个过程都没有响应这个事件,该事件就被丢弃。一般情况下,在响应者链中只要由对象处理事件,事件就停止传递。但有时候可以在视图的响应方法中根据一些条件判断来决定是否需要继续传递事件。
视图对触摸事件是否需要作处回应可以通过设置视图的userInteractionEnabled属性。默认状态为YES,如果设置为NO,可以阻止视图接收和分发触摸事件。
除此之外,当视图被隐藏(setHidden:YES)或者透明(alpha值为0)也不会收事件。
不过这个属性只对视图有效,如果想要整个程序都步响应事件,可以调用UIApplication的beginIngnoringInteractionEvents方法来完全停止事件接收和分发。通过endIngnoringInteractionEvents方法来恢复让程序接收和分发事件。
如果要让视图接收多点触摸,需要设置它的multipleTouchEnabled属性为YES,默认状态下这个属性值为NO,即视图默认不接收多点触摸。