自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS:狀態(tài)欄提示控件的實(shí)現(xiàn)原理

移動(dòng)開發(fā) iOS
現(xiàn)在很多流行的軟件都加入了狀態(tài)欄提示的功能,比如手機(jī)qq,微信等,今天我們就一起來(lái)看看狀態(tài)欄提示控件的原理與實(shí)現(xiàn)。

現(xiàn)在很多流行的軟件都加入了狀態(tài)欄提示的功能,比如手機(jī)qq,微信等,今天我們就一起來(lái)看看狀態(tài)欄提示控件的原理與實(shí)現(xiàn)。

[[113965]]

一、狀態(tài)欄提示的實(shí)現(xiàn)原理

不知道大家看到狀態(tài)欄提示控件,***感覺它是怎么實(shí)現(xiàn)的呢?

我們知道即使平時(shí)寫的view是充滿全屏的,也始終不會(huì)顯示到 statusBar的上層的。也就是說(shuō)statusBar應(yīng)該是一個(gè)特殊的view,始終位于程序的topLevel,這就容易聯(lián)想到UIKit中一個(gè)特 殊的view-----UIWindow。UIWindow有一個(gè)windowLevel的屬性剛好能實(shí)現(xiàn)一直保持在上層的功能,于是方向就比較明確了。 我較早寫的兩篇博客UIWindowLevel詳解以及關(guān)于UIWindow的一點(diǎn)兒思考中對(duì)windowLevel有過(guò)詳細(xì)的介紹和驗(yàn)證。

確定了使用UIWindow來(lái)實(shí)現(xiàn)狀態(tài)欄提示控件,好像問(wèn)題就全部解決了,真的是這樣嗎?

如果你的程序僅僅支持portrait方向的話,那么最主要的功能就結(jié)束了,剩下的事情就是文本框布局和簡(jiǎn)單動(dòng)畫的實(shí)現(xiàn)了。但如果你的控件要支持其他三個(gè)方向的話,就還需要處理window的旋轉(zhuǎn)。

iOS中完整的旋轉(zhuǎn)流程如下: 設(shè)備檢測(cè)到方向旋轉(zhuǎn)->UIApplication收到旋轉(zhuǎn)事件->通知window設(shè)備發(fā)生了旋轉(zhuǎn)->window通知它的 rootViewController進(jìn)行旋轉(zhuǎn)->viewController會(huì)調(diào)整自身view的transform。觀察發(fā)現(xiàn)自始至終 window本身的位置和方向是沒有發(fā)生變化的,也就是說(shuō)如果自己創(chuàng)建一個(gè)window用于展示提示,我們需要自己處理該window的旋轉(zhuǎn),根據(jù)不同的 方向調(diào)整window的位置和transform。

綜上要實(shí)現(xiàn)狀態(tài)欄提示控件我們需要做以下兩件事:

1、創(chuàng)建一個(gè)UIWindow,指定它的frame為statusBar的frame,并且設(shè)置該window的windowLevel級(jí)別略高于statusBar的windowLevel。

2、注冊(cè)系統(tǒng)的旋轉(zhuǎn)通知,監(jiān)測(cè)設(shè)備方向變化,根據(jù)當(dāng)前設(shè)備的方向做出相應(yīng)的調(diào)整。

整個(gè)過(guò)程中主要用到了UIWindow和transfrom的知識(shí),這兩部分知識(shí)我前面寫的博客都有涉及,難點(diǎn)主要集中在自己旋轉(zhuǎn)window這一塊。

二、Window的旋轉(zhuǎn)

UIKit通過(guò)UIWindow和UIViewContoller為我們提供了一套旋轉(zhuǎn)支持的框架,在方向變化以后viewController中view的坐標(biāo)系統(tǒng)就已經(jīng)被轉(zhuǎn)到正確的方向了,我們只需要簡(jiǎn)單的重新布局就可以了。我們現(xiàn)在是直接通過(guò)UIWindow實(shí)現(xiàn)狀態(tài)欄提示控件,因此需要自己完成對(duì)該window進(jìn)行旋轉(zhuǎn)的操作。

