iOS制作帶彈跳動畫發(fā)布界面
更新時間:2021年09月23日 09:31:55 作者:cybtop
這篇文章主要為大家詳細介紹了iOS制作帶彈跳動畫發(fā)布界面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
項目中經(jīng)常會用到帶彈跳動畫發(fā)布界面,具體內(nèi)容如下
效果圖:

代碼:
// PublishView.m
// UIImage+ImageEffects.h 蘋果蒙化圖片的分類 pop.h彈跳動畫框架 EJExtension.h模型轉(zhuǎn)換框架
// ComposeModel 用于設置按鈕文字與圖片的模型,在本地設置plist文件保存image(按鈕圖片)和text(按鈕文字)
#import "PublishView.h"
#import "BSVerticalButton.h"
#import "UIImage+ImageEffects.h"
#import "pop.h"
#import "MJExtension.h"
#import "ComposeModel.h"
@interface PublishView ()
/** 取消按鈕 */
@property (nonatomic, weak) UIButton *cancelButton;
@end
@implementation PublishView
/** 全局 window_ */
static UIWindow *window_;
/** 顯示發(fā)布view */
+ (void)show{
// 添加一個獨立的window是為了隔離點擊事件
window_ = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
window_.hidden = NO;
PublishView *publish = [[PublishView alloc]init];
publish.frame = window_.bounds;
[window_ addSubview:publish];
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIImageView *imageView = [[UIImageView alloc]initWithImage:[self getEffectImage]];
[self addSubview:imageView];
[self setupUI];
}
return self;
}
- (void)setupUI{
//這里用自定義的 window 是為了隔絕點擊事件 不讓點擊事件傳到后面控制器的view上去
// 按鈕彈跳動畫時讓view本身不能點擊
self.userInteractionEnabled = NO;
// 從plis文件獲得一個模型數(shù)組
NSArray *buttonModelArray = [ComposeModel mj_objectArrayWithFilename:@"buttonImage.plist"];
CGFloat button_w = 72;
CGFloat button_h = button_w + 30;
NSInteger maxLoc = 3; //最多列數(shù)
//按鈕彈跳動畫停止后的起始 y 值
CGFloat buttonEnd_y = ([[UIScreen mainScreen] bounds].size.height - button_h * 2) / 2;
//最開始在屏幕外上方的的起始 y 值
CGFloat buttonBegin_y = buttonEnd_y - [[UIScreen mainScreen] bounds].size.height;
//按鈕的起始間隙值
CGFloat buttonStartMargin = 20;
//中間的一個按鈕相對于兩邊按鈕的間隙
CGFloat buttonMargin = ([[UIScreen mainScreen] bounds].size.width - buttonStartMargin * 2 - button_w * maxLoc) / (maxLoc - 1);
for (NSInteger i = 0; i < buttonModelArray.count; ++i) {
// BSVerticalButton 自定義的垂直排布按鈕
BSVerticalButton *button = [[BSVerticalButton alloc]init];
button.tag = i;
[self addSubview:button];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
ComposeModel *composeModel = buttonModelArray[i];
[button setImage:[UIImage imageNamed:composeModel.image] forState:UIControlStateNormal];
[button setTitle:composeModel.text forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:14];
NSInteger loc = i % maxLoc; //例號
NSInteger row = i / maxLoc; //行號
CGFloat button_x = buttonStartMargin + loc * (button_w + buttonMargin);
CGFloat buttonBginAnimation_y = buttonBegin_y + (button_h * row); //彈跳前的 y 值
CGFloat buttonEndAnimation_y = buttonEnd_y + (button_h * row); //彈跳后的 y 值
//創(chuàng)建pop彈簧動畫對象
POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame];
animation.beginTime = CACurrentMediaTime() + i * 0.1; //動畫開始時間
animation.springBounciness = 10; //彈簧增強 0-20
animation.springSpeed = 8; //彈簧速度 0-20
animation.fromValue = [NSValue valueWithCGRect:CGRectMake(button_x, buttonBginAnimation_y, button_w, button_h)];
animation.toValue = [NSValue valueWithCGRect:CGRectMake(button_x, buttonEndAnimation_y, button_w, button_h)];
//中間的按鈕添加動畫
[button pop_addAnimation:animation forKey:nil];
}
// 添加品牌logo
UIImageView *topImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"compose_slogan"]];
topImageView.center = CGPointMake([[UIScreen mainScreen] bounds].size.width * 0.5, [[UIScreen mainScreen] bounds].size.height * 0.2 - [[UIScreen mainScreen] bounds].size.height);
[self addSubview:topImageView];
// POPBasicAnimation 基本的動畫
// POPSpringAnimation 彈簧動畫
// POPDecayAnimation 減速動畫
// POPCustomAnimation 自定義動畫
//創(chuàng)建pop彈簧動畫對象
POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
animation.beginTime = CACurrentMediaTime() + buttonModelArray.count * 0.001; //動畫開始時間
animation.springBounciness = 10; //彈簧增強 0-20
animation.springSpeed = 10; //彈簧速度 0-20
CGFloat center_x = [[UIScreen mainScreen] bounds].size.width * 0.5;
CGFloat endCenter_y = [[UIScreen mainScreen] bounds].size.height * 0.2;
CGFloat beginCenter_y = endCenter_y - [[UIScreen mainScreen] bounds].size.height;
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(center_x, beginCenter_y)];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(center_x, endCenter_y)];
animation.completionBlock = ^(POPAnimation *anim, BOOL finished){
NSLog(@"-------這里可以寫動畫結(jié)束后所要執(zhí)行的代碼...");
// view本身開啟交互
self.userInteractionEnabled = YES;
};
//給頂部的圖片添加動畫
[topImageView pop_addAnimation:animation forKey:nil];
// 底部取消按鈕
UIButton *cancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
[cancelButton setTitle:@"取 消" forState:UIControlStateNormal];
cancelButton.titleLabel.font = [UIFont systemFontOfSize:15];
[cancelButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[cancelButton setBackgroundColor:[UIColor whiteColor]];
[cancelButton addTarget:self action:@selector(cancelButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:cancelButton];
self.cancelButton = cancelButton;
}
- (void)cancelButtonClick:(UIButton *)button{
// 退出時執(zhí)行動畫 方法的參數(shù)block傳空
[self animationWithBlock:nil];
}
- (void)layoutSubviews{
[super layoutSubviews];
// 取消按鈕位置大小
CGPoint center = self.cancelButton.center;
center.x = self.center.x;
self.cancelButton.center = center;
CGRect frame = self.cancelButton.frame;
frame.origin.y = self.frame.size.height * 0.85;
frame.size = CGSizeMake(200, 35);
self.cancelButton.frame = frame;
}
- (void)buttonClick:(UIButton *)button{
[self animationWithBlock:^{
switch (button.tag) {
case 0:
NSLog(@"發(fā)視頻");
break;
case 1:
NSLog(@"發(fā)圖片");
break;
case 2:{
NSLog(@"發(fā)段子");
}
break;
case 3:
NSLog(@"發(fā)聲音");
break;
case 4:
NSLog(@"審貼子");
break;
case 5:
NSLog(@"離線下載");
break;
default:
break;
}
}];
}
/** 退出時與點出了某個按鈕時執(zhí)行的彈跳動畫后銷毀 window_ 移除 這個蒙板 view ,如果block參數(shù)completionBlock有值先銷毀window_后再執(zhí)行這個block里的代碼塊 */
- (void)animationWithBlock:(void (^) ())completionBlock{
NSLog(@"----%@\n",self.subviews);
//退出的時候這里用自定義的 window 是為了隔絕點擊事件 不讓點擊事件傳到后面控制器的view上去
// view本身不能點
self.userInteractionEnabled = NO;
// 選移除取消按鈕
[self.cancelButton removeFromSuperview];
for (NSInteger i = 1; i < self.subviews.count; ++i) {
UIView *view = self.subviews[i];
//創(chuàng)建pop基本動畫對象
POPBasicAnimation *animation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
// POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
animation.beginTime = CACurrentMediaTime() + (i-1) * 0.1; //動畫開始時間
// 如果用這個基類 POPBasicAnimation 動畫的執(zhí)行節(jié)奏(一開始很慢, 后面很快)
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
CGPoint center = view.center; //取出中心點
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(center.x , center.y + [[UIScreen mainScreen] bounds].size.height)];
if (i == self.subviews.count-1) { //說明是最后一個 view在做動畫,就讓執(zhí)行結(jié)束的 block
// 動畫結(jié)束時調(diào)用的 block
animation.completionBlock = ^(POPAnimation *anim, BOOL finished){
NSLog(@"取消時 這里可以寫動畫結(jié)束后所要執(zhí)行的代碼...");
[self removeFromSuperview];
window_ = nil; //銷毀自定義的 window
!completionBlock ? : completionBlock();
};
}
//給頂部的圖片添加動畫
[view pop_addAnimation:animation forKey:nil];
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self animationWithBlock:nil];
}
// 獲得一個磨紗蒙板 image 圖片
- (UIImage *)getEffectImage{
UIWindow *window = [UIApplication sharedApplication].keyWindow; //獲取當前 window
UIGraphicsBeginImageContext(window.size); //開啟window大小的圖形上下文
CGContextRef ref = UIGraphicsGetCurrentContext(); //開啟圖形上下文
[window.layer renderInContext:ref]; //把window圖層 渲染到圖形上下文當中
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); //獲取圖片
UIGraphicsEndImageContext(); //關(guān)閉圖形上下文
image = [image applyLightEffect]; //調(diào)用 image 分類方法 使圖片調(diào)成蒙板狀態(tài)
return image;
}
@end
項目中用到的垂直布局自定義按鈕 BSVerticalButton
#import "BSVerticalButton.h"
@implementation BSVerticalButton
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setupUI];
}
return self;
}
- (void)awakeFromNib{
[super awakeFromNib];
[self setupUI];
}
- (void)setupUI{
self.titleLabel.textAlignment = NSTextAlignmentCenter;
}
- (void)layoutSubviews{
[super layoutSubviews];
//按鈕內(nèi)部圖片 frame
CGRect imageViewFrame = self.imageView.frame;
imageViewFrame.origin.x = 0;
imageViewFrame.origin.y = 0;
imageViewFrame.size.width = self.bounds.size.width;
imageViewFrame.size.height = self.bounds.size.width;
self.imageView.frame = imageViewFrame;
//按鈕內(nèi)部label frame
CGRect titleLabelFrame = self.titleLabel.frame;
titleLabelFrame.origin.x = 0;
titleLabelFrame.origin.y = self.imageView.frame.size.height + 10;
titleLabelFrame.size.width = self.bounds.size.width;
self.titleLabel.frame = titleLabelFrame;
//按鈕自身大小
CGRect buttonBounds = self.bounds;
buttonBounds.size.width = self.imageView.frame.size.width;
buttonBounds.size.height = self.imageView.bounds.size.height + self.titleLabel.bounds.size.height + 10;
self.bounds = buttonBounds;
}
@end
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
IOS中NSPredicate和NSRegularExpression校驗正則表達式區(qū)別
本文文章通過實例代碼給大家講述了在IOS開發(fā)中NSPredicate和NSRegularExpression校驗正則表達式區(qū)別,需要的朋友趕快學習下吧。2018-01-01

