iOS制作带弹跳动画发布界面
程序员文章站
2023-12-21 08:02:09
项目中经常会用到带弹跳动画发布界面,具体内容如下
效果图:
代码:
// publishview.m
// uiimage+imageeffects...
项目中经常会用到带弹跳动画发布界面,具体内容如下
效果图:
代码:
// publishview.m // uiimage+imageeffects.h 苹果蒙化图片的分类 pop.h弹跳动画框架 ejextension.h模型转换框架 // 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_; /** 显示发布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文件获得一个模型数组 nsarray *buttonmodelarray = [composemodel mj_objectarraywithfilename:@"buttonimage.plist"]; cgfloat button_w = 72; cgfloat button_h = button_w + 30; nsinteger maxloc = 3; //最多列数 //按钮弹跳动画停止后的起始 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 值 //创建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 自定义动画 //创建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(@"-------这里可以写动画结束后所要执行的代码..."); // 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{ // 退出时执行动画 方法的参数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(@"发视频"); break; case 1: nslog(@"发图片"); break; case 2:{ nslog(@"发段子"); } break; case 3: nslog(@"发声音"); break; case 4: nslog(@"审贴子"); break; case 5: nslog(@"离线下载"); break; default: break; } }]; } /** 退出时与点出了某个按钮时执行的弹跳动画后销毁 window_ 移除 这个蒙板 view ,如果block参数completionblock有值先销毁window_后再执行这个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]; //创建pop基本动画对象 popbasicanimation *animation = [popbasicanimation animationwithpropertynamed:kpopviewcenter]; // popspringanimation *animation = [popspringanimation animationwithpropertynamed:kpopviewcenter]; animation.begintime = cacurrentmediatime() + (i-1) * 0.1; //动画开始时间 // 如果用这个基类 popbasicanimation 动画的执行节奏(一开始很慢, 后面很快) 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在做动画,就让执行结束的 block // 动画结束时调用的 block animation.completionblock = ^(popanimation *anim, bool finished){ nslog(@"取消时 这里可以写动画结束后所要执行的代码..."); [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(); //关闭图形上下文 image = [image applylighteffect]; //调用 image 分类方法 使图片调成蒙板状态 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]; //按钮内部图片 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; //按钮内部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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。