iOS 悬浮球效果实现,悬浮按钮,拖拽,贴边,隐藏,显示,旋转屏幕适配
生活随笔
收集整理的這篇文章主要介紹了
iOS 悬浮球效果实现,悬浮按钮,拖拽,贴边,隐藏,显示,旋转屏幕适配
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1.懸浮球與設(shè)備劉海的安全距離
無論是橫屏還是豎屏,懸浮球距離有劉海的一邊會留出安全距離
設(shè)備方向的上下兩邊,也有安全距離
2.貼邊吸附方向和距離
懸浮球只能貼設(shè)備方向的左右兩邊,需要貼上下兩邊自行調(diào)整
距離邊緣的數(shù)值自行調(diào)整
3.切換橫豎屏,懸浮球自適應(yīng)
懸浮球位置切換橫豎屏后,等比例轉(zhuǎn)換的。
4.隱藏和顯示
拖到屏幕中間ImageView范圍內(nèi)可以隱藏懸浮窗,在范圍內(nèi)會由藍色變紅色,可自定義圖片或者大小
使用說明:
懸浮球點擊事件代理方法
- (void)suspendViewButtonClick:(UIButton*)sender;懸浮球在ImageView范圍內(nèi)提示是否隱藏懸浮窗
- (void)showHideAlertView;顯示懸浮窗
- (void)showSuspendView;隱藏懸浮窗
- (void)dismissSuspendView;Demo下載點擊此處
?視頻效果展示
#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN @protocol SuspendViewDelegate <NSObject> - (void)suspendViewButtonClick:(UIButton*)sender; - (void)showHideAlertView; @end @interface SuspendView : UIView {CGPoint lastPoint;/**存儲懸浮球最后的移動完位置*/BOOL isChangePosition;/**懸浮球是否改變了位置*/CGFloat changeHig;//按鈕高度位置比例CGFloat changeWid;//按鈕寬度位置比例} @property (nonatomic, retain) UIButton *btn;/**<#name#>*/ @property (nonatomic, strong) NSTimer *_Nullable timer; @property (nonatomic, retain) UIImageView *imageView; @property (nonatomic, assign) UIInterfaceOrientation orientation; @property (nonatomic, weak) id<SuspendViewDelegate> delegate; - (void)showSuspendView; - (void)dismissSuspendView; @endNS_ASSUME_NONNULL_END #import "SuspendView.h"#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height #define ViewSize 50 #define KHeightFit(w) (((w) / 667.0) * SCREEN_HEIGHT)#define LRString [NSString stringWithFormat:@"%s", __FILE__].lastPathComponent #define DLog(...) {\ NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];\ [dateFormatter setDateFormat:@"YYYY-MM-dd hh:mm:ss"];\ NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];\ printf("%s %s 第%d行:%s\n\n",[dateString UTF8String],[LRString UTF8String] ,__LINE__, [[NSString stringWithFormat:__VA_ARGS__] UTF8String]);}@implementation SuspendView- (instancetype)init{self = [super init];if (self) {self.backgroundColor = UIColor.redColor;self.layer.masksToBounds = YES;self.layer.cornerRadius = ViewSize/2;self.alpha = 0.5;//獲取設(shè)備方向self.orientation = [[UIApplication sharedApplication] statusBarOrientation];if (self.orientation == UIInterfaceOrientationLandscapeRight){//橫向home鍵在右側(cè),設(shè)備左轉(zhuǎn),劉海在左邊self.frame = CGRectMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20, KHeightFit(80) + ViewSize/2, ViewSize, ViewSize);}else{self.frame = CGRectMake(SCREEN_WIDTH - ViewSize/2, KHeightFit(80) + ViewSize/2, ViewSize, ViewSize);}self.btn = [UIButton buttonWithType:UIButtonTypeCustom];self.btn.frame = CGRectMake(5, 5, 40, 40);self.btn.backgroundColor = UIColor.greenColor;self.btn.layer.cornerRadius = 20;[self.btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];[self addSubview:self.btn];//獲取按鈕與屏幕初始寬高比例[self changeCoordinateScale];//是否改變了懸浮窗初始位置isChangePosition = NO;//添加手勢UIPanGestureRecognizer *panRcognize=[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];[panRcognize setMinimumNumberOfTouches:1];[panRcognize setEnabled:YES];[panRcognize delaysTouchesEnded];[panRcognize cancelsTouchesInView];[self addGestureRecognizer:panRcognize];//監(jiān)聽屏幕旋轉(zhuǎn)[[NSNotificationCenter defaultCenter] addObserver:selfselector:@selector(didChangeStatusBarOrientation)name:UIApplicationDidChangeStatusBarOrientationNotificationobject:nil];}return self; }- (void)didChangeStatusBarOrientation {self.orientation = [UIApplication sharedApplication].statusBarOrientation;self.imageView.frame = CGRectMake((SCREEN_WIDTH - 50)/2, (SCREEN_HEIGHT - 50)/2, 50, 50); // DLog(@"===%zd=====%zd",[[UIDevice currentDevice] orientation],[UIApplication sharedApplication].statusBarOrientation);//請注意,UIInterfaceOrientationAndScapeLeft等于UIDeviceOrientation AndScapeRight(反之亦然)。//這是因為向左旋轉(zhuǎn)設(shè)備需要向右旋轉(zhuǎn)內(nèi)容。/**UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown,UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft*//**UIDeviceOrientationUnknown,UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottomUIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the topUIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the rightUIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the leftUIDeviceOrientationFaceUp, // Device oriented flat, face upUIDeviceOrientationFaceDown // Device oriented flat, face down*/switch ([UIDevice currentDevice].orientation){case UIDeviceOrientationPortraitUpsideDown:// DLog(@"設(shè)備倒垂直,home在上")[self locationChange:@"Down"];break;case UIDeviceOrientationLandscapeLeft:{// DLog(@"設(shè)備橫屏,左轉(zhuǎn),home在右")[self locationChange:@"left"];}break;case UIDeviceOrientationLandscapeRight:{ // DLog(@"設(shè)備橫屏,右轉(zhuǎn),home在左")[self locationChange:@"right"];}break;case UIDeviceOrientationPortrait:{ // DLog(@"設(shè)備垂直,home在下");[self locationChange:@"Portrait"];}break;default:break;} } //根據(jù)屏幕寬高改變按鈕位置比例 - (void)locationChange:(NSString *)message{ // NSLog(@"changeHig == %f,changeWid == %f",changeHig,changeWid);if (SCREEN_HEIGHT > SCREEN_WIDTH) {//屏幕方向上if ([message isEqualToString:@"Portrait"]) {NSLog(@"安全區(qū)在上邊");self.center = CGPointMake(changeWid * SCREEN_WIDTH, changeHig * SCREEN_HEIGHT);}else{//下NSLog(@"安全區(qū)在下邊");self.center = CGPointMake(changeWid * SCREEN_WIDTH, changeHig * SCREEN_HEIGHT - [self vg_safeDistanceTop]);}}else{if ([message isEqualToString:@"left"]) {//左NSLog(@"安全區(qū)在左邊");self.center = CGPointMake(changeWid * SCREEN_WIDTH + [self vg_safeDistanceTop] + ViewSize, changeHig * SCREEN_HEIGHT);}else{//右NSLog(@"安全區(qū)在右邊");self.center = CGPointMake(changeWid * SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize, changeHig * SCREEN_HEIGHT);}} // NSLog(@"lastPoint == %@, self.center == %@",NSStringFromCGPoint(lastPoint),NSStringFromCGPoint(self.center));[self changeCoordinateScale];} //旋轉(zhuǎn)屏幕后修改懸浮窗相對于屏幕的寬高比例以及坐標(biāo)位置 - (void)changeCoordinateScale{changeHig = self.center.y/SCREEN_HEIGHT;changeWid = self.center.x/SCREEN_WIDTH;//判斷設(shè)備旋轉(zhuǎn)方向if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側(cè),設(shè)備左轉(zhuǎn),劉海在左邊,劉海在左邊//判斷懸浮窗坐標(biāo)x在屏幕的左邊還是右邊if (self.center.x > SCREEN_WIDTH/2) {//大于中心x,在右邊//修改懸浮窗的坐標(biāo)在最右邊self.center = CGPointMake(SCREEN_WIDTH, self.center.y);}else{//修改懸浮窗的坐標(biāo)在最左邊self.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20, self.center.y);}}else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側(cè),設(shè)備右轉(zhuǎn),劉海在右邊if (self.center.x > SCREEN_WIDTH/2) {//大于中心x,在右邊//修改懸浮窗的坐標(biāo)在最右邊,留出頂部安全距離self.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20, self.center.y);}else{//修改懸浮窗的坐標(biāo)在最左邊self.center = CGPointMake(0, self.center.y);}}else{//大于中心x,在右邊if (self.center.x > SCREEN_WIDTH/2) {self.center = CGPointMake(SCREEN_WIDTH, self.center.y);}else{self.center = CGPointMake(0, self.center.y);}} // NSLog(@"changeHig == %f,changeWid == %f",changeHig,changeWid); // NSLog(@"設(shè)備寬度 == %f, 設(shè)備高度== %f, 按鈕坐標(biāo)==%@",SCREEN_WIDTH,SCREEN_HEIGHT,NSStringFromCGPoint(self.center)); } - (void)showSuspendView{self.hidden = NO;NSLog(@"顯示懸浮窗"); } - (void)dismissSuspendView{self.hidden = YES;NSLog(@"隱藏懸浮窗"); } /// 懸浮窗按鈕點擊放法 /// @param button 點擊之后完全顯示懸浮窗,改變按鈕位置 - (void)btnClick:(UIButton *)button{if (self.delegate && [self.delegate respondsToSelector:@selector(suspendViewButtonClick:)]) {[self.delegate suspendViewButtonClick:button];} // DLog(@"lastPoint == %@",NSStringFromCGPoint(lastPoint));//如果沒有改變過位置,lastPoint初始值(0,0)//判斷是否移動過懸浮窗if (!isChangePosition) {//懸浮窗初始位置在右上角,只有屏幕向右旋轉(zhuǎn),才需要留出iphone劉海的位置,設(shè)備左轉(zhuǎn)劉海在左邊,所以不需要做判斷if (self.orientation == UIInterfaceOrientationLandscapeLeft) {//橫向home鍵在左側(cè),設(shè)備右轉(zhuǎn),劉海在右邊//修改點擊后懸浮窗的位置,留出安全距離[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20 - 20, self.center.y);}];}else{[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - ViewSize, self.center.y);}];}}else{ // 判斷最后的坐標(biāo)是靠左還是靠右if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側(cè),設(shè)備左轉(zhuǎn),劉海在左邊if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - ViewSize, self.center.y);}];}else{//左轉(zhuǎn)劉海在左邊,留出安全距離[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20 + 20, self.center.y);}];}}else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側(cè),設(shè)備右轉(zhuǎn),劉海在右邊if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè),留出劉海安全距離[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20 - 20, self.center.y);}];}else{//左側(cè)顯示[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(ViewSize, self.center.y);}];}}else{if (self.center.x < SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(ViewSize, self.center.y);}];}else{[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - ViewSize, self.center.y);}];}}}self.alpha = 1;//三秒后隱藏懸浮窗,貼邊展示一半self.timer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(timerAction) userInfo:nil repeats:NO]; }- (void)timerAction{//隱藏懸浮球self.alpha = 0.5;//判斷是否移動過懸浮窗if (!isChangePosition) {//懸浮窗初始位置在右上角,只有屏幕向右旋轉(zhuǎn),才需要留出iphone劉海的位置,設(shè)備左轉(zhuǎn)劉海在左邊,所以不需要做判斷if (self.orientation == UIInterfaceOrientationLandscapeLeft) {//橫向home鍵在左側(cè),設(shè)備右轉(zhuǎn),劉海在右邊[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20, self.center.y);}];}else{[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH, self.center.y);}];}}else{if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側(cè),設(shè)備左轉(zhuǎn),劉海在左邊if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH, self.center.y);}];}else{//懸浮窗在屏幕左側(cè),留出劉海安全距離[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20, self.center.y);}];}}else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側(cè),設(shè)備右轉(zhuǎn),劉海在右邊if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)//懸浮窗在屏幕左側(cè),留出劉海安全距離[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20, self.center.y);}];}else{[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(0, self.center.y);}];}}else{if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(SCREEN_WIDTH, self.center.y);}];}else{[UIView animateWithDuration:0.5 animations:^{self.center = CGPointMake(0, self.center.y);}];}}}//銷毀定時器[self.timer invalidate];self.timer = nil; }/// pan手勢 /// @param recognizer recognizer description - (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {//移動狀態(tài)UIGestureRecognizerState recState = recognizer.state;isChangePosition = YES;switch (recState) {case UIGestureRecognizerStateBegan:self.alpha = 1;self.imageView.hidden = NO;break;case UIGestureRecognizerStateChanged://移動中{self.alpha = 1;CGPoint translation = [recognizer translationInView:self];recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x, recognizer.view.center.y + translation.y);CGRect rect = [self convertRect:self.frame toView:self];if (CGRectIntersectsRect(self.imageView.frame, rect)) {//在范圍內(nèi)self.imageView.backgroundColor = UIColor.redColor;}else{self.imageView.backgroundColor = UIColor.blueColor;}}break;case UIGestureRecognizerStateEnded://移動結(jié)束{self.alpha = 0.5;CGPoint stopPoint = CGPointMake(0, SCREEN_HEIGHT / 2);//判斷按鈕貼靠在屏幕的左邊還是右邊if (recognizer.view.center.x < SCREEN_WIDTH / 2) {stopPoint = CGPointMake(ViewSize/2, recognizer.view.center.y);}else{//貼靠在右邊stopPoint = CGPointMake(SCREEN_WIDTH - ViewSize/2,recognizer.view.center.y);}DLog(@"stopPoint == %@",NSStringFromCGPoint(stopPoint));if (stopPoint.y - ViewSize/2 <= 0) {DLog(@"上");//加上電池欄的高度if (stopPoint.x - ViewSize/2 <= SCREEN_WIDTH/2) {stopPoint = CGPointMake(0, stopPoint.y + [self vg_safeDistanceTop] + ViewSize);DLog(@"左上");}else{DLog(@"右上");stopPoint = CGPointMake(SCREEN_WIDTH, stopPoint.y + [self vg_safeDistanceTop] + ViewSize);}}//如果按鈕超出屏幕邊緣if (stopPoint.y + ViewSize + 20 >= SCREEN_HEIGHT) {DLog(@"下");//減去底部狀態(tài)欄的高度if (stopPoint.x - ViewSize/2 <= SCREEN_WIDTH/2) {DLog(@"左下");stopPoint = CGPointMake(0, stopPoint.y - [self vg_safeDistanceBottom] - ViewSize/2);}else{DLog(@"右下");stopPoint = CGPointMake(SCREEN_WIDTH, stopPoint.y - [self vg_safeDistanceBottom] - ViewSize/2);} // DLog(@"超出屏幕下方");}if (stopPoint.x - ViewSize/2 <= 0) {DLog(@"左"); // stopPoint = CGPointMake(ViewSize/2, stopPoint.y);//縮進去一半stopPoint = CGPointMake(0, stopPoint.y);}if (stopPoint.x + ViewSize/2 >= SCREEN_WIDTH) {DLog(@"右"); // stopPoint = CGPointMake(SCREEN_WIDTH - ViewSize/2, stopPoint.y);stopPoint = CGPointMake(SCREEN_WIDTH, stopPoint.y);}//保存最后的位置lastPoint = stopPoint;//隱藏懸浮球CGRect rect = [self convertRect:self.frame toView:self];if (CGRectIntersectsRect(self.imageView.frame, rect)) {//在范圍內(nèi)DLog(@"懸浮窗在中心imageview內(nèi),提示是否隱藏懸浮窗"); // [self showAlertView];[self.delegate showHideAlertView];} // NSLog(@"self.orientation == %ld",(long)self.orientation);if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側(cè),設(shè)備左轉(zhuǎn),劉海在左邊if (stopPoint.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)[UIView animateWithDuration:0.5 animations:^{recognizer.view.center = CGPointMake(SCREEN_WIDTH, stopPoint.y);}];}else{//懸浮窗在屏幕左側(cè),留出劉海安全距離[UIView animateWithDuration:0.5 animations:^{recognizer.view.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20, stopPoint.y);}];}}else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側(cè),設(shè)備右轉(zhuǎn),劉海在右邊if (stopPoint.x > SCREEN_WIDTH/2) {//懸浮窗在屏幕右側(cè)//懸浮窗在屏幕左側(cè),留出劉海安全距離[UIView animateWithDuration:0.5 animations:^{recognizer.view.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20, stopPoint.y);}];}else{[UIView animateWithDuration:0.5 animations:^{recognizer.view.center = CGPointMake(0, stopPoint.y);}];}}else{[UIView animateWithDuration:0.5 animations:^{recognizer.view.center = stopPoint;}];}[self changeCoordinateScale];self.imageView.hidden = YES;}break;default:break;}[recognizer setTranslation:CGPointMake(0, 0) inView:self]; }//獲取頭部安全區(qū)高度 - (CGFloat)vg_safeDistanceTop {if (@available(iOS 13.0, *)) {NSSet *set = [UIApplication sharedApplication].connectedScenes;UIWindowScene *windowScene = [set anyObject];UIWindow *window = windowScene.windows.firstObject;return window.safeAreaInsets.top;} else if (@available(iOS 11.0, *)) {UIWindow *window = [UIApplication sharedApplication].windows.firstObject;return window.safeAreaInsets.top;}return 0; }//獲取設(shè)備底部安全區(qū)高度 - (CGFloat)vg_safeDistanceBottom {if (@available(iOS 13.0, *)) {NSSet *set = [UIApplication sharedApplication].connectedScenes;UIWindowScene *windowScene = [set anyObject];UIWindow *window = windowScene.windows.firstObject;return window.safeAreaInsets.bottom;} else if (@available(iOS 11.0, *)) {UIWindow *window = [UIApplication sharedApplication].windows.firstObject;return window.safeAreaInsets.bottom;}return 0; }- (UIImageView *)imageView{if (!_imageView) {_imageView = [[UIImageView alloc]initWithFrame:CGRectMake((SCREEN_WIDTH - 50)/2, (SCREEN_HEIGHT - 50)/2, 50, 50)];_imageView.backgroundColor = UIColor.blueColor;_imageView.hidden = YES;[[UIApplication sharedApplication].keyWindow addSubview:_imageView];}return _imageView; }@end????????
總結(jié)
以上是生活随笔為你收集整理的iOS 悬浮球效果实现,悬浮按钮,拖拽,贴边,隐藏,显示,旋转屏幕适配的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【认证须知】什么是HCIE?为什么要考?
- 下一篇: Springboot毕设项目老年人社区服