我們知道對(duì)當(dāng)前view設(shè)置的transform是針對(duì)它的父view的,window本身就是一種特殊的view。你可能會(huì)疑問(wèn)window不就是***層的view,它還有父view嗎?

答案是YES,不信的話你可以打印一下 window的superView看看。window默認(rèn)方向是portrait方向,向下y坐標(biāo)增加,向右x坐標(biāo)增加。因此Portrait方向我們只 需要向普通的view那樣布局就可以了,其它幾個(gè)方向我們就需要用到transform和設(shè)置位置來(lái)搞定了。

下面我們看一看從Portrait方向轉(zhuǎn)到landscapeRight方向的圖示:

上圖中從左到右展示了如何將初始位置(Portrait方向),旋轉(zhuǎn)到目標(biāo)位置(landscapeRight方向)的過(guò)程。

1、原始window位置位于屏幕最上方(與statusBar的位置一樣)。

2、首先我們對(duì)這個(gè)window做順時(shí)針90°旋轉(zhuǎn),變化后到達(dá)綠色繪制位置。

3、接著我們?cè)傩薷膚indow的center到屏幕最右邊并且上下居中,達(dá)到紅色虛線所示的位置。

4、***對(duì)該window的bound進(jìn)行設(shè)置,使該window充滿屏幕最右邊的區(qū)域。注意這個(gè)時(shí)候由于window的transform已經(jīng)轉(zhuǎn)了90°,所以設(shè)置時(shí)width代表著高度,height代表這寬度。

下面是完整的處理旋轉(zhuǎn)到四個(gè)方向的代碼:

  1. - (void)updateOrientation:(NSNotification*)noti 
  2.     UIInterfaceOrientation newOrientation = [[noti.userInfo valueForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue]; 
  3.     NSLog(@"new orientation: %d", newOrientation); 
  4.      
  5.     switch (newOrientation) { 
  6.         case UIInterfaceOrientationPortrait: 
  7.         { 
  8.             self.transform = CGAffineTransformIdentity; 
  9.             self.frame = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  10.              
  11.             break
  12.         } 
  13.         case UIInterfaceOrientationPortraitUpsideDown: 
  14.         { 
  15.             // 先轉(zhuǎn)矩陣,坐標(biāo)系統(tǒng)落在屏幕有右下角,朝上是y,朝左是x 
  16.             self.transform = CGAffineTransformMakeRotation(M_PI); 
  17.             self.center = CGPointMake(SCREEN_WIDTH / 2, SCREEN_HEIGHT - HEIGHT / 2); 
  18.             self.bounds = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  19.              
  20.             break
  21.         } 
  22.         case UIInterfaceOrientationLandscapeLeft: 
  23.         { 
  24.             self.transform = CGAffineTransformMakeRotation(-M_PI_2); 
  25.             // 這個(gè)時(shí)候坐標(biāo)軸已經(jīng)轉(zhuǎn)了90°,調(diào)整x相當(dāng)于調(diào)節(jié)豎向調(diào)節(jié),y相當(dāng)于橫向調(diào)節(jié) 
  26.             self.center = CGPointMake(HEIGHT / 2, [UIScreen mainScreen].bounds.size.height / 2); 
  27.             self.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, HEIGHT); 
  28.              
  29.             break
  30.         } 
  31.         case UIInterfaceOrientationLandscapeRight: 
  32.         { 
  33.             // 先設(shè)置transform,在設(shè)置位置和大小 
  34.             self.transform = CGAffineTransformMakeRotation(M_PI_2); 
  35.             self.center = CGPointMake(SCREEN_WIDTH - HEIGHT / 2, SCREEN_HEIGHT / 2); 
  36.             self.bounds = CGRectMake(0, 0, SCREEN_HEIGHT, HEIGHT); 
  37.              
  38.             break
  39.         } 
  40.         default
  41.             break
  42.     } 

三、狀態(tài)欄提示控件源碼

講了那么多,說(shuō)好的控件呢?

下面是完整的控件代碼:

