主頁 > 移動端開發 > iOS 懸浮球效果實作,懸浮按鈕,拖拽,貼邊,隱藏,顯示,旋轉螢屏適配

iOS 懸浮球效果實作,懸浮按鈕,拖拽,貼邊,隱藏,顯示,旋轉螢屏適配

2022-08-25 08:45:03 移動端開發

1.懸浮球與設備劉海的安全距離
無論是橫屏還是豎屏,懸浮球距離有劉海的一邊會留出安全距離
設備方向的上下兩邊,也有安全距離

2.貼邊吸附方向和距離
懸浮球只能貼設備方向的左右兩邊,需要貼上下兩邊自行調整
距離邊緣的數值自行調整

3.切換橫豎屏,懸浮球自適應
懸浮球位置切換橫豎屏后,等比例轉換的,

4.隱藏和顯示
拖到螢屏中間ImageView范圍內可以隱藏懸浮窗,在范圍內會由藍色變紅色,可自定義圖片或者大小

使用說明:

懸浮球點擊事件代理方法
- (void)suspendViewButtonClick:(UIButton*)sender;
懸浮球在ImageView范圍內提示是否隱藏懸浮窗
- (void)showHideAlertView;
顯示懸浮窗
- (void)showSuspendView;
隱藏懸浮窗
- (void)dismissSuspendView;

 

demo下載地址:

https://github.com/longypjiangxi/XLUIDragButton

簡書地址:

https://www.jianshu.com/p/30aeb1d506d3

 

 

#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;
@end
 
