iOS全局的悬浮窗
2020-12-03 本文已影响0人
今年27
1.这个悬浮窗的持有者应该是比较稳定的,一般写在AppDelegate里面,KDEAISellFloatWindow继承于UIWindow, 关于UIWindow,为了保证始终悬浮在最上层,可以给windowLevel 设置成UIWindowLevelAlert
UIWindowLevelAlert > UIWindowLevelStatusBar>UIWindowLevelNormal
等级高的会优先显示覆盖掉等级低的
- (void)initFloatWindow{
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
self.floatWindow = [[KDEAISellFloatWindow alloc] initWithFrame:CGRectMake(screenWidth - KDEAISellFloatWindowWidth, screenHeight - KDEAISellFloatWindowHeight - KDEAISellFloatWindowBottomSpace , KDEAISellFloatWindowWidth, KDEAISellFloatWindowHeight)];
self.floatWindow.hidden = YES;
self.floatWindow.floatType = KDEAISellFloatWindowTypeSupportPortraitPan;
__weak typeof(self) weak_self = self;
self.floatWindow.clickAction = ^{
weak_self.floatWindow.hidden = YES;
[[weak_self getCurrentViewController] presentViewController:[KDEAISellThreeInterviewsManager shareManager].interviewsVC animated:YES completion:^{
}];
};
}
2.继承UIWindow
#import <UIKit/UIKit.h>
#import "KDEAISellFloatWindowViewModel.h"
#define KDEAISellFloatWindowWidth 74.0f
#define KDEAISellFloatWindowHeight 78.0f
#define KDEAISellFloatWindowBottomSpace 70.0f
#define KDEAISellFloatWindowRightSpace 0
typedef NS_OPTIONS(NSUInteger, KDEAISellFloatWindowType) {
KDEAISellFloatWindowTypeNormal = 1 << 0,//仅悬浮
KDEAISellFloatWindowTypeSupportPortraitPan = 1 << 1,//支持竖屏滑动
KDEAISellFloatWindowTypeSupportLandscapePan = 1 << 2,//支持横屏滑动
KDEAISellFloatWindowTypeSupportPortraitSpringToBounds = 1 << 3, //支持竖屏弹至边框
KDEAISellFloatWindowTypeSupportLandscapeSpringToBounds = 1 << 4, //支持横屏弹至边框
};
@interface KDEAISellFloatWindow : UIWindow
@property(nonatomic,assign)BOOL isShowMenu;
@property (nonatomic, strong) KDEAISellFloatWindowViewModel *viewModel;
@property (nonatomic, assign) KDEAISellFloatWindowType floatType;
@property (nonatomic, copy) void(^clickAction)(void);
//-(id)initWithFrame:(CGRect)frame imageName:(NSString*)name;
@end
#import "KDEAISellFloatWindow.h"
#import "KDEAISellGroundPageFile.h"
#define WIDTH self.frame.size.width
#define HEIGHT self.frame.size.height
UIButton *button[4];//button数组
@interface KDEAISellFloatWindow()
@property (nonatomic, strong) UIImageView *iconImageView;
@property (nonatomic, assign) UIInterfaceOrientation currentOrientation;
@end
@implementation KDEAISellFloatWindow
-(KDEAISellFloatWindowViewModel *)viewModel{
if (!_viewModel) {
_viewModel = [[KDEAISellFloatWindowViewModel alloc] init];
}
return _viewModel;
}
-(instancetype)initWithFrame:(CGRect)frame
{
if(self = [super initWithFrame:frame])
{
self.backgroundColor = [UIColor clearColor];
self.windowLevel = UIWindowLevelAlert;
[self makeKeyAndVisible];
_iconImageView = [[UIImageView alloc]initWithFrame:(CGRect){0, 0,frame.size.width, frame.size.height}];
_iconImageView.image = [UIImage aisell_getBundleImageWithImageName:self.viewModel.imageName];
// _imageView.alpha = 0.3;
[self addSubview:_iconImageView];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(locationChange:)];
pan.delaysTouchesBegan = YES;
[self addGestureRecognizer:pan];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(click:)];
[self addGestureRecognizer:tap];
// [self initbutton];
self.isShowMenu=false;
[self setRootViewController:[UIViewController new]];
self.currentOrientation = UIInterfaceOrientationPortrait;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
}
return self;
}
#define KDEAISellDegreesToRadians(degrees) (degrees * M_PI / 180)
- (void)statusBarOrientationChange:(NSNotification*)notification{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
[self setTransform:[self transformForOrientation:orientation]];
self.currentOrientation = orientation;
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
self.frame = CGRectMake(KDEAISellFloatWindowHeight+KDEAISellFloatWindowBottomSpace, screenWidth - KDEAISellFloatWindowWidth , KDEAISellFloatWindowWidth, KDEAISellFloatWindowHeight);
}else{
self.frame = CGRectMake(screenWidth - KDEAISellFloatWindowWidth, screenHeight - KDEAISellFloatWindowHeight - KDEAISellFloatWindowBottomSpace , KDEAISellFloatWindowWidth, KDEAISellFloatWindowHeight);
}
}
- (CGAffineTransform)transformForOrientation:(UIInterfaceOrientation)orientation {
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
return CGAffineTransformMakeRotation(-KDEAISellDegreesToRadians(90));
case UIInterfaceOrientationLandscapeRight:
return CGAffineTransformMakeRotation(KDEAISellDegreesToRadians(90));
case UIInterfaceOrientationPortraitUpsideDown:
return CGAffineTransformMakeRotation(KDEAISellDegreesToRadians(180));
case UIInterfaceOrientationPortrait:
default:
return CGAffineTransformMakeRotation(KDEAISellDegreesToRadians(0));
}
}
//初始化button
-(void)initbutton
{
for (int i=0; i<4; i++) {
button[i]=[UIButton buttonWithType:UIButtonTypeCustom];
[button[i] setBackgroundImage:[UIImage imageNamed:@"1.png"] forState:UIControlStateNormal];
[button[i] setTag:(100+i)];
[button[i] addTarget:self action:@selector(buttonfunc:) forControlEvents:UIControlEventTouchUpInside];
[button[i] setHidden:true];
[self addSubview:button[i]];
}
}
-(void)buttonfunc:(UIButton*)sender
{
switch (sender.tag) {
case 100:
{
NSLog(@"100");
}
break;
case 101:
{
NSLog(@"101");
}
break;
case 102:
{
NSLog(@"102");
}
break;
case 103:
{
NSLog(@"103");
}
break;
default:
break;
}
}
-(void)buttonchange
{
// if (self.isShowMenu) {
// [self setFrame:CGRectMake(touchpoint.x, touchpoint.y, 40, 40)];
// for (int i=0; i<4; i++) {
// [button[i] setHidden:true];
// NSLog(@"%f,%f",self.center.x, self.center.y);
//
// }
// self.isShowMenu=false;
// }
// else
// {
// for (int i=0; i<4; i++) {
// [button[i] setHidden:false];
// if (touchpoint.x<kScreenWidth/2) {
// [self setFrame:CGRectMake(touchpoint.x, touchpoint.y, 250, 40)];
// [button[i] setFrame:CGRectMake((i+1)*50, 0, 40, 40)];
// }
// else
// {
// [self setFrame:CGRectMake(touchpoint.x-210, touchpoint.y, 250, 40)];
// [button[i] setFrame:CGRectMake((i+1)*50, 0, 40, 40)];
// }
// }
// self.isShowMenu=true;
// }
}
//改变位置
//横屏之后的坐标系变为左下角坐标系,其中x轴向上,y轴向右,在这样的坐标系中计算即可
-(void)locationChange:(UIPanGestureRecognizer*)pan
{
if (self.floatType == KDEAISellFloatWindowTypeNormal) {//如果是普通的则不可滑动
return;
}
if (self.currentOrientation == UIInterfaceOrientationLandscapeRight || self.currentOrientation == UIInterfaceOrientationLandscapeLeft) {//如果是横屏
if (self.floatType & KDEAISellFloatWindowTypeSupportLandscapeSpringToBounds) {//横屏弹到边框效果
[self springToBoundsOnLandscape:pan];
} else if (self.floatType & KDEAISellFloatWindowTypeSupportLandscapePan){//横屏的拖动
[self landscapePan:pan];
}
} else{ //如果是竖屏
if (self.floatType & KDEAISellFloatWindowTypeSupportPortraitPan) {//竖屏拖动
[self portraitPan:pan];
}else if (self.floatType & KDEAISellFloatWindowTypeSupportPortraitSpringToBounds) {//竖屏弹到边框
[self springToBoundsOnPortrait:pan];
}
}
// touchpoint=self.frame.origin;
}
- (void)portraitPan:(UIPanGestureRecognizer*)panGesture{
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
[[UIApplication sharedApplication] keyWindow];
CGPoint panPoint = [panGesture locationInView:[[UIApplication sharedApplication] windows][0]];
if(panGesture.state == UIGestureRecognizerStateBegan)
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeColor) object:nil];
_iconImageView.alpha = 0.8;
} else if (panGesture.state == UIGestureRecognizerStateChanged)
{
if (self.floatType & KDEAISellFloatWindowTypeSupportPortraitPan) {
if (panPoint.x < WIDTH/2) {
panPoint.x = WIDTH/2;
} else if (panPoint.x > screenWidth - WIDTH/2) {
panPoint.x = screenWidth - WIDTH/2;
}
if (panPoint.y < LXMSTATUS_BAR_HEIGHT + HEIGHT/2) {
panPoint.y = LXMSTATUS_BAR_HEIGHT + HEIGHT/2;
} else if (panPoint.y > screenHeight - HEIGHT/2) {
panPoint.y = screenHeight - HEIGHT/2;
}
}
self.center = CGPointMake(panPoint.x, panPoint.y);
} else if(panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled)
{
_iconImageView.alpha = 1.0;
}
}
- (void)landscapePan:(UIPanGestureRecognizer*)panGesture{
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
[[UIApplication sharedApplication] keyWindow];
CGPoint panPoint = [panGesture locationInView:[[UIApplication sharedApplication] windows][0]];
panPoint = CGPointMake(screenHeight - panPoint.y, panPoint.x);
if(panGesture.state == UIGestureRecognizerStateBegan)
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeColor) object:nil];
_iconImageView.alpha = 0.8;
} else if (panGesture.state == UIGestureRecognizerStateChanged)
{
if (self.floatType & KDEAISellFloatWindowTypeSupportPortraitPan) {
if (panPoint.x < HEIGHT/2) {
panPoint.x = HEIGHT/2;
} else if (panPoint.x > screenHeight - HEIGHT/2) {
panPoint.x = screenHeight - HEIGHT/2;
}
if (panPoint.y < LXMSTATUS_BAR_HEIGHT + WIDTH/2) {
panPoint.y = LXMSTATUS_BAR_HEIGHT + WIDTH/2 + LXMSTATUS_BAR_HEIGHT;
} else if (panPoint.y > screenWidth - WIDTH/2) {
panPoint.y = screenWidth - WIDTH/2;
}
}
self.center = CGPointMake(panPoint.x, panPoint.y);
} else if(panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled)
{
_iconImageView.alpha = 1.0;
}
}
- (void)springToBoundsOnPortrait:(UIPanGestureRecognizer*)panGesture{
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
[[UIApplication sharedApplication] keyWindow];
CGPoint panPoint = [panGesture locationInView:[[UIApplication sharedApplication] windows][0]];
if(panGesture.state == UIGestureRecognizerStateBegan)
{
// [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeColor) object:nil];
_iconImageView.alpha = 0.8;
} else if (panGesture.state == UIGestureRecognizerStateChanged)
{
self.center = CGPointMake(panPoint.x, panPoint.y);
} else if(panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled)
{
_iconImageView.alpha = 1.0;
NSLog(@"ss");
if(panPoint.x <= screenWidth/2)
{
if(panPoint.y >= screenHeight-HEIGHT/2-40 )//左下边界判断
{
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(WIDTH/2, screenHeight-HEIGHT/2);
}];
} else if (panPoint.y < (HEIGHT/2 + LXMSTATUS_BAR_HEIGHT)) {
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(WIDTH/2, HEIGHT/2 + LXMSTATUS_BAR_HEIGHT);
}];
} else{
// CGFloat pointy = panPoint.y < (HEIGHT/2 + LXMSTATUS_BAR_HEIGHT)? (HEIGHT/2 + LXMSTATUS_BAR_HEIGHT) :panPoint.y;//左上边界与正常拖动
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(WIDTH/2, panPoint.y);
}];
}
}
else if(panPoint.x > screenWidth/2)
{
if(panPoint.y <= (HEIGHT/2 + LXMSTATUS_BAR_HEIGHT))//向右越过上边界
{
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(screenWidth-WIDTH/2, HEIGHT/2 + LXMSTATUS_BAR_HEIGHT);
}];
}
else if (panPoint.y > screenHeight-HEIGHT/2) {//右下边界
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(screenWidth-WIDTH/2, screenHeight-HEIGHT/2);
}];
}else{//正常拖动
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(screenWidth-WIDTH/2, panPoint.y);
}];
}
}
}
}
- (void)springToBoundsOnLandscape:(UIPanGestureRecognizer*)panGesture{
CGFloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
[[UIApplication sharedApplication] keyWindow];
CGPoint panPoint = [panGesture locationInView:[[UIApplication sharedApplication] windows][0]];
panPoint = CGPointMake(screenHeight - panPoint.y, panPoint.x);
NSLog(@"screenWidth:%f, panPoint:%@", screenWidth, NSStringFromCGPoint(panPoint));
if(panGesture.state == UIGestureRecognizerStateBegan)
{
_iconImageView.alpha = 0.8;
} else if (panGesture.state == UIGestureRecognizerStateChanged)
{
self.center = CGPointMake(panPoint.x, panPoint.y);
} else if(panGesture.state == UIGestureRecognizerStateEnded || panGesture.state == UIGestureRecognizerStateCancelled)
{
_iconImageView.alpha = 1.0;
if(panPoint.y <= screenWidth/2)
{
if (panPoint.x <= HEIGHT/2 + LXMSTATUS_BAR_HEIGHT) {
[UIView animateWithDuration:0.2 animations:^{//左下角
self.center = CGPointMake(WIDTH/2, HEIGHT/2 + LXMSTATUS_BAR_HEIGHT);
}];
}else if (panPoint.x >= screenHeight - HEIGHT/2){//左上角
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(screenHeight - HEIGHT/2, HEIGHT/2 + LXMSTATUS_BAR_HEIGHT);
}];
}else{
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(panPoint.x, HEIGHT/2 + LXMSTATUS_BAR_HEIGHT);
}];
}
}
else if(panPoint.y > screenWidth/2)
{
if (panPoint.x <= HEIGHT/2) {//右下角
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(HEIGHT/2, screenWidth - WIDTH/2);
}];
}else if (panPoint.x >= screenHeight - HEIGHT/2){//右上角
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(screenHeight - HEIGHT/2, screenWidth - WIDTH/2);
}];
}else{
[UIView animateWithDuration:0.2 animations:^{
self.center = CGPointMake(panPoint.x , screenWidth - WIDTH/2);
}];
}
}
}
}
//点击事件
-(void)click:(UITapGestureRecognizer*)t
{
_iconImageView.alpha = 0.8;
self.userInteractionEnabled = NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.iconImageView.alpha = 1.0;
self.userInteractionEnabled = YES;
});
if (self.clickAction) {
self.clickAction();
}
// [self buttonchange];
// [self performSelector:@selector(changeColor) withObject:nil afterDelay:4.0];
}
-(void)changeColor
{
[UIView animateWithDuration:2.0 animations:^{
self.iconImageView.alpha = 0.3;
}];
}