1.应用UIAccelerometer实例,设置updateInterval和delegate,实现accelerometer:didAccelerate协议方法,每隔一段updateInterval设置的时间调用协议方法,更新数据。
2.获得各个方向上的加速度:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
//获得x,y,z轴上的各个加速度分量
NSLog(@"%f, %f, %f",acceleration.x,acceleration.y,acceleration.z);
}
3.侦测摇动:
本来需要在加速传感器传出的信号上执行一些复杂的数学运算,才能侦测用户摇动设备的动作,但是在UIResponder类中实现的方法可以帮我们完成这些计算。
// Triggered when a shake is detected
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
// Triggered when the shake is complete
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
// Triggered when a shake is interrupted (by a call for example)
// Or if a shake lasts for more than a second
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
4.firstResponder:
当运动事件(指系统通过查询加速感应器硬件来侦测是否有“摇动”发生)发生时会向firstResponder发送响应的消息。这时候如果某个对象想接收这些消息,那就要成为第一响应者。比如:上面的UIResponder类中定义的- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;消息,因为这不是代理协议方法,没有什么代理对象可发送,会发送给第一响应者(firstResponder)。要成为第一响应者要1.向该对象发送becomeFirstResponder(定义在UIResponder类中)消息,2.该对象要覆盖- (BOOL)canBecomeFirstResponder方法并返回YES;
5.滤波与频率
为了使随着设备倾斜而变动的动画更流畅,书本(ios编程(第二版))提到了滤波和频率,频率是改变更新数据的频率也就是把updateInterval的值缩小。滤波是为了避免突发的移动造成的不流畅。(看代码就会更加明白)
其中有高通滤波和低通滤波:形式如下
float filteringFactor = 0.1;
lowPassed = newValue * filteringFactor + lowPassed * (1.0 - filteringFactor);
highPassed = newValue - lowPassed;
还有很多滤波算法,这是比较容易理解的。
6.视网膜屏(Reatina)
苹果设备有两种分辨率,以前是320*480,比较新的是640*960,也就是同一尺寸大小的设备320*480的每一个像素的大小是640*960的每个像素的2*2倍,为了更好的显示,在项目中通常会添加两套图片,一套是在图片名字后面加@2x,并且这套图片的像素是领一套的2*2倍,这样,当应用运行时就会检测设备是否为视网膜屏,如果是,则使用@2x那套图片。
这里附上主要代码(ios编程(第二版)方向感应器)
- (void)drawRect:(CGRect)rect {
CGRect bounds = [self bounds];
CGPoint center;
center.x = bounds.origin.x + bounds.size.width/2.0;
center.y = bounds.origin.y + bounds.size.height/2.0;
//计算半径
float maxRadius = hypot(bounds.size.width,bounds.size.height)/2.0;
//拿到绘图上下文
CGContextRef context = UIGraphicsGetCurrentContext();
//设置线条的宽度
CGContextSetLineWidth(context, 10);
// //设置线条颜色
// [[UIColor lightGrayColor] setStroke];
[stripeColor setStroke];
for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20) {
center.x += _xShift;
center.y += _yShift;
CGContextAddArc(context, center.x, center.y, currentRadius, 0.0, M_PI*2.0, YES);
CGContextStrokePath(context);
}
//创建字符串
NSString *text = @"you are getting sleepy.";
//获取所需的字体
UIFont *font = [UIFont boldSystemFontOfSize:28];
//计算绘图位置
CGRect textRect;
textRect.size = [text sizeWithFont:font];
textRect.origin.x = center.x - textRect.size.width/2.0;
textRect.origin.y = center.y - textRect.size.height/2.0;
//将当前上下文填充色设为黑色
[[UIColor blackColor] setFill];
//阴影设为右偏移4点,向下偏移3点,暗灰色,2点模糊半径
CGSize offset = CGSizeMake(4, 3);
CGColorRef color = [[UIColor darkGrayColor] CGColor];
CGContextSetShadowWithColor(context, offset, 2.0, color);
// CGContextStrokePath(context);
//绘制字符串
[text drawInRect:textRect withFont:font];
}
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake) {
NSLog(@"shake start");
float r,g,b;
r = random() % 256 / 256.0;
g = random() % 256 / 256.0;
b = random() % 256 / 256.0;
[stripeColor release];
stripeColor = [UIColor colorWithRed:r green:g blue:b alpha:1];
[stripeColor retain];
[self setNeedsDisplay];
}
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"Monitoring accelerometer");
UIAccelerometer *accelerometer = [UIAccelerometer sharedAccelerometer];
//每0.1秒更新
[accelerometer setUpdateInterval:0.1];
[accelerometer setDelegate:self];
[[self view] becomeFirstResponder];
}
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
HyponsisView *hv = (HyponsisView *)[self view];
// hv.xShift = 10.0 * acceleration.x;
// hv.yShift = -10.0 * acceleration.y;
float xShift = hv.xShift * 0.8 + acceleration.x * 2.0;
float yShift = hv.yShift * 0.8 - acceleration.y * 2.0;
hv.xShift = xShift;
hv.yShift = yShift;
// NSLog(@"%f",acceleration.x);
[hv setNeedsDisplay];
}