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. CentOS7 vi编辑命令【转】

    CentOS 7 vi编辑命令 用vi打开一个yum文件 vi /usr/bin/yum 按 i 键后  进入insert模式,进入insert模式后才能进行修改 修改完成后 按esc键进入comma ...

  2. 详解PHP中的过滤器(Filter)

    PHP 过滤器用于验证和过滤来自非安全来源的数据,比如用户的输入. 什么是 PHP 过滤器? PHP 过滤器用于验证和过滤来自非安全来源的数据. 验证和过滤用户输入或自定义数据是任何 Web 应用程序 ...

  3. 第10章 嵌入式Linux 的调试技术

    10.1  打印内核调试信息:printk printk位函数运行在内核空间, printf函数运行在用户空间.也就是说,像Linux 驱动这样的Linux内核程序只能使用printk函数输出调试信息 ...

  4. SAP 维护视图创建与修改

    维护视图创建与修改 维护视图创建 T-CODE:SE54 维护ABAP数据字典 维护已生产的对象 注意:当维护视图修改后,需要删除已生成的对象,重新创建已生成的对象,否则无法显示,这个小窍门我花了半天 ...

  5. Loj #3057. 「HNOI2019」校园旅行

    Loj #3057. 「HNOI2019」校园旅行 某学校的每个建筑都有一个独特的编号.一天你在校园里无聊,决定在校园内随意地漫步. 你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你 ...

  6. Python 浅拷贝copy()与深拷贝copy.deepcopy()

    首先我在这介绍两个新的小知识,要在下面用到.一个是函数 id() ,另一个是运算符 is.id() 函数就是返回对象的内存地址:is 是比较两个变量的对象引用是否指向同一个对象,在这里请不要和 == ...

  7. tomcat 安装配置部署到nginx+tomcat+https

    目录 1 Tomcat简介 2.下载并安装Tomcat服务 2.2 部署java环境 2.3 安装Tomcat 2.4 Tomcat目录介绍 (关注点 bin conf logs webapps) 2 ...

  8. 【vue】在移动端使用better-scroll 实现滚动效果

    安装依赖:(c)npm install better-scroll --save 引入: import BScroll from 'better-scroll' 格式: var obj = new B ...

  9. Node.js之mysql增删改查

    1.安装库 npm install mysql 2.编写db.js(用作公共模块) //连接MySQL数据库 var mysql = require("mysql"); var p ...

  10. 输出1-100 , 奇数偶数分别添加标识(for循环语句嵌套if-else语句)

    package com.summer.cn; /** * @author Summer * 输出1-100 , 奇数偶数分别添加标识 */ public class Test041518 { publ ...