UIView

UIView(控件)

  • 功能一:界面顯示
    1. 屏幕上顯示的所有UI元素都叫做控件,也有人叫做視圖、組件;按鈕(UIButton)、文本(UILabel)都是控件;
    2. 所有的控件最終都繼承自UIView
    3. UI控件能夠展示的原因是因?yàn)橛幸粋€(gè)layer層

  • 功能二:事件響應(yīng)
    1. UIView繼承自UIResponder。UIResponder繼承自NSObject
    2. 大部分UI開(kāi)頭的類都是繼承自UIResponder,UIResponder具有事件響應(yīng)的能力,這是它們能夠處理事件的原因

  • 注意
    1. UI控件沒(méi)有顯示原因總結(jié):
    1. 沒(méi)有尺寸位置;
    2. 尺寸位置超出視圖;
    3. 沒(méi)有顏色或圖片等顯示要素;
    4. 沒(méi)添加到當(dāng)前窗口或視圖中;
    5. 透明(alpha = 0 || opapue = 1);
    6. 其他控件或窗口擋住了;
    7. 按鈕、segmentedControl等直接設(shè)置屬性,而沒(méi)有分狀態(tài)設(shè)置;
    2. 大部分UI控件通過(guò)alloc.init創(chuàng)建都沒(méi)有尺寸,顏色等;開(kāi)關(guān),菊花控件、toolBar控件、導(dǎo)航條控件、標(biāo)簽條控件等除外

UIKit中可能用得上的UI控件:

UI控件.png

UIkit坐標(biāo)系(UI控件位置、尺寸的基礎(chǔ))

  • UIKit坐標(biāo)系:
    1. 坐標(biāo)系的原點(diǎn)(0,0)在屏幕的左上角
    2. x值向右正向延伸
    3. y值向下正向延伸
UIKit坐標(biāo)系.png

UIView位置、尺寸屬性

  1. frame:控件矩形框在父控件中的位置和尺寸
    1. 以父控件的左上角為坐標(biāo)原點(diǎn)

    view.frame = CGRectMake(0, 0, 100, 100);
    
  2. bonuds:控件矩形框的尺寸及在內(nèi)容層中的位置
    1. 修改bounds的尺寸是以中心點(diǎn)為基準(zhǔn)伸縮的
    2. 自己左上角'內(nèi)容層原點(diǎn)'為坐標(biāo)原點(diǎn),內(nèi)容層是無(wú)限大的
    3. bonuds的x,y修改,實(shí)際上是影響可視化區(qū)域在內(nèi)容層中的位置。
    4. 可視化區(qū)域,參照父控件,位置是不變。所以修改x,y,可以視作是內(nèi)容層反向移動(dòng),有如下規(guī)律:
    1. bounds x > 0,表示需要看右邊內(nèi)容,可視區(qū)域相對(duì)內(nèi)容層原點(diǎn)往右邊走,我們看到的效果,內(nèi)容層原點(diǎn)往左移動(dòng)
    2. bounds y > 0,表示需要看下邊內(nèi)容,可視區(qū)域相對(duì)內(nèi)容層原點(diǎn)往下邊走,我們看到效果,內(nèi)容層原點(diǎn)往上移動(dòng)

    view.bounds = CGRectMake(0, 0, 100, 100);
    
  • center:控件中心點(diǎn)的位置
    1. 以父控件的左上角為坐標(biāo)原點(diǎn)
    2. 注意:在設(shè)置center時(shí),先確定尺寸,否則尺寸不確定,center定位不準(zhǔn),布局控件時(shí)應(yīng):
    1. 先設(shè)置frame后設(shè)置center.
    2. 或通過(guò)設(shè)置bonuds,這樣則不需要區(qū)分先后
    view.center = CGPointMake(100, 100);
    

UIView位置、尺寸屬性的修改

