iOS学习笔记-03UI

Posted by 蔡华的博客 on September 16, 2016

3.UI

  • iOS的UI开发说起来复杂也不复杂,复杂在于控件很多,属性很多,各种delegate,但是众多的控件也遵循着相同的模式,让人学起来会觉得可以举一反三。同时在UI这个大的标题下还有Draw、layer、transforms、animation、touch这些技术点。想要做出一些非常规UI效果往往不是依靠简单的使用SDK提供的控件可以做到的。

3.1 手动编写UI

  • 个人认知:手动编写UI在iOS不需要考虑手机屏幕尺寸的时代是很好用的,但是随着多种尺寸屏幕的出现,在自适应上手动编写UI代码就有了一些局限性。
  • 手动编写的核心在于创建UI对象,设置frame及各种属性。
  • 当然也可以使用xib来拖动UI,然后让UI与代码关联进而编写相关功能。

3.2 autolayout

  • 目前在Xcode中可以很好的时候用约束(constraints)来实现UI的自适应。
  • constraints的使用心得:
    1. 按住ctrl+左键来创建约束
    2. 可以在Constraints下找到具体的约束,进而进行修改。
  1. 其基本的使用可以对比NGUI,都是距离superview上下左右的距离,与其它View的间距、size等约束。
  2. 需要注意,当存在多层关系时,需要逐层设置,否则效果可能有问题。
  3. 对于constraint不但可以通过视图来设置,还可以编写代码来设置或修改。只要关联到代码(类似其它UI关联带代码的方式)就可以控制,一般只修改constraint属性。
  4. 活用 -△- -口- 两个图标按钮。

3.3 触摸和手势识别器

  • 触摸的信息包含触摸点的位置、处于的阶段,其包含在UITouch对象中,手势是在触摸的基础上SDK封装的功能,它将一些复杂的连续触摸抽象成一个个手势动作。UITouch对象保存了含有手势识别器的数组。这个 数组里的每个元素都是手势识别器,而每个识别器都用来接收相关的触摸对象。如果创建某个 视图时没有指定手势识别器,那么在系统传给响应者方法的。而UIEvent对象包含了多个UITouch对象,多少由触摸点决定。

  • 触摸的五个阶段:UITouchPhaseBeganUITouchPhaseMovedUITouchPhaseStationaryUITouchPhaseEndedUITouchPhaseCancelled,除了stationary其它都可以在代码中重写方法(其实就是其它四个是可以callUIResponder中预定义好的回调方法)。以下代码演示了拖地效果的touch实现

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent *)event
{
	// Calculate and store offset, and pop view into front if needed
	startLocation = [[touches anyObject] locationInView:self];
	[self.superview bringSubviewToFront:self];
}

- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent *)event
{
	// Calculate offset
	CGPoint pt = [[touches anyObject] locationInView:self];
	float dx = pt.x - startLocation.x;
	float dy = pt.y - startLocation.y;
	CGPoint newcenter = CGPointMake(self.center.x + dx, self.center.y + dy);
	
	// Set new location
	self.center = newcenter;
}
  • 触摸分为单点和多点触摸,控制代码self.multipleTouchEnabled = YES;控制。

  • 手势识别器主要有点击(tap)、滑动(swipe)、手指聚拢(pinch)、旋转(rotate),拖动(pan)、长按(long press)。其基本用法都一样,类似:

 UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
        self.gestureRecognizers = @[panRecognizer];
  • 一个控件可以同时使用多个手势识别器。

  • 关于同时识别手势的问题,一般是一个手势由一个控件识别但是通过下面的代码可以让一个手势被多个对象识别。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}
  • 注意事项:
    1. 一些图片带有透明区域,因此有可能点击了透明区域也被识别为tap。
    2. 拖动的处理可以通过touch相关的函数或者手势,这就引出了放射变换的一些问题。

AffineTransform,仿射变换。其中transform定义为

> ```
> struct CGAffineTransform {
>  CGFloat a, b, c, d;
>  CGFloat tx, ty;
>};
> ```

它包含了位置、旋转、缩放三个信息。类似U3D中的transform的概念。

变换的本质是矩阵的计算,((x,0,0),(0,y,0),(tx,ty,1))。

SDK中有很多的方法,基础的方法是CGAffineTransformMake(a,b,c,d,tx,ty),参数对应矩阵。还有GAffineTransformMakeXXX和GAffineTransformXXX两个系列的方法。

3.4 控件