NS_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;
        
        //獲取設備方向
        self.orientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (self.orientation == UIInterfaceOrientationLandscapeRight){//橫向home鍵在右側,設備左轉,劉海在左邊
            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];
       
        //監聽螢屏旋轉
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(didChangeStatusBarOrientation)
                                                     name:UIApplicationDidChangeStatusBarOrientationNotification
                                                   object: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(反之亦然),
    //這是因為向左旋轉設備需要向右旋轉內容,
    /**
     UIInterfaceOrientationUnknown            = UIDeviceOrientationUnknown,
     UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
     UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
     UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
     UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft
     */
    
    /**
     UIDeviceOrientationUnknown,
     UIDeviceOrientationPortrait,            // Device oriented vertically, home button on the bottom
     UIDeviceOrientationPortraitUpsideDown,  // Device oriented vertically, home button on the top
     UIDeviceOrientationLandscapeLeft,       // Device oriented horizontally, home button on the right
     UIDeviceOrientationLandscapeRight,      // Device oriented horizontally, home button on the left
     UIDeviceOrientationFaceUp,              // Device oriented flat, face up
     UIDeviceOrientationFaceDown             // Device oriented flat, face down
     */
    switch ([UIDevice currentDevice].orientation)
    {
        case UIDeviceOrientationPortraitUpsideDown:
           // DLog(@"設備倒垂直,home在上")
            [self locationChange:@"Down"];
            break;
        case UIDeviceOrientationLandscapeLeft:{
          //  DLog(@"設備橫屏,左轉,home在右")
            [self locationChange:@"left"];
        }
            break;
        case UIDeviceOrientationLandscapeRight:{
//            DLog(@"設備橫屏,右轉,home在左")
            [self locationChange:@"right"];
        }
            break;
        case UIDeviceOrientationPortrait:{
//            DLog(@"設備垂直,home在下");
            [self locationChange:@"Portrait"];
        }
            break;
        default:
            break;
    }
}
//根據螢屏寬高改變按鈕位置比例
- (void)locationChange:(NSString *)message{
//    NSLog(@"changeHig == %f,changeWid == %f",changeHig,changeWid);
    if (SCREEN_HEIGHT > SCREEN_WIDTH) {
        //螢屏方向上
        if ([message isEqualToString:@"Portrait"]) {
            NSLog(@"安全區在上邊");
            self.center = CGPointMake(changeWid * SCREEN_WIDTH, changeHig * SCREEN_HEIGHT);
        }else{//下
            NSLog(@"安全區在下邊");
            self.center = CGPointMake(changeWid * SCREEN_WIDTH, changeHig * SCREEN_HEIGHT - [self vg_safeDistanceTop]);
        }
    }else{
        if ([message isEqualToString:@"left"]) {//左
            NSLog(@"安全區在左邊");
            self.center = CGPointMake(changeWid * SCREEN_WIDTH + [self vg_safeDistanceTop] + ViewSize, changeHig * SCREEN_HEIGHT);
        }else{//右
            NSLog(@"安全區在右邊");
            self.center = CGPointMake(changeWid * SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize, changeHig * SCREEN_HEIGHT);
        }
    }
//    NSLog(@"lastPoint == %@, self.center == %@",NSStringFromCGPoint(lastPoint),NSStringFromCGPoint(self.center));
 
    [self changeCoordinateScale];
    
}
//旋轉螢屏后修改懸浮窗相對于螢屏的寬高比例以及坐標位置
- (void)changeCoordinateScale{
    changeHig = self.center.y/SCREEN_HEIGHT;
    changeWid = self.center.x/SCREEN_WIDTH;
    //判斷設備旋轉方向
    if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側,設備左轉,劉海在左邊,劉海在左邊
        //判斷懸浮窗坐標x在螢屏的左邊還是右邊
        if (self.center.x > SCREEN_WIDTH/2) {//大于中心x,在右邊
            //修改懸浮窗的坐標在最右邊
            self.center = CGPointMake(SCREEN_WIDTH, self.center.y);
        }else{
            //修改懸浮窗的坐標在最左邊
            self.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20, self.center.y);
        }
    }else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側,設備右轉,劉海在右邊
        if (self.center.x > SCREEN_WIDTH/2) {//大于中心x,在右邊
            //修改懸浮窗的坐標在最右邊,留出頂部安全距離
            self.center = CGPointMake(SCREEN_WIDTH - [self vg_safeDistanceTop] - ViewSize - 20, self.center.y);
        }else{
            //修改懸浮窗的坐標在最左邊
            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(@"設備寬度 == %f, 設備高度== %f, 按鈕坐標==%@",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) {
        //懸浮窗初始位置在右上角,只有螢屏向右旋轉,才需要留出iphone劉海的位置,設備左轉劉海在左邊,所以不需要做判斷
        if (self.orientation == UIInterfaceOrientationLandscapeLeft) {//橫向home鍵在左側,設備右轉,劉海在右邊
            //修改點擊后懸浮窗的位置,留出安全距離
            [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{
//        判斷最后的坐標是靠左還是靠右
        if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側,設備左轉,劉海在左邊
            if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在螢屏右側
                [UIView animateWithDuration:0.5 animations:^{
                    self.center = CGPointMake(SCREEN_WIDTH - ViewSize, self.center.y);
                }];
            }else{
                //左轉劉海在左邊,留出安全距離
                [UIView animateWithDuration:0.5 animations:^{
                    self.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20 + 20, self.center.y);
                }];
            }
        }else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側,設備右轉,劉海在右邊
            if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在螢屏右側,留出劉海安全距離
                [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(ViewSize, self.center.y);
                }];
            }
        }else{
            if (self.center.x < SCREEN_WIDTH/2) {//懸浮窗在螢屏右側
                [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) {
        //懸浮窗初始位置在右上角,只有螢屏向右旋轉,才需要留出iphone劉海的位置,設備左轉劉海在左邊,所以不需要做判斷
        if (self.orientation == UIInterfaceOrientationLandscapeLeft) {//橫向home鍵在左側,設備右轉,劉海在右邊
            [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鍵在右側,設備左轉,劉海在左邊
            if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在螢屏右側
                [UIView animateWithDuration:0.5 animations:^{
                    self.center = CGPointMake(SCREEN_WIDTH, self.center.y);
                }];
            }else{
                //懸浮窗在螢屏左側,留出劉海安全距離
                [UIView animateWithDuration:0.5 animations:^{
                    self.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20, self.center.y);
                }];
            }
        }else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側,設備右轉,劉海在右邊
            if (self.center.x > SCREEN_WIDTH/2) {//懸浮窗在螢屏右側
                //懸浮窗在螢屏左側,留出劉海安全距離
                [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) {//懸浮窗在螢屏右側
                [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
{
    //移動狀態
    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)) {//在范圍內
                self.imageView.backgroundColor = UIColor.redColor;
            }else{
                self.imageView.backgroundColor = UIColor.blueColor;
            }
        }
            break;
        case UIGestureRecognizerStateEnded://移動結束
        {
            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(@"下");
                //減去底部狀態欄的高度
                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)) {//在范圍內
                DLog(@"懸浮窗在中心imageview內,提示是否隱藏懸浮窗");
//                [self showAlertView];
                [self.delegate showHideAlertView];
            }
//            NSLog(@"self.orientation == %ld",(long)self.orientation);
            if (self.orientation == UIInterfaceOrientationLandscapeRight) {//橫向home鍵在右側,設備左轉,劉海在左邊
                if (stopPoint.x > SCREEN_WIDTH/2) {//懸浮窗在螢屏右側
                    [UIView animateWithDuration:0.5 animations:^{
                        recognizer.view.center = CGPointMake(SCREEN_WIDTH, stopPoint.y);
                    }];
                }else{
                    //懸浮窗在螢屏左側,留出劉海安全距離
                    [UIView animateWithDuration:0.5 animations:^{
                        recognizer.view.center = CGPointMake([self vg_safeDistanceTop] + ViewSize + 20, stopPoint.y);
                    }];
                }
            }else if(self.orientation == UIInterfaceOrientationLandscapeLeft){//橫向home鍵在左側,設備右轉,劉海在右邊
                if (stopPoint.x > SCREEN_WIDTH/2) {//懸浮窗在螢屏右側
                    //懸浮窗在螢屏左側,留出劉海安全距離
                    [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];
}
 
//獲取頭部安全區高度
- (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;
}
 
//獲取設備底部安全區高度
- (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

 

 

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/502688.html

標籤:iOS

上一篇:【Android端】軟體脫殼簡單通用思路

下一篇:iOS 懸浮球效果實作,懸浮按鈕,拖拽,貼邊,隱藏,顯示,旋轉螢屏適配

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more