CS193p Lecture 7 - Views, Gestures
Views
如何绘制自定义图像
Gestures
如何处理用户手势操作
Views
1、它是基本的构造块,代表屏幕上一块矩形区域,定义了一个坐标空间,在此空间中可以绘制,可以添加触控事件;
2、它是分层级的,可以在视图中嵌套视图;
3、一个视图只有一个父视图,但可以有多个子视图,视图就是一个个的矩形,可以重叠;
4、UIWindow,所有视图都展示在其中
iOS只有一个UIWindow(不像Mac application)
self.view.window
5、
添加子视图
(void)addSubview:(UIView *)aView;
移除子视图
(void)removeFromSuperview;
6、每个UIViewController都有一个属性
@property (nomatic, strong) UIView *view;
self.view是UIViewController的顶级UIView
当View Controller创建时,这个view就被关联起来了
如图,这个名为view的outlet就关联到View
7、常用的初始化模版
- (void)setup{...} - (void)awakeFromNib{ [self setup];} - (void)initWithFrame:(CGRect)aRect{ self = [super initWithFrame:aRect]; [self setup]; return self; }
- 初始化的操作在setup方法中定义;
- 然后首先是要重写指定初始化方法,在其中调用setup;
- 其次,需要在awakeFromNib中也调用setup,原因是当一个UIView从storyboard中释放时,调用的是awakeFromNib;如果是通过alloc、init...来初始化的话,那么调用的是指定初始化方法initWithFrame;aRect制定了在父视图中的相对位置;
CGFloat
浮点数,用来表示图像大小、坐标
CGPoint
CGFloat x, y;
CGSize
CGFloat width, height;
CGRect
CGPoint origin; CGSize size;
坐标原点在左上角;
绘制的单位都是点,而不是像素点;
(Retina屏每个点=2像素点,非Retina屏每个点=1像素点)
3个与location和size有关的属性
(CGRect) frame:视图在父视图坐标中的位置和大小;
(CGRect) bounds:视图在视图本身坐标中的位置和大小;(位置就是原点(0,0))
(CGPoint) center:视图在父视图坐标中的中心点;
注意:
frame和bounds的差别不仅仅是原点不一样,当view旋转时,要包容视图的矩形变的比原视图要大,所有frame可以这样理解:它是在你的父视图坐标系中包含你的一个矩形;
Create view in XCode
先拖出一个通用视图,然后到标示符检察器(identity inspector),修改它的类;(与创建一个自定义ViewController类似)
Create view in code
alloc & initWithFrame: (CGRect frame)
或者 alloc & init (等同于 frame 为 CGRectZero,CGRectZero是原点、长、宽都为0)
drawRect : is invoked automaticall, never call it directly!!
drawRect是由系统调用的,用户不要自行调用;
When a view needs to be redrawn,use:
- (void)setNeedsDisplay;
1、Quartz库:Core Graphics
很多C函数,都是以CG开头,以context上下文作为第一参数
2、UIBezierPath类
可以绘制复杂形状组成一个大大路径,然后对其进行描边(stroke)或者填充(fill)
Core Graphics的基本流程
1. Get a context to draw into
2. Create path
3. Set colors, fonts, textures, linewidths, linecaps, etc.
4. Stroke or fill above-created paths
UIBezierPath类封装了上述全部过程
第一步:设置context上下文(相当于一张画布)
如果使用UIBezierPath来绘制,则不需要获取context,系统会自动获取;
若不得已要用CG函数来绘制,获取context的方法:
CGContextRef context = UIGraphicsGetCurrentContext();
举个🌰
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, self.bounds.size.width, self.bounds.size.height);
CGContextRotateCTM(context, M_PI);
第二步:绘制好 path
UIBezierPath *path = [[UIBezierPath alloc] init];
[path moveToPoint:CGPointMake(75, 100)];
[path addLineToPoint:CGPointMake(160, 150)];
[path addLineToPoint:CGPointMake(10, 150)];
[path closePath];
第三步:设置path的属性(包括填充fill和描边stroke)
[[UIColor greenColor] setFill];
[[UIColor redColor] setStroke];
第四步:将path属性赋予path
[path fill];
[path stroke];
注意到:只有执行完第四步,才真正绘制完成;若只到第二步,此时的path只是一条没有粗细、颜色的路径,所以页面上海看不到;
Draw Text
NSAttributedString *text = ...;
[text drawAtPoint:(CGPoint)p];
Draw Image
UIImage *image = ...;
[image drawAtPoint:(CGPoint)p];
[image drawInRect:(CGRect)r]; // 拉伸图片以适应区域
[image drawAsPatternInRect:(CGRect)patRect]; //平铺图片以充满区域
UIGestureRecognizer
是所有手势操作类的基类,无法实例化,我们用到的都是它的子类
1、Adding a gesture recognizer to a UIView;
2、A method to "handle" that gesture when it happens;
UIPanGestureRecognizer
translationInView:
velocityInView:
setTranslation:inView:
@property (readonly) UIGestureRecognizerState state;
Began、Changed、Ended: for continus gestures like a pan(拖动) or pinch(捏合)
Recognized:for discrete gestures like a tap(点击) or swipe(滑动)
Failed、Canneled:手势操作中来电话等
UIPinchGestureRecognizer(捏合、缩放)
scale:表示缩放比例,初始值1.0
velocity:缩放速度
UIRotationGestureRecognizer(旋转)
rotaton:表示旋转角度
velocity:旋转速度
UISwipeGestureRecognizer(滑动)
@property UISwipeGestureRecognizerDirection direction;
@property NSUInteger numberOfTouchesRequired;