本次要做的例子是iOS的弹出视图动画,不喜欢废话,直接上图:
上图就是要实现的效果,不喜欢看文章的人,点击 这里 直达代码。
该Demo中涉及两个类:
PopOutView:弹出视图类
MJPopTool:弹出视图工具类
1、PopOutView
.h文件代码如下:
#import <UIKit/UIKit.h>
@class PopOutView;
typedef void(^PopOutViewDismissBlock)(PopOutView *popOutView);
@interface PopOutView : UIView
@property (nonatomic, copy) PopOutViewDismissBlock dismissBlock;
@end
.m代码如下
#import "PopOutView.h"
@interface PopOutView ()
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIButton *closeButton;
@end
@implementation PopOutView
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
_imageView = [[UIImageView alloc] init];
[self addSubview:_imageView];
_closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_closeButton setBackgroundImage:[UIImage imageNamed:@"red_packge_close"] forState:UIControlStateNormal];
[_closeButton addTarget:self action:@selector(close) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_closeButton];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
_imageView.frame = self.bounds;
_imageView.image = [UIImage imageNamed:@"cat.jpg"];
_closeButton.frame = CGRectMake(self.bounds.size.width - 15, -15, 30, 30);
}
/**
* @author 王梦杰, 16-06-24 13:06:00
*
* 让超出父视图的子视图响应事件
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (view == nil) {
for (UIView *subView in self.subviews) {
CGPoint tp = [subView convertPoint:point fromView:self];
if (CGRectContainsPoint(subView.bounds, tp)) {
view = subView;
}
}
}
return view;
}
- (void)close {
if (_dismissBlock) {
_dismissBlock(self);
}
}
@end
这个界面直接放了一个imageView和closeButton,并且用block实现按钮点击事件的传递,这边也可以使用代理,看个人喜好。布局代码比较简单,就不啰嗦了,这里有一段代码可能需要讲解一下用途:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (view == nil) {
for (UIView *subView in self.subviews) {
CGPoint tp = [subView convertPoint:point fromView:self];
if (CGRectContainsPoint(subView.bounds, tp)) {
view = subView;
}
}
}
return view;
}
由于closeButton是PopOutView的子视图,并且closeButton有一部分在PopOutView视图的外面,会导致该部分的点击无响应,上面那一段代码的作用就是为了使超出父视图边界部分也可以得到响应。如果想知道具体原理的,请看这里。
2、MJPopTool
该类是一个单例类,提供了两个对象方法,一个用于弹出视图,另一个用于关闭视图。
/**
* 弹出视图
*
* @param view 被弹出的视图
* @param animated 是否需要动画
*/
- (void)popView:(UIView *)view animated:(BOOL)animated;
/**
* 关闭视图
*
* @param animated 是否需要动画
*/
- (void)closeAnimated:(BOOL)animated;
这两个方法的具体实现代码:
- (void)popView:(UIView *)view animated:(BOOL)animated {
// 保存当前弹出的视图
_currentView = view;
CGFloat halfScreenWidth = [[UIScreen mainScreen] bounds].size.width * 0.5;
CGFloat halfScreenHeight = [[UIScreen mainScreen] bounds].size.height * 0.5;
// 屏幕中心
CGPoint screenCenter = CGPointMake(halfScreenWidth, halfScreenHeight);
view.center = screenCenter;
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
[keyWindow addSubview:view];
if (animated) {
// 第一步:将view宽高缩至无限小(点)
view.transform = CGAffineTransformScale(CGAffineTransformIdentity,
CGFLOAT_MIN, CGFLOAT_MIN);
[UIView animateWithDuration:0.3
animations:^{
// 第二步: 以动画的形式将view慢慢放大至原始大小的1.2倍
view.transform =
CGAffineTransformScale(CGAffineTransformIdentity, 1.2, 1.2);
}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.2
animations:^{
// 第三步: 以动画的形式将view恢复至原始大小
view.transform = CGAffineTransformIdentity;
}];
}];
}
}
- (void)closeAnimated:(BOOL)animated {
if (animated) {
[UIView animateWithDuration:0.2
animations:^{
// 第一步: 以动画的形式将view慢慢放大至原始大小的1.2倍
_currentView.transform =
CGAffineTransformScale(CGAffineTransformIdentity, 1.2, 1.2);
}
completion:^(BOOL finished) {
[UIView animateWithDuration:0.3
animations:^{
// 第二步: 以动画的形式将view缩小至原来的1/1000分之1倍
_currentView.transform = CGAffineTransformScale(
CGAffineTransformIdentity, 0.001, 0.001);
}
completion:^(BOOL finished) {
// 第三步: 移除
[_currentView removeFromSuperview];
}];
}];
} else {
[_currentView removeFromSuperview];
}
}
文末再次附上源码地址:去下载。
顺手点个星的都是好同志。