View Code SvStatusBarTipsWindow.h

  1. - (void)updateOrientation:(NSNotification*)noti 
  2.     UIInterfaceOrientation newOrientation = [[noti.userInfo valueForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue]; 
  3.     NSLog(@"new orientation: %d", newOrientation); 
  4.      
  5.     switch (newOrientation) { 
  6.         case UIInterfaceOrientationPortrait: 
  7.         { 
  8.             self.transform = CGAffineTransformIdentity; 
  9.             self.frame = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  10.              
  11.             break
  12.         } 
  13.         case UIInterfaceOrientationPortraitUpsideDown: 
  14.         { 
  15.             // 先轉(zhuǎn)矩陣,坐標(biāo)系統(tǒng)落在屏幕有右下角,朝上是y,朝左是x 
  16.             self.transform = CGAffineTransformMakeRotation(M_PI); 
  17.             self.center = CGPointMake(SCREEN_WIDTH / 2, SCREEN_HEIGHT - HEIGHT / 2); 
  18.             self.bounds = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  19.              
  20.             break
  21.         } 
  22.         case UIInterfaceOrientationLandscapeLeft: 
  23.         { 
  24.             self.transform = CGAffineTransformMakeRotation(-M_PI_2); 
  25.             // 這個(gè)時(shí)候坐標(biāo)軸已經(jīng)轉(zhuǎn)了90°,調(diào)整x相當(dāng)于調(diào)節(jié)豎向調(diào)節(jié),y相當(dāng)于橫向調(diào)節(jié) 
  26.             self.center = CGPointMake(HEIGHT / 2, [UIScreen mainScreen].bounds.size.height / 2); 
  27.             self.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, HEIGHT); 
  28.              
  29.             break
  30.         } 
  31.         case UIInterfaceOrientationLandscapeRight: 
  32.         { 
  33.             // 先設(shè)置transform,在設(shè)置位置和大小 
  34.             self.transform = CGAffineTransformMakeRotation(M_PI_2); 
  35.             self.center = CGPointMake(SCREEN_WIDTH - HEIGHT / 2, SCREEN_HEIGHT / 2); 
  36.             self.bounds = CGRectMake(0, 0, SCREEN_HEIGHT, HEIGHT); 
  37.              
  38.             break
  39.         } 
  40.         default
  41.             break
  42.     } 
  43.  
  44. 復(fù)制代碼 
  45.  
  46.    
  47.  
  48. 三、狀態(tài)欄提示控件源碼 
  49.  
  50.   
  51.  
  52. 講了那么多,說(shuō)好的控件呢? 
  53.  
  54.   下面是完整的控件代碼: 
  55. 復(fù)制代碼 
  56.  
  57. // 
  58. //  SvStatusBarTipsWindow.h 
  59. //  SvStatusBarTips 
  60. // 
  61. //  Created by  maple on 4/21/13. 
  62. //  Copyright (c) 2013 maple. All rights reserved. 
  63. // 
  64.  
  65. #import <UIKit/UIKit.h> 
  66.  
  67. @interface SvStatusBarTipsWindow : UIWindow 
  68.  
  69. /* 
  70.  * @brief get the singleton tips window 
  71.  */ 
  72. + (SvStatusBarTipsWindow*)shareTipsWindow; 
  73.  
  74. /* 
  75.  * @brief show tips message on statusBar 
  76.  */ 
  77. - (void)showTips:(NSString*)tips; 
  78.  
  79. /* 
  80.  * @brief show tips message on statusBar 
  81.  */ 
  82. - (void)showTips:(NSString*)tips hideAfterDelay:(NSInteger)seconds; 
  83.  
  84. /* 
  85.  * @brief show tips icon and message on statusBar 
  86.  */ 
  87. - (void)showTipsWithImage:(UIImage*)tipsIcon message:(NSString*)message; 
  88.  
  89. /* 
  90.  * @brief show tips icon and message on statusBar 
  91.  */ 
  92. - (void)showTipsWithImage:(UIImage*)tipsIcon message:(NSString*)message hideAfterDelay:(NSInteger)seconds; 
  93.  
  94.  
  95. /* 
  96.  * @brief hide tips window 
  97.  */ 
  98. - (void)hideTips; 
  99.  
  100. @end 