以frame的修改為例(位置,尺寸的修改可參照f(shuō)rame的修改)
  1. 不能直接修改->OC對(duì)象的結(jié)構(gòu)體屬性的成員
    // imageView.frame.size.width = 100; // 不允許
    
  • 方案一:通過(guò)CGRectMake函數(shù)(常用)

    imageView.frame = CGRectMake(100, 100, 200, 200);
    
  • 方案二:利用臨時(shí)結(jié)構(gòu)體變量(常用)

    • 使用場(chǎng)景:針對(duì)結(jié)構(gòu)體中某個(gè)變量的修改
    • C結(jié)構(gòu)體的修改方式
      CGRect tempFrame = imageView.frame;
      tempFrame.origin.x = 100;
      imageView.frame = tempFrame;
      
  • 方案三:使用大括號(hào){}形式(不常用)

    • C結(jié)構(gòu)體的修改方式
      imageView.frame = redView.frame = (CGRect){(100, 100), (100, 100)};;
      
  • 小結(jié):開(kāi)發(fā)中經(jīng)常需要設(shè)置或獲取UIView尺寸屬性,建議增加UIView(Rect)的分類,提高效率,步驟如下;
    1. 創(chuàng)建Rect分類文件(UIView的分類),在.h文件通過(guò)@property聲明x,y,width,height,centerX,centerY,top,bottom,leading,trailing屬性;
    1. 分類不能定義屬性,這里使用@property僅是聲明set、get方法,不會(huì)生成下劃線成員屬性并實(shí)現(xiàn)set、get方法
    2. 實(shí)現(xiàn)set方法;
    3. 實(shí)現(xiàn)get方法;
    4. 建議UIView尺寸屬性名都帶上類前綴,如zq_x、zq_top等,避免以后會(huì)與原生或其他框架沖突

    .h文件
    @interface UIView (Rect)
    
    /** 生成set、get方法聲明 */
    @property(nonatomic,assign) CGFloat zq_x;
    @property(nonatomic,assign) CGFloat zq_y;
    @property(nonatomic,assign) CGFloat zq_width;
    @property(nonatomic,assign) CGFloat zq_height;
    @property(nonatomic,assign) CGFloat zq_centerX;
    @property(nonatomic,assign) CGFloat zq_centerY;
    @property(nonatomic,assign) CGFloat zq_top;
    @property(nonatomic,assign) CGFloat zq_leading;//左
    @property(nonatomic,assign) CGFloat zq_bottom;
    @property(nonatomic,assign) CGFloat zq_trailing;//右
    
    .m文件(僅以代表舉例)
    #pragma mark - x set、get方法實(shí)現(xiàn)
    - (void)setZq_x:(CGFloat)zq_x
    {
        CGRect frame = self.frame;
        frame.origin.x = zq_x;
        self.frame = frame;
    }
    - (CGFloat)zq_x
    {
        return self.frame.origin.x;
    }
    
    #pragma mark - leading set、get方法實(shí)現(xiàn)
    - (void)setZq_leading:(CGFloat)zq_leading
    {
        self.zq_x = zq_leading;
    }
    
    - (CGFloat)zq_leading
    {
        return self.zq_x;
    }
    
    #pragma mark - bottom set、get方法實(shí)現(xiàn)
    - (void)setZq_bottom:(CGFloat)zq_bottom
    {
        self.zq_y = zq_bottom - self.zq_height;
    }
    
    - (CGFloat)zq_bottom
    {
        return self.zq_y + self.zq_height;
    }
    

UIView的transform(形變)屬性

  • 控件的形變包括平移、縮放、旋轉(zhuǎn)等屬性,類型是CGAffineTransform
  • 常用形變方式舉例,效果以Scale(伸縮)為例說(shuō)明,假設(shè)寬高都是100:
    • 方式一:CGAffineTransformMakeXXX:每次從零開(kāi)始形變,每次都是相對(duì)于最開(kāi)始的狀態(tài)形變

      • 效果說(shuō)明:重復(fù)執(zhí)行代碼,每次寬高都是從(100,100)->(50,50)
        self.view.transform = CGAffineTransformMakeTranslation(100, 100);
        self.view.transform = CGAffineTransformMakeScale(0.5, 0.5);
        self.view.transform = CGAffineTransformMakeRotation(M_PI);
        
    • 方式二:CGAffineTransformXXX:接著上次的狀態(tài)形變

      • 效果說(shuō)明:重復(fù)執(zhí)行代碼,寬高是從(100,100)->(50,50)->(25,25)->...
        self.view.transform = CGAffineTransformTranslate(self.view.transform, 100, 100);
        self.view.transform = CGAffineTransformScale(self.view.transform, 0.5, 0.5);
        self.view.transform = CGAffineTransformRotate(self.view.transform, M_PI);
        
    • 方式三:清空形變

      • 效果說(shuō)明:寬高從(?,?)-> (100, 100)
        self.view.transform = CGAffineTransformIdentity;
        

