需求:view需根据y轴移动,固定x轴,且滑动不超出屏幕,点击按钮后文字出现,五秒后自动消失
xib RabbitView
RabbitView.h
#import <UIKit/UIKit.h>
typedef void(^ClickRabbitBlock)();
typedef void(^PanGestureRecognizer)(UIPanGestureRecognizer *panGes);
@interface RabbitView : UIView
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIImageView *backImage;
// 初始化view
+ (instancetype)initWithChickenView;
@property (nonatomic, copy) ClickRabbitBlock block;
@property (nonatomic, copy) PanGestureRecognizer panBlock;
@property (weak, nonatomic) IBOutlet UIButton *rabbitBut;
@property (nonatomic, assign) CGRect rabbitFrame;//记录移动后的frame
// 设置兔子的背景图与文字是隐藏还是显示
- (void)rabbitViewHidden:(BOOL)hidden frame:(CGRect)frame;
@end
RabbitView.m
#import "RabbitView.h"
@implementation RabbitView
- (void)awakeFromNib {
[super awakeFromNib];
// 这里给view添加一个手势
// 我这里因为view也需要可移动所以加在了view上,只需要移动按钮的,可以直接将手势加在按钮上
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[self addGestureRecognizer:pan];
// 因为背景图有颜色,不设置clear的话滑动到灰色区域会显示白边
self.backgroundColor = [UIColor clearColor];
}
// 设置兔子的背景图与文字是隐藏还是显示
- (void)rabbitViewHidden:(BOOL)hidden frame:(CGRect)frame {
// 隐藏文字与背景图
if (hidden == YES) {
self.backImage.hidden = YES;
self.titleLabel.hidden = YES;
// 过渡动画
[UIView transitionWithView:self duration:0.8 options:UIViewAnimationOptionShowHideTransitionViews animations:^{
// 更新界面的宽度
[self mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(60);
}];
} completion:^(BOOL finished) {
}];
} else {
// 显示背景图与文字
self.backImage.hidden = NO;
self.titleLabel.hidden = NO;
// 过渡动画
[UIView transitionWithView:self duration:0.8 options:UIViewAnimationOptionAllowAnimatedContent animations:^{
// 更新界面的宽度
[self mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(220);
}];
} completion:^(BOOL finished) {
}];
}
// ******* 注意这里
// 判断是否是初始位置,origin.y默认是0,如果没有移动过直接点击按钮,y会移动到顶部
if (frame.origin.y != 0) {
// 设置更新宽度后origin.y的位置,如果此处不处理的话容易造成点击后回到初始y轴位置
[self mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(frame.origin.y);
}];
}
}
- (void)panAction:(UIPanGestureRecognizer *)pan {
if (self.panBlock) {
self.panBlock(pan);
}
}
- (IBAction)clickRabbitButtonAction:(id)sender {
// 判断是背景图与文字隐藏还是显示,以防5秒执行未结束又开启下一次执行
if (self.backImage.hidden == YES) {
if (self.block) {
self.block();
}
}
}
+ (instancetype)initWithChickenView {
NSString *className = NSStringFromClass([self class]);
UINib *nib = [UINib nibWithNibName:className bundle:nil];
return [nib instantiateWithOwner:nil options:nil].firstObject;
}
ViewController.m
@interface SearchViewController ()
@property (nonatomic, strong) RabbitView *rabbitView;
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation SearchViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.rabbitView];
[self.rabbitView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(-3);
make.top.mas_equalTo(SCREEN_HEIGHT-100);
make.width.mas_equalTo(60);
make.height.mas_equalTo(65);
}];
[self clickWithRabbitView];
}
// 点击兔子视图
- (void)clickWithRabbitView {
__weak typeof(self) weakSelf = self;
// 点击兔子
self.rabbitView.block = ^{
// 显示
[weakSelf.rabbitView rabbitViewHidden:NO frame:weakSelf.rabbitFrame];
// 开启定时器
[weakSelf addTimerWithClickRabbit];
};
// 移动兔子
self.rabbitView.panBlock = ^(UIPanGestureRecognizer *panGes) {
// x轴固定 判断y轴是否超出界面
CGPoint translationPoint = [panGes translationInView:weakSelf.view];
CGPoint center = panGes.view.center;
//计算view本身的center y
CGFloat centerY = weakSelf.rabbitView.bounds.size.height / 2;
//计算view顶部的偏移量 20是statusbar高度
CGFloat topCenterY = centerY + 20;
//计算view底部的偏移量
CGFloat bottomCenterY = SCREEN_HEIGHT - centerY;
//计算view center x 的偏移量 固定x轴(-3是因为为了背景图的自适应,正常计算不用-3)
CGFloat centerX = weakSelf.rabbitView.bounds.size.width / 2 - 3;
// 当现在的偏移量大于顶部偏移量时,根据现在的偏移量移动
if (center.y >= topCenterY) {
panGes.view.center = CGPointMake(centerX, center.y + translationPoint.y);
[panGes setTranslation:CGPointZero inView:weakSelf.view];
} else {
// 当偏移量小于顶部偏移量时,根据最顶端偏移量固定
panGes.view.center = CGPointMake(centerX, topCenterY);
[panGes setTranslation:CGPointZero inView:weakSelf.view];
}
// 当现在的偏移量大于底部偏移量时,根据最底端偏移量固定
if (center.y > bottomCenterY) {
panGes.view.center = CGPointMake(centerX, bottomCenterY);
[panGes setTranslation:CGPointZero inView:weakSelf.view];
}
// 记录移动后此时的frame
weakSelf.rabbitFrame = panGes.view.frame;
};
}
// 五秒后执行定时器,隐藏兔子
- (void)fiveLaterAction {
[self.rabbitView rabbitViewHidden:YES frame:self.rabbitFrame];
[_timer invalidate];
_timer = nil;
}
// 开启定时器
- (void)addTimerWithClickRabbit {
// 五秒后隐藏
NSTimer*timer=[NSTimer timerWithTimeInterval:5 target:self selector:@selector(fiveLaterAction) userInfo:nil repeats:NO];
_timer = timer;
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}
//初始化view
- (RabbitView *)rabbitView {
if (!_rabbitView) {
_rabbitView = [RabbitView initWithChickenView];
_rabbitView.backImage.hidden = YES;
_rabbitView.titleLabel.hidden = YES;
}
return _rabbitView;
}