ScrollViewをエレベーター風にボタンで動くようにしたiPhoneアプリのサンプルコードを描いてみます。
動かすとこんな感じです
サンプルコード
#import “ViewController.h”
@interface ViewController ()
@property BOOL doorOpen;
@property (weak, nonatomic) UIScrollView *scroll;
@end
@implementation ViewController
– (void)viewDidAppear:(BOOL)animated
{
[self createFloor];
[self createElevator];
[self open];
}
– (void)createFloor
{
float h = CGRectGetMaxY(self.view.bounds);
UIScrollView *v = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(self.view.bounds), h * 5.0)];
v.backgroundColor = [UIColor whiteColor];
[self.view addSubview:v];
for (int i=0; i<5; i++) {
for (int j=0; j<30; j++) {
UILabel *l = [[UILabel alloc] init];
l.text = [NSString stringWithFormat:@”%d F”,i + 1];
float hue = (arc4random() % 10) * 0.1;
l.textColor = [UIColor colorWithHue:hue saturation:0.6 brightness:0.6 alpha:1.0];
l.font = [UIFont fontWithName:@”ChalkboardSE-Bold” size:40];
[l sizeToFit];
float x = (arc4random() % 7) * 80;
float y = h * i + (arc4random() % 6) * 50 + 20;
l.center = CGPointMake(x, y);
float angle = (arc4random() * 10) * 0.2 * M_PI;
l.transform = CGAffineTransformMakeRotation(angle);
[v addSubview:l];
}
}
self.scroll = v;
}
– (void)createElevator
{
CAShapeLayer *doorR = [CAShapeLayer layer];
doorR.name = @”door”;
doorR.lineWidth = 10;
doorR.strokeColor = [UIColor lightGrayColor].CGColor;
doorR.fillColor = [UIColor darkGrayColor].CGColor;
UIBezierPath *pathR = [UIBezierPath bezierPathWithRect:CGRectMake(CGRectGetMidX(self.view.bounds), 0, CGRectGetMidX(self.view.bounds), CGRectGetMaxY(self.view.bounds))];
[pathR appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(CGRectGetMidX(self.view.bounds) + 40, 20, 100, 160)]];
pathR.usesEvenOddFillRule = YES;
doorR.fillRule = kCAFillRuleEvenOdd;
doorR.path = pathR.CGPath;
[self.view.layer addSublayer:doorR];
CAShapeLayer *doorL = [CAShapeLayer layer];
doorL.name = @”door”;
doorL.lineWidth = 10;
doorL.strokeColor = [UIColor lightGrayColor].CGColor;
doorL.fillColor = [UIColor darkGrayColor].CGColor;
UIBezierPath *pathL = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, CGRectGetMidX(self.view.bounds), CGRectGetMaxY(self.view.bounds))];
[pathL appendPath:[UIBezierPath bezierPathWithRect:CGRectMake(100, 20, 100, 160)]];
doorL.fillRule = kCAFillRuleEvenOdd;
doorL.path = pathL.CGPath;
[self.view.layer addSublayer:doorL];
CALayer *barR = [CALayer layer];
barR.frame = CGRectMake(0, 0, 80, CGRectGetMaxY(self.view.bounds));
barR.backgroundColor = [UIColor grayColor].CGColor;
barR.shadowRadius = 3.0;
barR.shadowOpacity = 0.5;
[self.view.layer addSublayer:barR];
CALayer *barL = [CALayer layer];
barL.frame = CGRectMake(CGRectGetMaxX(self.view.bounds)-80, 0, 80, CGRectGetMaxY(self.view.bounds));
barL.backgroundColor = [UIColor grayColor].CGColor;
barL.shadowRadius = 3.0;
barL.shadowOpacity = 0.5;
[self.view.layer addSublayer:barL];
for (int i=0; i<5; i++) {
float x = CGRectGetMaxX(self.view.bounds) – 40;
float y = i * 60 + 50;
UIButton *floorButton = [UIButton buttonWithType:UIButtonTypeSystem];
[floorButton setTitle:[@(i+1) stringValue] forState:UIControlStateNormal];
floorButton.titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
[floorButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[floorButton setTitleColor:[UIColor orangeColor] forState:UIControlStateSelected];
[floorButton sizeToFit];
floorButton.layer.borderColor = [UIColor whiteColor].CGColor;
floorButton.layer.borderWidth = 2;
floorButton.center = CGPointMake(x, y);
[self.view addSubview:floorButton];
[floorButton addTarget:self action:@selector(push:) forControlEvents:UIControlEventTouchUpInside];
}
}
– (void)open
{
self.doorOpen = YES;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@”name == %@”, @”door”];
NSArray *door = [self.view.layer.sublayers filteredArrayUsingPredicate:predicate];
float p[] = {CGRectGetMidX(self.view.bounds), – 200};
for (int i=0; i<2; i++) {
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@”position.x”];
a.fromValue = @([door[i] position].x);
a.toValue = @(p[i]);
a.repeatCount = 1;
a.duration = 2.0;
[door[i] setPosition:CGPointMake(p[i], [door[i] position].y)];
[door[i] addAnimation:a forKey:nil];
}
}
– (void)close
{
self.doorOpen = NO;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@”name == %@”, @”door”];
NSArray *door = [self.view.layer.sublayers filteredArrayUsingPredicate:predicate];
float p[] = {0, 0};
for (int i=0; i<2; i++) {
CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@”position.x”];
a.fromValue = @([door[i] position].x);
a.toValue = @(p[i]);
a.repeatCount = 1;
a.duration = 2.0;
[door[i] setPosition:CGPointMake(p[i], [door[i] position].y)];
[door[i] addAnimation:a forKey:nil];
}
}
– (void)push:(UIButton*)sender
{
[self.view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UIButton class]]) {
[(UIButton*)obj setSelected:NO];
}
}];
sender.selected = YES;
float h = ([sender.titleLabel.text intValue] – 1) * CGRectGetMaxY(self.view.bounds);
if (self.doorOpen) {
[self close];
[UIView animateWithDuration:3.0 delay:2.2 options:0 animations:^{
[self.scroll setContentOffset:CGPointMake(0, h) animated:NO];
} completion:^(BOOL finished) {
[self open];
}];
}
}
@end