iOS開發:自訂狀態列代碼詳解

來源:互聯網
上載者:User

   公司的開發的項目要求在狀態列上邊加入程式下載的進度條,之前寫的程式,由於是根據ipad的朝向來設定自訂的狀態列的frame,以及子視圖的 frame和transform,出現一些不太容易解決的bug。這兩天正好項目不太緊,就好好學習一下這方面的知識,以下是我所總結的一點經驗:

  這裡說明一下,Apple沒有開放的狀態列的API,在ios 的官方文檔沒有提到修改Window Level的方式;

  先看一下Window Level的可用的值包括:

  1: typedef CGFloat UIWindowLevel;

  2: const UIWindowLevel UIWindowLevelNormal; // 0.0

  3: const UIWindowLevel UIWindowLevelAlert; // 2000.0

  4: const UIWindowLevel UIWindowLevelStatusBar; // 1000.0

  預設我們的UIView layer都是在UIWindowLevelNormal上,這也就是為什麼系統彈出來的對話方塊在我們的視圖之上,因為它的Window Level層級更高。

  根據WindowLevel的原理我們也就知道,如果想在系統的狀態列上,添加自訂的狀態列,就需要比UIWindowLevelStatusBar的層級更高,接下來,用代碼說明一下:

  首先,先建一個Single View Application,名字自訂就可以了,

  然後,建立一個類命名為: StatusBarOverlay 繼承自UIWindow類,代碼:

  StatusBarOverlay.h檔案

  1: #import

  2:

  3: @interface StatusBarOverlay : UIWindow{

  4: UIView *contentView;

  5: UILabel *textLabel;

  6: }

  7:

  8: @property (nonatomic, retain) UIView *contentView;

  9:

  10: @property (nonatomic, retain) UILabel *textLabel;

  11:

  12: @end

  StatusBarOverlay.m檔案

  1: //

  2: // StatusBarOverlay.m

  3: // StatusBarDemo

  4: //

  5: // Created by jordy wang on 12-8-7.

  6: // Copyright (c) 2012年 __MyCompanyName__. All rights reserved.

  7: //

  8:

  9: #import "StatusBarOverlay.h"

  10:

  11: #define STATUS_BAR_ORIENTATION [UIApplication sharedApplication].statusBarOrientation

  12: #define ROTATION_ANIMATION_DURATION [UIApplication sharedApplication].statusBarOrientationAnimationDuration

  13:

  14:

  15: @interface StatusBarOverlay()

  16:

  17: - (void)initializeToDefaultState;

  18: - (void)rotateStatusBarWithFrame:(NSValue *)frameValue;

  19: - (void)setSubViewHFrame;

  20: - (void)setSubViewVFrame;

  21: @end

  22:

  23:

  24: @implementation StatusBarOverlay

  25: @synthesize contentView;

  26: @synthesize textLabel;

  27:

  28: //重寫init方法

  29: - (id)init

  30: {

  31: self = [super initWithFrame:CGRectZero];

  32: if (self) {

  33: self.windowLevel = UIWindowLevelStatusBar + 1;

  34: self.frame = [UIApplication sharedApplication].statusBarFrame;

  35: [self setBackgroundColor:[UIColor orangeColor]];

  36: [self setHidden:NO];

  37:

  38: //內容視圖

  39: UIView *_contentView = [[UIView alloc] initWithFrame:self.bounds];

  40: self.contentView = _contentView;

  41: [self.contentView setAutoresizingMask:UIViewAutoresizingFlexibleWidth];

  42: [self.contentView setBackgroundColor:[UIColor cyanColor]];

  43: [self addSubview:self.contentView];

  44: [_contentView release];

  45:

  46:

  47: //添加textLabel

  48: UILabel *_textLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, 0, CGRectGetWidth(self.frame)-60, CGRectGetHeight(self.frame))];

  49: self.textLabel = _textLabel;

  50: [self.textLabel setBackgroundColor:[UIColor blueColor]];

  51: [self.textLabel setFont:[UIFont systemFontOfSize:12]];

  52: [self.textLabel setTextAlignment:UITextAlignmentCenter];

  53: [self.textLabel setTextColor:[UIColor blackColor]];

  54: [self.textLabel setText:@"自訂的狀態列 author by jordy"];

  55: [self.contentView addSubview:self.textLabel];

  56: [_textLabel release];

  57:

  58: //註冊監聽---當螢幕將要轉動時,所出發的事件(用於操作本視圖改變其frame)

  59: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willRotateScreenEvent:)

  name:UIApplicationWillChangeStatusBarFrameNotification object:nil];

  60: //初始化

  61: [self initializeToDefaultState];

  62: }

  63:

  64: return self;

  65: }

  66:

  67:

  68:

  69:

  70: //初始化為預設狀態

  71: - (void)initializeToDefaultState

  72: {

  73: //擷取當前的狀態列位置

  74: CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;

  75: //設定當前視圖的旋轉, 根據當前裝置的朝向

  76: [self rotateStatusBarWithFrame:[NSValue valueWithCGRect:statusBarFrame]];

  77:

  78:

  79:

  80: }

  81:

  82:

  83: //旋轉螢幕

  84: - (void)rotateStatusBarWithFrame:(NSValue *)frameValue

  85: {

  86: CGRect frame = [frameValue CGRectValue];

  87: UIInterfaceOrientation orientation = STATUS_BAR_ORIENTATION;

  88:

  89: if (orientation == UIDeviceOrientationPortrait) {

  90: self.transform = CGAffineTransformIdentity; //螢幕不旋轉

  91: [self setSubViewVFrame];

  92: }else if (orientation == UIDeviceOrientationPortraitUpsideDown) {

  93: self.transform = CGAffineTransformMakeRotation(M_PI); //旋轉螢幕180度

  94: [self setSubViewVFrame];

  95: }else if (orientation == UIDeviceOrientationLandscapeRight) {

  96: self.transform = CGAffineTransformMakeRotation((M_PI * (-90.0f) / 180.0f)); //旋轉螢幕-90度

  97: [self setSubViewHFrame];

  98: }else if (orientation == UIDeviceOrientationLandscapeLeft){

  99: self.transform = CGAffineTransformMakeRotation(M_PI * 90.0f / 180.0f); //旋轉螢幕90度

  100: [self setSubViewHFrame];

  101: }

  102:

  103: self.frame = frame;

  104: [self.contentView setFrame:self.bounds];

  105: }

  106:

  107: //設定橫屏的子視圖的frame

  108: - (void)setSubViewHFrame

  109: {

  110: self.textLabel.frame = CGRectMake(30, 0, 1024-60, 20);

  111: }

  112: //設定豎屏的子視圖的frame

  113: - (void)setSubViewVFrame

  114: {

  115: self.textLabel.frame = CGRectMake(30, 0, 748-60, 20);

  116: }

  117:

  118: #pragma mark -

  119: #pragma mark 響應螢幕即將旋轉時的事件響應

  120: - (void)willRotateScreenEvent:(NSNotification *)notification

  121: {

  122: NSValue *frameValue = [notification.userInfo valueForKey:UIApplicationStatusBarFrameUserInfoKey];

  123: [self rotateStatusBarAnimatedWithFrame:frameValue];

  124: }

  125:

  126: - (void)rotateStatusBarAnimatedWithFrame:(NSValue *)frameValue {

  127: [UIView animateWithDuration:ROTATION_ANIMATION_DURATION animations:^{

  128: self.alpha = 0;

  129: } completion:^(BOOL finished) {

  130: [self rotateStatusBarWithFrame:frameValue];

  131: [UIView animateWithDuration:ROTATION_ANIMATION_DURATION animations:^{

  132: self.alpha = 1;

  133: }];

  134: }];

  135: }

  136:

  137: - (void)dealloc

  138: {

  139: [[NSNotificationCenter defaultCenter] removeObserver:self];

  140: [textLabel release];

  141: textLabel = nil;

  142:

  143: [contentView release];

  144: contentView = nil;

  145:

  146: [super dealloc];

  147: }

  148:

  149: @end

  由於代碼比較簡單,並且我在上述代碼裡有相應的注釋,這裡需要說明一點的是,預設我們繼承自UIWindow的StatusBarOverlay類是hidden狀態,需要在初始化的時候設定它的hidden屬性為NO,

  在旋轉螢幕過程中,自訂的狀態列與UIViewController之間的旋轉是分離的,所以我們需要做一個隱藏的動畫,在旋轉過程前先隱藏自訂的狀態列,旋轉結果後設定顯示狀態。

  如果需要做一種動畫,比方從底部下移顯示一條資訊,隔N秒後又自動收回的動畫,直接設定自訂的視圖的y座標就可以了,預設y座標設定是0。

  最後, 使用它的方式也比較簡單,只需要初始化,代碼:

  StatusBarOverlay *statusBarOverlay = [[StatusBarOverlay alloc] init];

  由於我公司的需求是開機自動下載的功能,所以我在初始化的時候,是放在了AppDelegate中。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.