黑馬程式設計師--分享自定義UIActionSheet
阿新 • • 發佈:2019-01-29
學完黑馬和基礎視訊許久, 最近牛刀小試, 發現在開發過程中很多UI介面都跟IOS原生的不一樣, 加上要考慮4寸與3.5寸, 許多UI都要自定義, 在處分享一下自定義UIActionSheet的實現, 希望跟大家交流學習.
首先講一下我的實現思路, 我是使用一個UIView來完成ActionSheet的介面, 之後在需要彈出的時候, 通過獲取當前keyWindow, 然後新增我的UIView起到一個模仿UIActionSheet的效果, 這裡我開放了比較多的屬性, 使ActionSheet的介面效果可以調整. 另外命名還是比較容易看懂的, 就不加太多註釋了, 自己添加了一些簡單的動畫效果, 介面佈局的, 我用一些簡單的計算去得出每一個控制元件的frame, 支援多個OtherButton的新增. 本人小菜鳥一個, 希望大神能指定一下其中的錯誤. 方便我改進.
標頭檔案:
#import <UIKit/UIKit.h> @class SettingActionSheet; @protocol SettingActionSheetDelegate <NSObject> - (void)settingActionSheet:(SettingActionSheet *)actionSheet ClickButtonAtIndex:(NSInteger)buttonIndex; @end @interface SettingActionSheet : UIView @property (weak, nonatomic) id<SettingActionSheetDelegate> delegate; @property (weak, nonatomic) UIImageView *backgroundView; @property (weak, nonatomic) UILabel *titleLabel; @property (strong, nonatomic) UIImage *cancelButtonImage; @property (strong, nonatomic) UIImage *cancelButtonHighLightImage; @property (strong, nonatomic) UIImage *otherButtonImage; @property (strong, nonatomic) UIImage *otherButtonHighLightImage; - (instancetype)initWithTitle:(NSString *)title Delegate:(id<SettingActionSheetDelegate>)delegate cancelButtonTitle:(NSString *)cancelButtonTitle ButtonTitles:(NSArray *)titles; - (void)show; @end
下面是.m檔案的實現
#import "SettingActionSheet.h" #define TitleLabelTopSpace 0 //標題欄頂部空隙 #define TitleLabelWidth 320 #define TitleLabelHeight 60 #define ButtonHeight 40 #define ButtonWidth 280 #define ButtonSpace 10 // otherButton之間的距離 #define CancelButtonHeight 40 #define CancelButtonSpace 20 //Cancel按鈕與Other按鈕之間的間距 #define LucencyViewAlpha 0.2 @interface SettingActionSheet() @property (weak, nonatomic) UIView *lucencyView; @property (copy, nonatomic) NSString *title; @property (copy, nonatomic) NSString *cancelButtonTitle; @property (strong, nonatomic) NSArray *otherButtontitles; @end @implementation SettingActionSheet - (id)initWithTitle:(NSString *)title Delegate:(id<SettingActionSheetDelegate>)delegate cancelButtonTitle:(NSString *)cancelButtonTitle ButtonTitles:(NSArray *)titles { self = [super initWithFrame:[UIScreen mainScreen].bounds]; if (self) { // 使ActionSheet的View全透明 [self setBackgroundColor:[UIColor clearColor]]; self.title = title; self.cancelButtonTitle = cancelButtonTitle; self.delegate = delegate; self.otherButtontitles = titles; } return self; } #pragma mark - 載入所有子檢視 - (void)initSubViews { // 計算背景檢視高度 NSInteger backgroundHeight = TitleLabelTopSpace + TitleLabelHeight + self.otherButtontitles.count * (ButtonHeight + ButtonSpace) + CancelButtonSpace + CancelButtonHeight + CancelButtonSpace; // 頂部半透明檢視 UIControl *lucencyView = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height - backgroundHeight)]; [lucencyView setBackgroundColor:[UIColor lightGrayColor]]; [lucencyView setAlpha:0]; [lucencyView addTarget:self action:@selector(dismissActionSheet) forControlEvents:UIControlEventTouchDown]; self.lucencyView = lucencyView; [self addSubview:lucencyView]; // 底部背景檢視 UIImageView *bgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.frame.size.height - backgroundHeight, self.frame.size.width, backgroundHeight)]; [bgView setBackgroundColor:[UIColor blackColor]]; [bgView setUserInteractionEnabled:YES]; self.backgroundView = bgView; [self addSubview:bgView]; // 標題 UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake( (320 - TitleLabelWidth) / 2, TitleLabelTopSpace, TitleLabelWidth, TitleLabelHeight)]; [titleLabel setBackgroundColor:[UIColor clearColor]]; [titleLabel setFont:[UIFont systemFontOfSize:17]]; [titleLabel setTextColor:[UIColor whiteColor]]; [titleLabel setTextAlignment:NSTextAlignmentCenter]; titleLabel.text = self.title; self.titleLabel = titleLabel; [self.backgroundView addSubview:titleLabel]; // 其它按鈕 CGFloat x = (self.frame.size.width - ButtonWidth) / 2; CGFloat otherY = TitleLabelTopSpace + TitleLabelHeight; NSInteger i = 0; for (NSString *title in self.otherButtontitles) { [self createButtonWithFrame:CGRectMake(x, otherY, ButtonWidth, ButtonHeight) Title:title Index:i]; otherY += (ButtonSpace + ButtonHeight); i++; } // 取消按鈕 CGFloat y = TitleLabelTopSpace + TitleLabelHeight + (ButtonHeight + ButtonSpace) * self.otherButtontitles.count + CancelButtonSpace; [self createCancelButtonWithFrame:CGRectMake(x, y, ButtonWidth, CancelButtonHeight) Title:self.cancelButtonTitle]; } #pragma mark - 建立OtherButton - (void)createButtonWithFrame:(CGRect)buttonFrame Title:(NSString *)title Index:(NSInteger)index { UIButton *button = [[UIButton alloc] initWithFrame:buttonFrame]; [button setTitle:title forState:UIControlStateNormal]; // 使用tag記錄index button.tag = index; // 使用設定的背景 if (self.otherButtonImage) { [button setBackgroundImage:self.otherButtonImage forState:UIControlStateNormal]; } if (self.otherButtonHighLightImage) { [button setBackgroundImage:self.otherButtonHighLightImage forState:UIControlStateHighlighted]; } // 新增響應事件 [button addTarget:self action:@selector(clickButtonAtIndex:) forControlEvents:UIControlEventTouchUpInside]; [self.backgroundView addSubview:button]; } #pragma mark - OtherButton監聽事件 - (void)clickButtonAtIndex:(UIButton *)button{ // 執行代理實現的方法 [self.delegate settingActionSheet:self ClickButtonAtIndex:button.tag]; [self dismissActionSheet]; } #pragma mark - 建立cancelButton - (void)createCancelButtonWithFrame:(CGRect)frame Title:(NSString *)title { UIButton *cancelButton = [[UIButton alloc] initWithFrame:frame]; [cancelButton setTitle:title forState:UIControlStateNormal]; if (self.cancelButtonImage) { [cancelButton setBackgroundImage:self.cancelButtonImage forState:UIControlStateNormal]; } if (self.cancelButtonHighLightImage) { [cancelButton setBackgroundImage:self.cancelButtonHighLightImage forState:UIControlStateHighlighted]; } // 響應事件 [cancelButton addTarget:self action:@selector(dismissActionSheet) forControlEvents:UIControlEventTouchUpInside]; [self.backgroundView addSubview:cancelButton]; } #pragma mark 顯示ActionSheet - (void)show { // 載入子檢視 [self initSubViews]; // 將ActionSheet新增到主螢幕上 UIView *windowView = [UIApplication sharedApplication].keyWindow; [windowView addSubview:self]; // 移出螢幕 CGRect temp = self.backgroundView.frame; CGRect rect = CGRectMake(0, [UIScreen mainScreen].bounds.size.height, temp.size.width, temp.size.height); [self.backgroundView setFrame:rect]; // 稱回螢幕 [UIView animateWithDuration:LucencyViewAlpha animations:^{ self.backgroundView.frame = temp; [self.lucencyView setAlpha:LucencyViewAlpha]; }]; } #pragma mark 退出ActionSheet - (void)dismissActionSheet { [self.lucencyView setAlpha:0]; [UIView animateWithDuration:LucencyViewAlpha animations:^{ self.backgroundView.frame = CGRectMake(0, self.frame.size.height, self.backgroundView.frame.size.width, self.backgroundView.frame.size.height); } completion:^(BOOL finished) { [self removeFromSuperview]; }]; } @end
最後是實現程式碼:
SettingActionSheet *actionSheet = [[SettingActionSheet alloc] initWithTitle:@"恢復預設設定 ?" Delegate:self cancelButtonTitle:@"取消" ButtonTitles:@[@"確定"]];
actionSheet.cancelButtonImage = [UIImage imageNamed:@"shipin_btn_anniu2_normal"];
actionSheet.cancelButtonHighLightImage = [UIImage imageNamed:@"shipin_btn_anniu2_press"];
actionSheet.otherButtonImage = [UIImage imageNamed:@"shipin_btn_anniu1_normal"];
actionSheet.otherButtonHighLightImage = [UIImage imageNamed:@"shipin_btn_anniu1_press"];
[actionSheet show];
效果圖下如: 按鈕的圖片背景可以自定義.