矩形的坐標(biāo)系轉(zhuǎn)換

坐標(biāo)系轉(zhuǎn)換.png
  1. 坐標(biāo)系:
    • UIKit坐標(biāo)系 :以屏幕的左上角為坐標(biāo)原點(diǎn)
    • view1坐標(biāo)系 : 以view1的左上角為坐標(biāo)原點(diǎn)
    • view2坐標(biāo)系 : 以view2的左上角為坐標(biāo)原點(diǎn)
  • 轉(zhuǎn)換過(guò)程:
    1. 判斷舊坐標(biāo)系,確定舊坐標(biāo)系原點(diǎn);
    2. 根據(jù)rect判斷矩形在坐標(biāo)系中的位置,可借助UIKit坐標(biāo)系中轉(zhuǎn);
    3. 確定新坐標(biāo)系,確定舊坐標(biāo)系原點(diǎn),判斷矩形在坐標(biāo)系中的位置
  • 必須注意:rect不是控件,與控件無(wú)關(guān)系!只代表一塊區(qū)域
    convertRect: toView:為例;
    // 0.基礎(chǔ)數(shù)據(jù):UIKit坐標(biāo)系下,view1,view2的坐標(biāo)
    view1.frame = CGRectMake(100, 100, 100, 100);
    view2.frame = CGRectMake(200, 200, 100, 100);
    -------------------------------------------------
    
    // 1.從零點(diǎn)矩形看坐標(biāo)轉(zhuǎn)換
    // 不代表UIKit坐標(biāo)系左上角的點(diǎn)!
    CGRect zeroRect = CGRectZero; // {(0,0),(0,0)}
    
    CGRect newRect1 = [view1 convertRect:zeroRect toView:view2];
    // view1坐標(biāo)系-> view2坐標(biāo)系
    // UIKit坐標(biāo)系下,矩形位置為{(100,100),(0,0)},view2坐標(biāo)系左上角為{(200,200),(0,0)}
    // newRect1{(-100, -100), (0, 0)}
    
    CGRect newRect2 = [view2 convertRect:zeroRect toView:view1];
    // view2坐標(biāo)系-> view1坐標(biāo)系
    // UIKit坐標(biāo)系下,矩形位置為{(200,200),(0,0)},view1坐標(biāo)系左上角為{(100,100),(0,0)}
    // newRect2:{(100,100),(0,0)}
    
    -------------------------------------------------
    // 2.rect={(100, 100, 100, 100)}看坐標(biāo)轉(zhuǎn)換
    // 不代表UIKit坐標(biāo)系中view1控件!
    
    rect1 = redView.frame = CGRectMake(100, 100, 100, 100);
    
    CGRect newRect3 = [view1 convertRect:rect1 toView:view2];
    // view1坐標(biāo)系-> view2坐標(biāo)系
    // UIKit坐標(biāo)系下,矩形位置為{(200,200),(100,100)},view2坐標(biāo)系左上角為{(200,100),(200,100)}
    // newRect3 = {(0, 0), (100, 100)}
    
    CGRect newRect4 = [view2 convertRect:zeroRect toView:view1];
    // view2坐標(biāo)系-> view1坐標(biāo)系
    // UIKit坐標(biāo)系下,矩形位置為{(300,300),(100,100)},view1坐標(biāo)系左上角為{(100,100),(100,100)}
    // newRect6 = {(200, 200), (100, 100)}
    
  • 矩形的坐標(biāo)轉(zhuǎn)換另一個(gè)方法的原理與上述一致,只是fromView才是轉(zhuǎn)換前坐標(biāo)系,不再多論。
    // 結(jié)果一致
    CGRect newRect = [view1 convertRect:rect1 fromView:view2];
    CGRect newRect = [view2 convertRect:rect1 toView:view1];
    
  • 點(diǎn)得坐標(biāo)系轉(zhuǎn)換可參照上述原理,使用方法是:
    CGPoint point = CGPointMake(100, 100);
    // 結(jié)果一致
    [view1 convertPoint:point toView:view2];
    [view2 convertRect:point fromView:view1];
    

