【iOS】UIStackViewを使ってアコーディオンを作る
やりたいこと
UIScrollViewがある状態でこういうアコーディオンが作りたい
どうつくるか
UIStackViewを使います。
また、UILabelの高さを直接変更すると意図しない動きになるので、
ClipToBoundsをオンにしたViewを利用します。
つくりかた
Storybordで気をつける点は以下です
- 上下左右の制約0でUIScrollViewを配置する(ContentLayaoutGuidesのチェックは外しておく)
- UIScrollViewの中に、上下左右の制約0でUIStackViewを配置する。横幅はUIScrollViewと同じになる制約を追加する。
- UIButtonの下にViewを配置、左右の制約0、高さの制約も0にする。ClipToBoundsをオンにする。
- ClipToBoundsをオンにしたViewの中に、上左右の制約0でUILabelを配置
動きをつける
ボタンが押されたら、高さ0で設定した制約を、UILabelの高さと同じに変えます。 開いている場合は、再び高さ0に設定します。
#import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet NSLayoutConstraint *acoordionView1Height; @property (weak, nonatomic) IBOutlet UILabel *label1; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *accordionView2Height; @property (weak, nonatomic) IBOutlet UILabel *label2; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (IBAction)button1:(id)sender { [self.view layoutIfNeeded]; if (_acoordionView1Height.constant != 0){ _acoordionView1Height.constant = 0; }else{ _acoordionView1Height.constant = _label1.frame.size.height; } [UIView animateWithDuration:0.3f animations:^{ [self.view layoutIfNeeded]; }]; } - (IBAction)button2:(id)sender { [self.view layoutIfNeeded]; if (_accordionView2Height.constant != 0){ _accordionView2Height.constant = 0; }else{ _accordionView2Height.constant = _label2.frame.size.height; } [UIView animateWithDuration:0.3f animations:^{ [self.view layoutIfNeeded]; }]; }
GitHub
【iOS】UIButtonでハイライトや無効時の色を指定する
UIButtonを拡張して、UIControlStateHighlightedやUIControlStateDisabledにsetBackgroundColorで色を指定する方法です。
UIButtonの拡張クラス
StateColorButton.h @interface StateColorButton : UIButton - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state; @end
#import "StateColorButton.h" @interface StateColorButton() @property (nonatomic, strong) NSMutableDictionary *backgroundColors; @end @implementation StateColorButton #pragma mark - Background Colors - (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state { if (!self.backgroundColors) { self.backgroundColors = [[NSMutableDictionary alloc] init]; } if (backgroundColor) { self.backgroundColors[@(state)] = backgroundColor; } if (state == UIControlStateNormal) { self.backgroundColor = backgroundColor; } } - (void)transitionBackgroundToColor:(UIColor*)color { CATransition *animation = [CATransition animation]; animation.type = kCATransitionFade; [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [self.layer addAnimation:animation forKey:@"EaseOut"]; self.backgroundColor = color; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; UIColor *selectedColor = self.backgroundColors[@(UIControlStateHighlighted)]; if (selectedColor) { [self transitionBackgroundToColor:selectedColor]; } } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesCancelled:touches withEvent:event]; UIColor *normalColor = self.backgroundColors[@(UIControlStateNormal)]; if (normalColor) { [self transitionBackgroundToColor:normalColor]; } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesEnded:touches withEvent:event]; UIColor *normalColor = self.backgroundColors[@(UIControlStateNormal)]; if (normalColor) { [self transitionBackgroundToColor:normalColor]; } } - (void)setEnabled:(BOOL)enabled { [super setEnabled:enabled]; if (enabled){ self.backgroundColor = self.backgroundColors[@(UIControlStateNormal)]; }else{ self.backgroundColor = self.backgroundColors[@(UIControlStateDisabled)]; } } @end
使い方
StateColorButton *button = [[StateColorButton alloc] initWithFrame:CGRectMake(50, 100, 200, 36)]; [button setTitle:@"button" forState:UIControlStateNormal]; // 状態に応じて色変更 [button setBackgroundColor:[UIColor blueColor] forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor greenColor] forState:UIControlStateHighlighted]; [button setBackgroundColor:[UIColor blackColor] forState:UIControlStateDisabled]; [self.view addSubview:button];