2011斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
来源:互联网 发布:中班美工剪纸 编辑:程序博客网 时间:2024/06/11 02:20
第五课内容: 自动旋转、 Protocols、 手势识别、一个自定义UIView的Demo
1、自动旋转
当设备旋转时,你的controller会做什么呢?你可以控制界面是否和设备一起一起旋转。
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation{return UIInterfaceOrientationIsPortrait(orientation); // only support portrait return YES; // support all orientationsreturn (orientation != UIInterfaceOrientationPortraitUpsideDown); // anything but}当旋转的时候,view的bounds会改变,子view的frame,子view的子view也会改变。
改变的规则是:struts和springs。
当view的bound改变时,drawRect不会默认调用
红色的I就是struts,中间的红色箭头就是springs。
右边红白色的显示屏似的就是用动画告诉你view如何改变。白色的是父view,红色的是你选中的view。
这个控制在iPhone上一般使用不到,因为屏幕太小了。
幸运的是,有UIView有这么个属性来控制
三种控制方式:
1、
@property (nonatomic) UIViewContentMode contentMode;
UIViewContentMode{Left,Right,Top,Right,BottomLeft,BottomRight,TopLeft,TopRight}2、缩放的控制属性:
UIViewContentModeScale{ToFill,AspectFill,AspectFit} // bit stretching/shrinking分别是填充,内容填充,内容适应。 toFill是默认的模式,它会自动缩放像素点填满新的空间,可能会造成图形扭曲。
3、
@property (nonatomic) CGRect contentStretch;指定某一个区域拉伸
初始化一个UIView.
2、协议procotol
@protocol Foo <Other, NSObject> // implementors must implement Other and NSObject too- (void)doSomething; // implementors must implement this (methods are @required by default) @optional- (int)getSomething; // implementors do not have to implement this- (void)doSomethingOptionalWithArgument:(NSString *)argument; // also optional@required- (NSArray *)getManySomethings:(int)howMany; // back to being “must implement” @property (nonatomic, strong) NSString *fooProp; // note that you must specify strength@end
可以定义在自己的头文件里,也可以定义在其他类的头文件中。
实现协议,并使用的语法:
#import “Foo.h” // importing the header file that declares the Foo @protocol @interface MyClass : NSObject <Foo> // MyClass is saying it implements the Foo @protocol...@en
id <Foo> obj = [[MyClass alloc] init];
@property (nonatomic, weak) id <Foo> myFooProperty; // properties too!协议的主要作用:
实现委托和数据源。
委托几乎都是weak的,因为被设置为委托的对象通常都是委托对象的所有者或创建者。
委托几乎都是weak的,因为被设置为委托的对象通常都是委托对象的所有者或创建者。
比如controller通常把自己设置成view的委托或数据源,你不要它们相互的strong指针指向。
scrollView例子
@protocol UIScrollViewDelegate@optional- (UIView *)viewForZoomingInScrollView:(UIScrollView *)sender;- (void)scrollViewDidEndDragging:(UIScrollView *)sender willDecelerate:(BOOL)decelerate;@end@interface UIScrollView : UIView@property (nonatomic, weak) id <UIScrollViewDelegate> delegate;@end@interface MyViewController : UIViewController <UIScrollViewDelegate>@property (nonatomic, weak) IBOutlet UIScrollView *scrollView;@end@implementation MyViewController- (void)setScrollView:(UIScrollView *)scrollView { _scrollView = scrollView;self.scrollView.delegate = self; // compiler won’t complain }- (UIView *)viewForZoomingInScrollView:(UIScrollView *)sender { return ... }; @end
3、手势识别
如何获得触摸事件呢?
得到触摸时间的通知
相应预定义好的手势
UIGestureRecognizer类,它是个抽象类,需要实现。
使用手势识别有两步骤:
先创建一个手势,把它附到UIView上,然后当手势被识别时进行处理。
第一步由controller来完成
第二步由UIView自己完成
从controller添加一个手势到UIView:
- (void)setPannableView:(UIView *)pannableView { _pannableView = pannableView; UIPanGestureRecognizer *pangr = [[UIPanGestureRecognizer alloc] initWithTarget:pannableView action:@selector(pan:)]; [pannableView addGestureRecognizer:pangr];}target 是手势识别之后的处理者,这里就是view本身。
UIPangestureRecognizer的三个方法:
- (CGPoint)translationInView:(UIView *)aView;- (CGPoint)velocityInView:(UIView *)aView;- (void)setTranslation:(CGPoint)translation inView:(UIView *)aView;第一个告诉移动的距离
第二个告诉移动的速度
第三个是重新设置
手势识别的状态机
@property (readonly) UIGestureRecognizerState state;
状态从possible 如果手势比较短:recognized 如果持续:Began - Changed ,最后Ended
还有Failed 和 Cancelled状态,取消或其他操作中断时会有这个情况。
pan:是什么样的呢:
- (void)pan:(UIPanGestureRecognizer *)recognizer{if ((recognizer.state == UIGestureRecognizerStateChanged) ||(recognizer.state == UIGestureRecognizerStateEnded)) { CGPoint translation = [recognizer translationInView:self]; // move something in myself (I’m a UIView) by translation.x and translation.y // for example, if I were a graph and my origin was set by an @property called origin self.origin = CGPointMake(self.origin.x+translation.x, self.origin.y+translation.y); [recognizer setTranslation:CGPointZero inView:self]; } }
其他实例的手势:
UIPinchGestureRecognizer 缩放
UIRotationGestureRecognizer 旋转手势,两个手指按下,然后旋转,是个弧度,不是角度。
UISwipeGestureRecognizer 滑动手势, 一个或多个手指滑动,
UITapGestureRecognizer 点击手势
4、一个幸福笑脸的Demo:
内容介绍:
Model是: int happiness
View是:自定义的view叫做FaceView
Controller是:HappinessViewController
观察内容有:
drawRect 包括绘制子程序, pop push context(环境)
Faceview委托的数据如何属于Controller的协议。
Controller处理手势,或者view处理手势
通过手势来改变幸福度。
用整数表示幸福度, 0表示悲伤, 100表示非常幸福。
有两个手势,一个被view处理,因为它只修改显示,另外一个被controller处理,它要修改model,修改幸福度。
主要源码:
happinessViewController.h
#import <UIKit/UIKit.h>@interface HappinessViewController : UIViewController@property (nonatomic) int happiness; // 0 is sad; 100 is very happy@end
happinessViewController.m
#import "HappinessViewController.h"#import "FaceView.h"@interface HappinessViewController() <FaceViewDataSource>@property (nonatomic, weak) IBOutlet FaceView *faceView;@end@implementation HappinessViewController@synthesize happiness = _happiness;@synthesize faceView = _faceView;- (void)setHappiness:(int)happiness{ _happiness = happiness; [self.faceView setNeedsDisplay]; // any time our Model changes, redraw our View}- (void)setFaceView:(FaceView *)faceView{ _faceView = faceView; // enable pinch gestures in the FaceView using its pinch: handler [self.faceView addGestureRecognizer:[[UIPinchGestureRecognizer alloc] initWithTarget:self.faceView action:@selector(pinch:)]]; [self.faceView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleHappinessGesture:)]]; // gesture to modify our Model self.faceView.dataSource = self;}- (void)handleHappinessGesture:(UIPanGestureRecognizer *)gesture{ if ((gesture.state == UIGestureRecognizerStateChanged) || (gesture.state == UIGestureRecognizerStateEnded)) { CGPoint translation = [gesture translationInView:self.faceView]; self.happiness -= translation.y / 2; [gesture setTranslation:CGPointZero inView:self.faceView]; }}- (float)smileForFaceView:(FaceView *)sender{ return (self.happiness - 50) / 50.0; // translate Model for View}- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{ return YES; // support all orientations}@end
FaceView.h
#import <UIKit/UIKit.h>@class FaceView; // forward declaration for use in @protocol@protocol FaceViewDataSource- (float)smileForFaceView:(FaceView *)sender;@end@interface FaceView : UIView@property (nonatomic) CGFloat scale;- (void)pinch:(UIPinchGestureRecognizer *)gesture; // resizes the face// set this property to whatever object will provide this View's data// usually a Controller using a FaceView in its View@property (nonatomic, weak) IBOutlet id <FaceViewDataSource> dataSource;@endFaceView.m
#import "FaceView.h"@implementation FaceView@synthesize dataSource = _dataSource;@synthesize scale = _scale;#define DEFAULT_SCALE 0.90- (CGFloat)scale{ if (!_scale) { return DEFAULT_SCALE; // don't allow zero scale } else { return _scale; }}- (void)setScale:(CGFloat)scale{ if (scale != _scale) { _scale = scale; [self setNeedsDisplay]; // any time our scale changes, call for redraw }}- (void)pinch:(UIPinchGestureRecognizer *)gesture{ if ((gesture.state == UIGestureRecognizerStateChanged) || (gesture.state == UIGestureRecognizerStateEnded)) { self.scale *= gesture.scale; // adjust our scale gesture.scale = 1; // reset gestures scale to 1 (so future changes are incremental, not cumulative) }}- (void)setup{ self.contentMode = UIViewContentModeRedraw; // if our bounds changes, redraw ourselves}- (void)awakeFromNib{ [self setup]; // get initialized when we come out of a storyboard}- (id)initWithFrame:(CGRect)frame{ self = [super initWithFrame:frame]; if (self) { [self setup]; // get initialized if someone uses alloc/initWithFrame: to create us } return self;}- (void)drawCircleAtPoint:(CGPoint)p withRadius:(CGFloat)radius inContext:(CGContextRef)context{ UIGraphicsPushContext(context); CGContextBeginPath(context); CGContextAddArc(context, p.x, p.y, radius, 0, 2*M_PI, YES); // 360 degree (0 to 2pi) arc CGContextStrokePath(context); UIGraphicsPopContext();}- (void)drawRect:(CGRect)rect{ CGContextRef context = UIGraphicsGetCurrentContext(); CGPoint midPoint; // center of our bounds in our coordinate system midPoint.x = self.bounds.origin.x + self.bounds.size.width/2; midPoint.y = self.bounds.origin.y + self.bounds.size.height/2; CGFloat size = self.bounds.size.width / 2; if (self.bounds.size.height < self.bounds.size.width) size = self.bounds.size.height / 2; size *= self.scale; // scale is percentage of full view size CGContextSetLineWidth(context, 5.0); [[UIColor blueColor] setStroke]; [self drawCircleAtPoint:midPoint withRadius:size inContext:context]; // head #define EYE_H 0.35#define EYE_V 0.35#define EYE_RADIUS 0.10 CGPoint eyePoint; eyePoint.x = midPoint.x - size * EYE_H; eyePoint.y = midPoint.y - size * EYE_V; [self drawCircleAtPoint:eyePoint withRadius:size * EYE_RADIUS inContext:context]; // left eye eyePoint.x += size * EYE_H * 2; [self drawCircleAtPoint:eyePoint withRadius:size * EYE_RADIUS inContext:context]; // right eye#define MOUTH_H 0.45#define MOUTH_V 0.40#define MOUTH_SMILE 0.25 CGPoint mouthStart; mouthStart.x = midPoint.x - MOUTH_H * size; mouthStart.y = midPoint.y + MOUTH_V * size; CGPoint mouthEnd = mouthStart; mouthEnd.x += MOUTH_H * size * 2; CGPoint mouthCP1 = mouthStart; mouthCP1.x += MOUTH_H * size * 2/3; CGPoint mouthCP2 = mouthEnd; mouthCP2.x -= MOUTH_H * size * 2/3; float smile = [self.dataSource smileForFaceView:self]; if (smile < -1) smile = -1; if (smile > 1) smile = 1; CGFloat smileOffset = MOUTH_SMILE * size * smile; mouthCP1.y += smileOffset; mouthCP2.y += smileOffset; CGContextBeginPath(context); CGContextMoveToPoint(context, mouthStart.x, mouthStart.y); CGContextAddCurveToPoint(context, mouthCP1.x, mouthCP2.y, mouthCP2.x, mouthCP2.y, mouthEnd.x, mouthEnd.y); // bezier curve CGContextStrokePath(context);}@end
容芳志 (http://blog.csdn.net/totogo2010)
本文遵循“署名-非商业用途-保持一致”创作公用协议
- 2011斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- 2011斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- 2011斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- 2011斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- 斯坦福大学公开课 iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- 斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- 斯坦福大学iOS应用开发教程学习笔记
- 斯坦福大学iOS应用开发教程学习笔记
- 斯坦福大学iOS应用开发教程学习笔记
- 2011斯坦福大学iOS应用开发教程学习笔记(第二课)My First iOS App
- 2011斯坦福大学iOS应用开发教程学习笔记(第二课)My First iOS App
- 2011斯坦福大学iOS应用开发教程学习笔记(第二课)My First iOS App
- 2011年冬斯坦福大学公开课 iOS应用开发教程学习笔记(第四课) Views 视图
- 2011年冬斯坦福大学公开课 iOS应用开发教程学习笔记(第四课) Views 视图
- 2011年冬斯坦福大学公开课 iOS应用开发教程学习笔记(第四课) Views 视图
- 2011斯坦福大学iOS应用开发教程学习笔记(第一课)MVC.and.Introduction.to.Objective-C
- 2011斯坦福大学iOS应用开发教程学习笔记(第三课)Objective-C
- 2011斯坦福大学iOS应用开发教程学习笔记(第六课)故事版
- FLEX中使用outerDocument
- Spring获取bean方式(BeanFactory和ApplicationContext)
- 【Tech-Android-Other】Android中有效自定义View的注意事项
- ASP.NET连接数据库
- 微软面试智力题
- 2011斯坦福大学iOS应用开发教程学习笔记(第五课)Protocols,手势识别
- ora.rac1.LISTENER_RAC1.lsnr` on member `rac1` has experienced an unrecoverable failure
- OpenGL ES 01]OpenGL ES之初体验
- kernel tips
- UVa 324 - Factorial Frequencies
- Fibnacci序列(递归)
- Web Dicom Viewer
- Windows Media Service9
- Windows Media Service网络电台服务器架设教程