常用坐標(biāo)系轉(zhuǎn)換 -> 獲得控件在主窗口(屏幕)中的區(qū)域(rect)

  1. 坐標(biāo)系轉(zhuǎn)換:控件的坐標(biāo)系 -> 主窗口的坐標(biāo)系
    1. 控件的坐標(biāo)系:
    1. 父控件坐標(biāo)系 :以父控件的左上角為坐標(biāo)原點(diǎn)(常用)
    2. 自身坐標(biāo)系 :以控件自身內(nèi)容層的左上角為坐標(biāo)原點(diǎn)(常用)
    2. 主窗口的坐標(biāo)系:即UIKit坐標(biāo)系
  • 注意:在控件的坐標(biāo)系下,rect描述的必須是控件所在區(qū)域;存在規(guī)律:
    1. 若以自身左上角為轉(zhuǎn)換前坐標(biāo)系原點(diǎn),rect為self.bounds;
    2. 若以父控件左上角為轉(zhuǎn)換前坐標(biāo)系原點(diǎn),rect為self.frame
  • 獲取寫法概況如下:
    // 這里為使顯示簡(jiǎn)潔,定義KEY_WINDOW為主窗口
    #define KEY_WINDOW ([UIApplication sharedApplication].keyWindow)
    
    1. 寫法一(推薦):
      // convertRect: toView:
      // 第一個(gè)參數(shù)(這里是KEY_WINDOW)不能設(shè)置為nil
      // redView.bounds的x、y設(shè)置不影響轉(zhuǎn)換結(jié)果
      
      CGRect newRect = [redView convertRect:redView.bounds toView:KEY_WINDOW];
      CGRect newRect = [redView.superview convertRect:redView.frame toView:KEY_WINDOW];
      
    • 等價(jià)于:
      // 規(guī)律:交換寫法一中第一與第三參數(shù),由toView->fromView
      // redView.bounds的x、y設(shè)置不影響轉(zhuǎn)換結(jié)果
      
      // convertRect: fromView:
      CGRect newRect = [KEY_WINDOW convertRect:redView.bounds fromView:redView];
      CGRect newRect = [KEY_WINDOW convertRect:redView.frame fromView:redView.superview];
      
    • 等價(jià)于(假設(shè)redView或其父控件加入的是主窗口):
      // redView.bounds的x、y設(shè)置不影響轉(zhuǎn)換結(jié)果
      CGRect newRect = [redView convertRect:redView.bounds toView:nil];
      CGRect newRect = [redView.superview convertRect:redView.frame toView:nil];
      // 最后一個(gè)參數(shù)可以設(shè)置(toView:nil)->表示以自身所在的窗口(self.window)的左上角為坐標(biāo)系原點(diǎn);
      // 盡管可以省略,開(kāi)發(fā)中建議標(biāo)明轉(zhuǎn)換的坐標(biāo)系,而不是設(shè)置為nil,這是因?yàn)椋?// self.window大部分情況下是keyWindow;但如果控件是加入到其他窗口中(如狀態(tài)欄等),則不是keyWindow
      // 若是比較兩矩形間、點(diǎn)與矩形的關(guān)系,此時(shí)需要保證轉(zhuǎn)換后的坐標(biāo)系必須是相同的坐標(biāo)系;
      
    • 等價(jià)于:
      // 通過(guò) @protocol UICoordinateSpace <NSObject> 中的方法
      // CoordinateSpace:坐標(biāo)空間(系)
      
      CGRect newRect = [redView convertRect:redView.bounds toCoordinateSpace:KEY_WINDOW];
      CGRect newRect = [KEY_WINDOW convertRect:redView.bounds fromCoordinateSpace:redView];
      
      CGRect newRect = [redView.superview convertRect:redView.frame toCoordinateSpace:KEY_WINDOW];
      CGRect newRect = [KEY_WINDOW convertRect:redView.frame fromCoordinateSpace:redView.superview];
      
    • 不等價(jià)于
      // 正確轉(zhuǎn)換(寫法一):
      CGRect newRect = [redView convertRect:redView.bounds toView:KEY_WINDOW];
      CGRect newRect = [redView.superview convertRect:redView.frame toView:KEY_WINDOW];
      
      // 偽轉(zhuǎn)換 -> 描述的區(qū)域不是redView
      CGRect newRect = [redView convertRect:redView.frame toView:KEY_WINDOW];
      CGRect newRect = [redView.superview convertRect:redView.bounds toView:KEY_WINDOW];
      
      // 正確轉(zhuǎn)換(寫法二):
      CGRect newRect = [KEY_WINDOW convertRect:redView.bounds fromView:redView];
      CGRect newRect = [KEY_WINDOW convertRect:redView.frame fromView:redView.superview];
      
      // 偽轉(zhuǎn)換 -> 描述的區(qū)域不是redView
      CGRect newRect = [KEY_WINDOW convertRect:redView.frame fromView:redView];
      CGRect newRect = [KEY_WINDOW convertRect:redView.bounds fromView:redView.superview];
      
      // 偽轉(zhuǎn)換 -> 邏輯錯(cuò)誤
      // 是獲取redView坐標(biāo)系下區(qū)域?yàn)閞ect的矩形在KEY_WINDOW坐標(biāo)系下的區(qū)域newRect,而不是相反
      CGRect newRect = [KEY_WINDOW convertRect:redView.bounds toView:redView];
      CGRect newRect = [KEY_WINDOW convertRect:redView.frame toView:redView.superview];
      CGRect newRect = [KEY_WINDOW convertRect:redView.frame toView:redView];
      CGRect newRect = [KEY_WINDOW convertRect:redView.bounds toView:redView.superview];
      

