2016.09.24 23:52* 字数 71 阅读 5925评论 9喜欢 11

让所有界面都显示,最好还是封装一个继承Window的类:JYCWindow。

先看看效果:

 
mygif.gif

关键代码如下:

- (instancetype)initWithFrame:(CGRect)frame mainImageName:(NSString*)name bgcolor:(UIColor *)bgcolor animationColor:animationColor

{
if(self = [super initWithFrame:frame])
{
NSAssert(name != nil, @"mainImageName can't be nil !"); self.backgroundColor = [UIColor clearColor];
self.windowLevel = UIWindowLevelAlert + 1; //如果想在 alert 之上,则改成 + 2
self.rootViewController = [UIViewController new];
[self makeKeyAndVisible]; _bgcolor = bgcolor;
_frameWidth = frame.size.width;
_animationColor = animationColor; _mainImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_mainImageButton setFrame:(CGRect){0, 0,frame.size.width, frame.size.height}];
[_mainImageButton setImage:[UIImage imageNamed:name] forState:UIControlStateNormal];
// _mainImageButton.layer.cornerRadius = frame.size.width*0.5;
// _mainImageButton.layer.masksToBounds= YES;
_mainImageButton.alpha = normalAlpha;
[_mainImageButton addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
if (_animationColor) {
[_mainImageButton addTarget:self action:@selector(mainBtnTouchDown) forControlEvents:UIControlEventTouchDown];
} [self addSubview:_mainImageButton]; // 增加拖动window的手势
_pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(locationChange:)];
_pan.delaysTouchesBegan = NO;
[self addGestureRecognizer:_pan];
_tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(click:)];
[self addGestureRecognizer:_tap]; [self performSelector:@selector(justbegin) withObject:nil afterDelay:statusChangeDuration]; }
return self;
}

至于怎么移动,怎么动画,直接看.h和.m文件如下:

JYCWindow.h###


#import <UIKit/UIKit.h> typedef void(^CallTheService)(void); @interface JYCWindow : UIWindow //重要:所有图片都要是圆形的,程序里并没有自动处理成圆形 // warning: frame的长宽必须相等
- (instancetype)initWithFrame:(CGRect)frame mainImageName:(NSString*)name bgcolor:(UIColor *)bgcolor; // 长按雷达辐射效果
- (instancetype)initWithFrame:(CGRect)frame mainImageName:(NSString*)name bgcolor:(UIColor *)bgcolor animationColor:animationColor; // 显示(默认)
- (void)showWindow; // 隐藏
- (void)dissmissWindow; @property (nonatomic,copy)CallTheService callService;
@end

JYCWindow.m###