SvStatusBarTipsWindow.m

  1. // 
  2. //  SvStatusBarTipsWindow.m 
  3. //  SvStatusBarTips 
  4. // 
  5. //  Created by  maple on 4/21/13. 
  6. //  Copyright (c) 2013 maple. All rights reserved. 
  7. // 
  8.  
  9. #import "SvStatusBarTipsWindow.h" 
  10.  
  11. #define SCREEN_WIDTH  ([UIScreen mainScreen].bounds.size.width) 
  12. #define SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height) 
  13.  
  14. #define HEIGHT   20 
  15.  
  16. #define ICON_WIDTH 20 
  17.  
  18. #define TIPMESSAGE_RIGHT_MARGIN 20 
  19. #define ICON_RIGHT_MARGIN       5 
  20.  
  21.  
  22. @interface SvStatusBarTipsWindow () { 
  23.     UILabel     *_tipsLbl; 
  24.     UIImageView *_tipsIcon; 
  25.      
  26.     NSTimer     *_hideTimer; 
  27.  
  28. @property (nonatomic, copy)     NSString *tipsMessage; 
  29.  
  30. @end 
  31.  
  32.  
  33.  
  34. @implementation SvStatusBarTipsWindow 
  35.  
  36. @synthesize tipsMessage; 
  37.  
  38.  
  39. static SvStatusBarTipsWindow *tipsWindow = nil; 
  40.  
  41. + (SvStatusBarTipsWindow*)shareTipsWindow 
  42.     if (!tipsWindow) { 
  43.         static dispatch_once_t onceToken; 
  44.         dispatch_once(&onceToken, ^{ 
  45.             tipsWindow = [[super allocWithZone:NULL] init]; 
  46.         }); 
  47.     } 
  48.      
  49.     return tipsWindow; 
  50.  
  51. + (id)copyWithZone:(NSZone *)zone 
  52.     return [[self shareTipsWindow] retain]; 
  53.  
  54. + (id)allocWithZone:(NSZone *)zone 
  55.     return [[self shareTipsWindow] retain]; 
  56.  
  57. - (id)retain 
  58.     return tipsWindow; 
  59.  
  60. - (oneway void)release 
  61.     return
  62.  
  63. - (id)autorelease 
  64.     return tipsWindow; 
  65.  
  66. - (id)init 
  67.     CGRect frame = [UIApplication sharedApplication].statusBarFrame; 
  68.     self = [super initWithFrame:frame]; 
  69.     if (self) { 
  70.          
  71.         self.autoresizingMask = UIViewAutoresizingFlexibleWidth; 
  72.         self.windowLevel = UIWindowLevelStatusBar + 10; 
  73.         self.backgroundColor = [UIColor clearColor]; 
  74.          
  75.         _tipsIcon = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, ICON_WIDTH, ICON_WIDTH)]; 
  76.         _tipsIcon.autoresizingMask = UIViewAutoresizingFlexibleHeight; 
  77.         _tipsIcon.backgroundColor = [UIColor redColor]; 
  78.         [self addSubview:_tipsIcon]; 
  79.         [_tipsIcon release]; 
  80.          
  81.         _tipsLbl = [[UILabel alloc] initWithFrame:self.bounds]; 
  82.         #ifdef NSTextAlignmentRight 
  83.             _tipsLbl.textAlignment = NSTextAlignmentLeft; 
  84.             _tipsLbl.lineBreakMode = NSLineBreakByTruncatingTail; 
  85.         #else 
  86.             _tipsLbl.textAlignment = 0; // means UITextAlignmentLeft 
  87.             _tipsLbl.lineBreakMode = 4; //UILineBreakModeTailTruncation; 
  88.         #endif 
  89.         _tipsLbl.textColor = [UIColor whiteColor]; 
  90.         _tipsLbl.font = [UIFont systemFontOfSize:12]; 
  91.         _tipsLbl.backgroundColor = [UIColor blackColor]; 
  92.         _tipsLbl.autoresizingMask = UIViewAutoresizingFlexibleHeight; 
  93.         [self addSubview:_tipsLbl]; 
  94.         [_tipsLbl release]; 
  95.          
  96.         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateOrientation:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; 
  97.     } 
  98.      
  99.     return self; 
  100.  
  101. - (void)dealloc 
  102.     [[NSNotificationCenter defaultCenter] removeObserver:self]; 
  103.  
  104.     [tipsMessage release]; 
  105.      
  106.     [super dealloc]; 
  107.  
  108. #pragma mark - 
  109. #pragma mark Notification Handle 
  110.  
  111. - (void)updateOrientation:(NSNotification*)noti 
  112.     UIInterfaceOrientation newOrientation = [[noti.userInfo valueForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue]; 
  113.     NSLog(@"new orientation: %d", newOrientation); 
  114.      
  115.     switch (newOrientation) { 
  116.         case UIInterfaceOrientationPortrait: 
  117.         { 
  118.             self.transform = CGAffineTransformIdentity; 
  119.             self.frame = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  120.              
  121.             break
  122.         } 
  123.         case UIInterfaceOrientationPortraitUpsideDown: 
  124.         { 
  125.             // 先轉(zhuǎn)矩陣,坐標(biāo)系統(tǒng)落在屏幕有右下角,朝上是y,朝左是x 
  126.             self.transform = CGAffineTransformMakeRotation(M_PI); 
  127.             self.center = CGPointMake(SCREEN_WIDTH / 2, SCREEN_HEIGHT - HEIGHT / 2); 
  128.             self.bounds = CGRectMake(0, 0, SCREEN_WIDTH, HEIGHT); 
  129.              
  130.             break
  131.         } 
  132.         case UIInterfaceOrientationLandscapeLeft: 
  133.         { 
  134.             self.transform = CGAffineTransformMakeRotation(-M_PI_2); 
  135.             // 這個(gè)時(shí)候坐標(biāo)軸已經(jīng)轉(zhuǎn)了90°,調(diào)整x相當(dāng)于調(diào)節(jié)豎向調(diào)節(jié),y相當(dāng)于橫向調(diào)節(jié) 
  136.             self.center = CGPointMake(HEIGHT / 2, [UIScreen mainScreen].bounds.size.height / 2); 
  137.             self.bounds = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.height, HEIGHT); 
  138.              
  139.             break
  140.         } 
  141.         case UIInterfaceOrientationLandscapeRight: 
  142.         { 
  143.             // 先設(shè)置transform,在設(shè)置位置和大小 
  144.             self.transform = CGAffineTransformMakeRotation(M_PI_2); 
  145.             self.center = CGPointMake(SCREEN_WIDTH - HEIGHT / 2, SCREEN_HEIGHT / 2); 
  146.             self.bounds = CGRectMake(0, 0, SCREEN_HEIGHT, HEIGHT); 
  147.              
  148.             break
  149.         } 
  150.         default
  151.             break
  152.     } 
  153.  
  154. #pragma mark - 
  155. #pragma mark Tips Method 
  156.  
  157. /* 
  158.  * @brief show tips message on statusBar 
  159.  */ 
  160. - (void)showTips:(NSString*)tips 
  161.     if (_hideTimer) { 
  162.         [_hideTimer invalidate]; 
  163.         [_hideTimer release]; 
  164.     } 
  165.      
  166.     _tipsIcon.image = nil; 
  167.     _tipsIcon.hidden = YES; 
  168.      
  169.     CGSize size = [tips sizeWithFont:_tipsLbl.font constrainedToSize:CGSizeMake(320, 30)]; 
  170.     size.width += TIPMESSAGE_RIGHT_MARGIN; 
  171.     if (size.width > self.bounds.size.width - ICON_WIDTH) { 
  172.         size.width = self.bounds.size.width - ICON_WIDTH; 
  173.     } 
  174.      
  175.     _tipsLbl.frame = CGRectMake(self.bounds.size.width - size.width, 0, size.width, self.bounds.size.height); 
  176.     _tipsLbl.text = tips; 
  177.      
  178.     [self makeKeyAndVisible]; 
  179.  
  180. - (void)showTips:(NSString*)tips hideAfterDelay:(NSInteger)seconds 
  181.     [self showTips:tips]; 
  182.      
  183.     _hideTimer = [NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(hideTips) userInfo:nil repeats:NO]; 
  184.  
  185. /* 
  186.  * @brief show tips icon and message on statusBar 
  187.  */ 
  188. - (void)showTipsWithImage:(UIImage*)tipsIconImage message:(NSString*)message 
  189.     if (_hideTimer) { 
  190.         [_hideTimer invalidate]; 
  191.         [_hideTimer release]; 
  192.     } 
  193.      
  194.     CGSize size = [message sizeWithFont:_tipsLbl.font constrainedToSize:self.bounds.size]; 
  195.     size.width += TIPMESSAGE_RIGHT_MARGIN; 
  196.     if (size.width > self.bounds.size.width - ICON_WIDTH) { 
  197.         size.width = self.bounds.size.width - ICON_WIDTH; 
  198.     } 
  199.      
  200.     _tipsLbl.frame = CGRectMake(self.bounds.size.width - size.width, 0, size.width, self.bounds.size.height); 
  201.     _tipsLbl.text = message; 
  202.      
  203.     _tipsIcon.center = CGPointMake(self.bounds.size.width - _tipsLbl.bounds.size.width - ICON_WIDTH / 2 - ICON_RIGHT_MARGIN, self.bounds.size.height / 2); 
  204.     _tipsIcon.image = tipsIconImage; 
  205.     _tipsIcon.hidden = NO; 
  206.      
  207.     [self makeKeyAndVisible]; 
  208.  
  209. - (void)showTipsWithImage:(UIImage*)tipsIconImage message:(NSString*)message hideAfterDelay:(NSInteger)seconds 
  210.     [self showTipsWithImage:tipsIconImage message:message]; 
  211.      
  212.     _hideTimer = [NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(hideTips) userInfo:nil repeats:NO]; 
  213.  
  214. /* 
  215.  * @brief hide tips window 
  216.  */ 
  217. - (void)hideTips 
  218.     self.hidden = YES; 
  219.  
  220. @end 