坐標(biāo)系轉(zhuǎn)換應(yīng)用 -> 矩形區(qū)域(Rect)、點(diǎn)(Point)比較

  • 不同坐標(biāo)系下的區(qū)域(點(diǎn))轉(zhuǎn)換成同一個(gè)坐標(biāo)系下的區(qū)域(點(diǎn))時(shí),可以進(jìn)行區(qū)域間關(guān)系判斷及區(qū)域與點(diǎn)的關(guān)系判斷
  • 判斷rect1是否包含了rect2
    bool CGRectContainsRect(CGRect rect1, CGRect rect2)
    
  • 判斷rect1和rect2是否有重疊
    bool CGRectIntersectsRect(CGRect rect1, CGRect rect2)
    
  • 判斷point是不是在rect上
    bool CGRectContainsPoint(CGRect rect1, CGRect rect2)
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 初識(shí)iOS APP開(kāi)發(fā)#### 在iOS APP開(kāi)發(fā)中, main函數(shù)仍是程序的入口和出口, 但main函數(shù)不需要...
    DeanYan閱讀 6,609評(píng)論 0 3
  • 轉(zhuǎn)載自:http://www.cnblogs.com/snake-hand/p/3190021.html 在調(diào)用視...
    CoderLWG閱讀 657評(píng)論 0 0
  • 1、背景顏色、透明度以及是否隱藏 @property(nullable,nonatomic,copy)UIColo...
    趙亦晨閱讀 412評(píng)論 0 0
  • 1、概念 UIView表示 屏幕上的一塊矩形區(qū)域,它在app占有絕對(duì)重要的地位,因?yàn)閕os中幾乎所有可視化控件都是...
    lilinjianshu閱讀 660評(píng)論 0 0
  • 一、初始化方法 1、- initWithFrame: UIView *view = [[UIView alloc]...
    默默_David閱讀 2,712評(píng)論 1 3

友情鏈接更多精彩內(nèi)容