#import "JYCWindow.h"
#define kk_WIDTH self.frame.size.width
#define kk_HEIGHT self.frame.size.height #define kScreenWidth [[UIScreen mainScreen] bounds].size.width
#define kScreenHeight [[UIScreen mainScreen] bounds].size.height #define animateDuration 0.3 //位置改变动画时间
#define showDuration 0.1 //展开动画时间
#define statusChangeDuration 3.0 //状态改变时间
#define normalAlpha 1.0 //正常状态时背景alpha值
#define sleepAlpha 0.5 //隐藏到边缘时的背景alpha值
#define myBorderWidth 1.0 //外框宽度
#define marginWith 5 //间隔 #define WZFlashInnerCircleInitialRaius 20 @interface JYCWindow () @property(nonatomic)NSInteger frameWidth;
@property(nonatomic,strong)UIPanGestureRecognizer *pan;
@property(nonatomic,strong)UITapGestureRecognizer *tap;
@property(nonatomic,strong)UIButton *mainImageButton;
@property(nonatomic,strong)UIColor *bgcolor;
@property(nonatomic,strong)CAAnimationGroup *animationGroup;
@property(nonatomic,strong)CAShapeLayer *circleShape;
@property(nonatomic,strong)UIColor *animationColor; @end
@implementation JYCWindow
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
} - (instancetype)initWithFrame:(CGRect)frame mainImageName:(NSString*)name bgcolor:(UIColor *)bgcolor{
return [self initWithFrame:frame mainImageName:name bgcolor:bgcolor animationColor:nil];
} - (instancetype)initWithFrame:(CGRect)frame mainImageName:(NSString*)name bgcolor:(UIColor *)bgcolor animationColor:animationColor {
if(self = [super initWithFrame:frame])
{
NSAssert(name != nil, @"mainImageName can't be nil !"); self.backgroundColor = [UIColor clearColor];
self.windowLevel = UIWindowLevelAlert + 1; //如果想在 alert 之上,则改成 + 2
self.rootViewController = [UIViewController new];
[self makeKeyAndVisible]; _bgcolor = bgcolor;
_frameWidth = frame.size.width;
_animationColor = animationColor; _mainImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_mainImageButton setFrame:(CGRect){0, 0,frame.size.width, frame.size.height}];
[_mainImageButton setImage:[UIImage imageNamed:name] forState:UIControlStateNormal];
// _mainImageButton.layer.cornerRadius = frame.size.width*0.5;
// _mainImageButton.layer.masksToBounds= YES;
_mainImageButton.alpha = normalAlpha;
[_mainImageButton addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];
if (_animationColor) {
[_mainImageButton addTarget:self action:@selector(mainBtnTouchDown) forControlEvents:UIControlEventTouchDown];
} [self addSubview:_mainImageButton]; // [self doBorderWidth:myBorderWidth color:nil cornerRadius:_frameWidth/2]; _pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(locationChange:)];
_pan.delaysTouchesBegan = NO;
[self addGestureRecognizer:_pan];
_tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(click:)];
[self addGestureRecognizer:_tap]; [self performSelector:@selector(justbegin) withObject:nil afterDelay:statusChangeDuration]; }
return self;
} - (void)dissmissWindow{
self.hidden = YES;
}
- (void)showWindow{
self.hidden = NO;
} - (void)justbegin{ [self performSelector:@selector(changeStatus) withObject:nil afterDelay:statusChangeDuration]; CGPoint panPoint = CGPointMake(kScreenWidth-80, kScreenHeight-150); [self changBoundsabovePanPoint:panPoint];
} - (void)changBoundsabovePanPoint:(CGPoint)panPoint{ if(panPoint.x <= kScreenWidth/2)
{
if(panPoint.y <= 40+kk_HEIGHT/2 && panPoint.x >= 20+kk_WIDTH/2)
{
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(panPoint.x, kk_HEIGHT/2);
}];
}
else if(panPoint.y >= kScreenHeight-kk_HEIGHT/2-40 && panPoint.x >= 20+kk_WIDTH/2)
{
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(panPoint.x, kScreenHeight-kk_HEIGHT/2);
}];
}
else if (panPoint.x < kk_WIDTH/2+20 && panPoint.y > kScreenHeight-kk_HEIGHT/2)
{
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(kk_WIDTH/2, kScreenHeight-kk_HEIGHT/2);
}];
}
else
{
CGFloat pointy = panPoint.y < kk_HEIGHT/2 ? kk_HEIGHT/2 :panPoint.y;
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(kk_WIDTH/2, pointy);
}];
}
}
else if(panPoint.x > kScreenWidth/2)
{
if(panPoint.y <= 40+kk_HEIGHT/2 && panPoint.x < kScreenWidth-kk_WIDTH/2-20 )
{
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(panPoint.x, kk_HEIGHT/2);
}];
}
else if(panPoint.y >= kScreenHeight-40-kk_HEIGHT/2 && panPoint.x < kScreenWidth-kk_WIDTH/2-20)
{
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(panPoint.x, kScreenHeight-kk_HEIGHT/2);
}];
}
else if (panPoint.x > kScreenWidth-kk_WIDTH/2-20 && panPoint.y < kk_HEIGHT/2)
{
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(kScreenWidth-kk_WIDTH/2, kk_HEIGHT/2);
}];
}
else
{
CGFloat pointy = panPoint.y > kScreenHeight-kk_HEIGHT/2 ? kScreenHeight-kk_HEIGHT/2 :panPoint.y;
[UIView animateWithDuration:animateDuration animations:^{
self.center = CGPointMake(kScreenWidth-kk_WIDTH/2, pointy);
}];
}
} }
//改变位置
- (void)locationChange:(UIPanGestureRecognizer*)p
{
CGPoint panPoint = [p locationInView:[[UIApplication sharedApplication] keyWindow]];
if(p.state == UIGestureRecognizerStateBegan)
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeStatus) object:nil];
_mainImageButton.alpha = normalAlpha;
}
if(p.state == UIGestureRecognizerStateChanged)
{
self.center = CGPointMake(panPoint.x, panPoint.y);
}
else if(p.state == UIGestureRecognizerStateEnded)
{
[self stopAnimation];
[self performSelector:@selector(changeStatus) withObject:nil afterDelay:statusChangeDuration]; [self changBoundsabovePanPoint:panPoint]; }
}
//点击事件
- (void)click:(UITapGestureRecognizer*)p
{
[self stopAnimation]; _mainImageButton.alpha = normalAlpha; //拉出悬浮窗
if (self.center.x == 0) {
self.center = CGPointMake(kk_WIDTH/2, self.center.y);
}else if (self.center.x == kScreenWidth) {
self.center = CGPointMake(kScreenWidth - kk_WIDTH/2, self.center.y);
}else if (self.center.y == 0) {
self.center = CGPointMake(self.center.x, kk_HEIGHT/2);
}else if (self.center.y == kScreenHeight) {
self.center = CGPointMake(self.center.x, kScreenHeight - kk_HEIGHT/2);
} if (self.callService) { self.callService();
} } - (void)changeStatus
{
[UIView animateWithDuration:1.0 animations:^{
_mainImageButton.alpha = sleepAlpha;
}];
[UIView animateWithDuration:0.5 animations:^{
CGFloat x = self.center.x < 20+kk_WIDTH/2 ? 0 : self.center.x > kScreenWidth - 20 -kk_WIDTH/2 ? kScreenWidth : self.center.x;
CGFloat y = self.center.y < 40 + kk_HEIGHT/2 ? 0 : self.center.y > kScreenHeight - 40 - kk_HEIGHT/2 ? kScreenHeight : self.center.y; //禁止停留在4个角
if((x == 0 && y ==0) || (x == kScreenWidth && y == 0) || (x == 0 && y == kScreenHeight) || (x == kScreenWidth && y == kScreenHeight)){
y = self.center.y;
}
self.center = CGPointMake(x, y);
}];
} //- (void)doBorderWidth:(CGFloat)width color:(UIColor *)color cornerRadius:(CGFloat)cornerRadius{
// // self.layer.masksToBounds = YES;
// self.layer.cornerRadius = cornerRadius;
// self.layer.borderWidth = width;
// if (!color) {
// self.layer.borderColor = [UIColor whiteColor].CGColor;
// }else{
// self.layer.borderColor = color.CGColor;
// }
//} #pragma mark ------- animation ------------- - (void)buttonAnimation{ self.layer.masksToBounds = NO; CGFloat scale = 1.0f;
//
CGFloat width = self.mainImageButton.bounds.size.width, height = self.mainImageButton.bounds.size.height;
//
CGFloat biggerEdge = width > height ? width : height, smallerEdge = width > height ? height : width;
CGFloat radius = smallerEdge / 2 > WZFlashInnerCircleInitialRaius ? WZFlashInnerCircleInitialRaius : smallerEdge / 2; scale = biggerEdge / radius + 0.5;
_circleShape = [self createCircleShapeWithPosition:CGPointMake(width/2, height/2)
pathRect:CGRectMake(0, 0, radius * 3, radius * 3)
radius:radius]; // 方形放大效果
// scale = 2.5f;
// _circleShape = [self createCircleShapeWithPosition:CGPointMake(width/2, height/2)
// pathRect:CGRectMake(-CGRectGetMidX(self.mainImageButton.bounds), -CGRectGetMidY(self.mainImageButton.bounds), width, height)
// radius:self.mainImageButton.layer.cornerRadius]; [self.mainImageButton.layer addSublayer:_circleShape]; CAAnimationGroup *groupAnimation = [self createFlashAnimationWithScale:scale duration:1.0f]; [_circleShape addAnimation:groupAnimation forKey:nil];
} - (void)stopAnimation{ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(buttonAnimation) object:nil]; if (_circleShape) {
[_circleShape removeFromSuperlayer];
}
} - (CAShapeLayer *)createCircleShapeWithPosition:(CGPoint)position pathRect:(CGRect)rect radius:(CGFloat)radius
{
CAShapeLayer *circleShape = [CAShapeLayer layer];
circleShape.path = [self createCirclePathWithRadius:rect radius:radius];
circleShape.position = position; // 雷达覆盖区域
circleShape.bounds = CGRectMake(0, 0, radius * 3, radius * 3);
circleShape.fillColor = _animationColor.CGColor; // 圆圈放大效果
// circleShape.fillColor = [UIColor clearColor].CGColor;
// circleShape.strokeColor = [UIColor purpleColor].CGColor; circleShape.opacity = 0;
circleShape.lineWidth = 1; return circleShape;
} - (CAAnimationGroup *)createFlashAnimationWithScale:(CGFloat)scale duration:(CGFloat)duration
{
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(scale, scale, 1)]; CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
alphaAnimation.fromValue = @1;
alphaAnimation.toValue = @0; _animationGroup = [CAAnimationGroup animation];
_animationGroup.animations = @[scaleAnimation, alphaAnimation];
_animationGroup.duration = duration;
_animationGroup.repeatCount = INFINITY;
_animationGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; return _animationGroup;
} - (CGPathRef)createCirclePathWithRadius:(CGRect)frame radius:(CGFloat)radius
{
return [UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:radius].CGPath;
} - (void)mainBtnTouchDown{ [self performSelector:@selector(buttonAnimation) withObject:nil afterDelay:0.5];
} /*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/ @end

最后附上小demo

iOS悬浮窗口(无论界面跳转、View始终在视图上显示,可移动)的更多相关文章

  1. ios的两种界面跳转方式

    1.在界面的跳转有两种方法,一种方法是先删除原来的界面,然后在插入新的界面,使用这种方式无法实现界面跳转时的动画效果. if(self.rootViewController.view.supervie ...

  2. ios在tableview里面加subview后在ip4和ip5上显示不一样的问题

    文章链接:http://quke.org/post/ios-tableview-addsubview-height.html (转载时请注明本文出处及文章链接) 我在在tableview里面加subv ...

  3. iOS利用代理实现界面跳转

    引入代理类头文件和要跳转到的界面头文件 -(void)aaa { //可以插入动画 LYXViewControllor * view = [LYXViewControllor new]; LYXDel ...

  4. Android 悬浮窗口

    Android 悬浮窗口 一.创建悬浮窗口步骤    1.实现一个ViewGroup类,作为悬浮窗口的界面类,以便在里面重写onInterceptTouchEvent和onTouchEvent方法,实 ...

  5. Atitit. 悬浮窗口的实现 java swing c# .net c++ js html 的实现

    Atitit. 悬浮窗口的实现 java swing c# .net c++ js html 的实现 1. 建立悬浮窗口引用代码 1 1.1. 定义悬浮窗口,设置this主窗口引用,是为了在悬浮窗口中 ...

  6. Android之悬浮窗口实现(WindowManager)

    工作中遇到一些项目需要把窗体显示在最上层,像来电弹窗显示电话号码等信息.拦截短信信息显示给用户或者游戏中实现声音的调节,我们想这些数据放在最上层,activity就满足不了我们的需求了,有些开发者使用 ...

  7. ios中的界面跳转方式

    ios中,两种界面跳转方式 1.NavgationController本身可以作为普通ViewController的容器,它有装Controller的栈,所以可以push和pop它们,实现你所说的跳转 ...

  8. iOS之访问权限以及跳转到系统界面

    iOS开发中有时候有这样的需求:当用户设置不允许访问照片.麦克风和相机等系统权限的时候,这时需要直接跳转到系统的隐私界面进行设置. 判断是否开启权限 前面已经说过,我们需要在用户不允许访问的时候跳转, ...

  9. iOS界面跳转的一些优化方案

    原文地址: http://blog.startry.com/2016/02/14/Think-Of-UIViewController-Switch/ iOS界面跳转的一些优化方案 App应用程序开发, ...

随机推荐

  1. SqlServer误删数据恢复

    误删数据,操作步骤: 第一步: 找到误删的数据库之前备份文件. 第二步: 1,修改数据库备份模式为:大容量日志 2,修改访问限制为:SINGLE_USER(单用户模式) 第三步: 执行sql一条一条执 ...

  2. win10优化开机进程

    一种比杀毒软件都优化还给力的方法,还在为开机几百个程序启动发愁嘛.一般电脑在重装系统之后的开机进程在50左右,而随着安装程序的增多开机进程将越来越多.下面介绍怎么优化win10进程的方法 之后重启电脑 ...

  3. docker 私有仓库简易搭建

    概要 本地私有仓库 局域网私有仓库 总结 概要 docker hub 使用非常方便,而且上面有大量的镜像可以使用. 但是,每次都远程下载镜像速度非常慢,如果能在本地做一个 docker 的仓库,多人协 ...

  4. May 30. 2018 Week 22nd Wednesday

    Never forget to say "Thanks." 永远不要忘记说谢谢. Don't take anything we get for granted, and never ...

  5. 微信H5开发,页面被缓存,不更新

    原文:https://blog.csdn.net/qq_27471405/article/details/79295348  这里只是备份 前言:每一次请求,我们都知道浏览器会做一定处理,其中就包括对 ...

  6. Java面试知识点之线程篇(一)

    前言:在Java面试中,一定会遇到线程相关问题,因此笔者在这里总结Java中有关线程方面知识点,多数从网上得来(文中会贴出主要参考链接),有些也是笔者在面试中所遇到的问题,如有错误,请不吝指正.主要参 ...

  7. SharePoint 2010 在同意匿名訪问的站点中隐藏登陆链接

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012025054/article/details/37565787 SharePoint 2010 ...

  8. go 调用windows dll 的三种方法

    参考:https://blog.csdn.net/qq_39584315/article/details/81287669 大部分代码参考:https://studygolang.com/articl ...

  9. UVA1609-Foul Play(构造+递归)

    Problem UVA1609-Foul Play Accept: 101  Submit: 514Time Limit: 3000 mSec Problem Description Input Fo ...

  10. UVA215-Spreadsheet Calculator(模拟+拓扑排序)

    Problem UVA215-Spreadsheet Calculator Accept:401  Submit:2013 Time Limit: 3000 mSec Problem Descript ...