該狀態(tài)欄提示控件實(shí)現(xiàn)了添加提示圖標(biāo)和提示文字,以及自動(dòng)隱藏等功能。顯示和隱藏動(dòng)畫實(shí) 現(xiàn)起來(lái)比較簡(jiǎn)單,控件中就沒有實(shí)現(xiàn),大家可以根據(jù)需要隨意發(fā)揮。該控件使用單例模式,接口非常簡(jiǎn)單,使用起來(lái)很方便。上面代碼相信大家都能看得懂,這里就不展開講了,有什么問(wèn)題歡迎討論。

責(zé)任編輯:閆佳明 來(lái)源: cnblogs
相關(guān)推薦

2015-02-12 14:49:36

CGToast狀態(tài)欄提示Status

2013-07-18 16:09:10

自定義iOS狀態(tài)欄iOS開發(fā)iOS學(xué)習(xí)

2017-02-17 11:00:57

狀態(tài)欄Android

2012-12-24 14:42:48

iOS自定義狀態(tài)欄

2013-11-20 15:08:32

iOS開發(fā)狀態(tài)欄

2021-08-09 20:29:27

Android沉浸式狀態(tài)欄

2023-07-12 23:27:24

Powerline編輯器

2016-11-29 11:20:08

Android

2017-12-05 12:44:57

Android沉浸式狀態(tài)欄APP

2022-11-23 14:47:29

北向開發(fā)鴻蒙

2018-03-09 12:12:25

macOSiOS蘋果

2011-06-16 11:15:04

2021-06-15 15:28:31

谷歌Android開發(fā)

2021-06-15 15:04:38

Android 12安卓通話

2013-04-09 10:03:29

iOS6.0旋轉(zhuǎn)兼容

2009-10-16 14:31:48

VB.NET Noti

2014-07-15 09:26:13

swiftiosMPGNotifica

2022-09-29 10:26:59

iOSScaffoldflutter

2024-10-10 17:46:06

2018-05-16 09:11:19

Android狀態(tài)欄移動(dòng)系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)