Creating Custom iOS User Interfaces

Make your app stand out

When Should You Build Custom UI?

  • Where will this be used?
  • Dose it need to support multiple states?
  • Can this be shared across serveral apps?
  • What APIs can be leveraged?

UIAppearance

  • UIImageRenderingMode

Dynamic Type

Accessibility

Localization

Spring Animations

Where might you use them?

  • 不想用傳統線性動態
  • 想符合原生 UIKit 的動態
  • 接近 iOS 原生動態
  • 較為自然的動態
  • 用於任意動態的屬性(alpha...)而不是只有位置
// presents
[UIView animateWithDuration:kTRANSITION_DURATION
        delay:0
        usingSpringWithDamping:0.75
        initialSpringVelocity:10
        options:0
        animations:^{ ... }];
// dismiss
[UIView animateWithDuration:kTRANSITION_DURATION - 0.1
        delay:0
        usingSpringWithDamping:1
        initialSpringVelocity:0
        options:0
        animations:^{ ... }];

Rendering in iOS

Rendering Pipeline

  1. Application - commit transaction
  2. Render server
  3. GPU
  4. Display

Commit Transaction

  • Set up and perform view layout
  • View and string drawing
  • Addition Core Animation work
  • Package up layer and send them to render server

Fast, Static Blur

drawViewHierarchyInRect:afterScreenUpdates:

UIVisualEffectView

New API for creating visual effects
Two effect types

  • Live blur
  • Vibrancy(通常用於文字,提升可讀性,不受背景模糊效果影響)

UIBlurEffect - Three styles

  • Dark
  • Light
  • ExtraLight

UIVibrancyEffect

儘可能避免

  • alpha 與 blur 混用
  • mask
  • groups
    • Animation groups
    • Opacity group

Rendering cost

  1. Standard view(效能最好)
  2. Standard view with static blur
  3. Blur effect
  4. Blur effect with vibrancy(效能最差)

CAShapeLayer

Path

bezierPath = [UIBezierPath bezierPath];
[bezierPath moveToPoint:CGPointMake(0,220)];
[bezierPath addCurveToPoint:CGPointMake(160, 115)
            controlPoint:CGPointMake(0,220)
            controlPoint:CGPointMake(15,100)];
...
[shapeLayer setPath:bezierPath.CGPath];

Line

  • lineCap(線頭的樣式:平/圓弧...)
  • lineDashPattern(虛線的樣式)
  • lineDashPhase(虛線的樣式)

Stroke

  • strokeColor(線的顏色)
  • strokeBegin(從頭算起幾%開始填色)
  • strokeEnd(從尾算起)

CAShapeLayer 是用 CPU 運算,再丟給 render server
當有複雜圖形時,將會花費大量的 CPU time。

+ (Class)layerClass {
  return [CAShapeLayer class];
}

- (void)awakeFromNib {
  CAShapeLayer *layer = (CAShapeLayer *)self.layer;
  CGPathRef path = CGPathCreateWithRect(self.bounds, NULL);
  [layer setPath:path];
  [layer setLineWidth:6];
  ...

}

Dynamic Core Animation Behaviors

CAAction Protocol

- (void)runActionForKey:(NSString *)key object:(id)anObject arguments:(NSDictionary *)dict {
  ...
}

CALayerDelegate method

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
  if ([event isEqualToString:@"opacity"]) {
    return [[APPLOpacityAction alloc] init];
  }
  return [super actionForLayer:layer forKey:event];
}

Summary

  • Spring animations
  • UIVisualEffectView
  • CAShapeLayer
  • Dynamic Core Animation behaviors