Deep understand iOS view(一)

Experimenting with Views(view 的小实验)

The viewDidLoad method can refer to the view controller’s main view by saying self.view

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v = UIView(frame:CGRect(x: 0, y: 0, width: 50, height: 50))
        v.backgroundColor = .red  //small red square
        self.view.addSubview(v)  //add it to main view
        
        let v2 = UIView(frame:CGRect(x: 100, y: 100, width: 50, height: 50))
        v2.backgroundColor = .green  //small green square
        self.view.addSubview(v2)  //add it to main view
    }

iphoneXR simulator effect:

 

Subview and Superview(父子view)

starting in OS X 10.5, Apple introduced an entirely new architecture for view drawing that lifted those restrictions completely. iOS view drawing is based on this revised architecture. In iOS, some or all of a subview can appear outside its superview, and a view can overlap another view and can be drawn partially or totally in front of it without being its subview.

1)a superview is drawn before its subviews, so if they overlap it, it will appear to be behind them

2)Sibling subviews of the same superview have a definite order: one is drawn before the other, so if they overlap, it will appear to be behind its sibling

Here are some other effects of the view hierarchy:
• If a view is removed from or moved within its superview, its subviews go with it.
• A view’s degree of transparency is inherited by its subviews.
• A view can optionally limit the drawing of its subviews so that any parts of them outside the view are not shown. This is called clipping and is set with the view’s clipsToBounds property.
• A superview owns its subviews, in the memory-management sense, much as an array owns its elements; it retains them and is responsible for releasing a subview when that subview ceases to be its subview (it is removed from the collection of
this view’s subviews) or when the superview itself goes out of existence.
• If a view’s size is changed, its subviews can be resized automatically (and I’ll have much more to say about that later in this chapter).

A UIView has a superview property (a UIView) and a subviews property (an array of UIView objects, in back-to-front order), 

isDescendant(of:) letting you check whether one view is a subview of another at any depth.

view can have a numeric tag (its tag property)  sending any view higher up the view hierarchy the viewWithTag(_:) message.

addSubview(_:) makes one view a subview of another;

removeFromSuperview takes a subview out of its superview’s view hierarchy

Events inform a view of these dynamic changes

• willRemoveSubview(_:), didAddSubview(_:)
• willMove(toSuperview:), didMoveToSuperview
• willMove(toWindow:), didMoveToWindow

• insertSubview(_:at:)
• insertSubview(_:belowSubview:), insertSubview(_:aboveSubview:)
• exchangeSubview(at:withSubviewAt:)
• bringSubviewToFront(_:), sendSubviewToBack(_:)

removing all of a view’s subviews 

myView.subviews.forEach {$0.removeFromSuperview()}

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v.backgroundColor = .red  //small red square
        self.view.addSubview(v)  //add it to main view
        
        let subV = UIView(frame:CGRect(x: 70, y: 70, width: 150, height: 250))
        subV.backgroundColor = .yellow  //small red square
        v.addSubview(subV)  //add it to main view
        
        let v2 = UIView(frame:CGRect(x: 20, y: 130, width: 200, height: 250))
        v2.backgroundColor = .green  //small green square
        self.view.addSubview(v2)  //add it to main view
    }

iphoneXR simulator effect:

 

Visibility and Opacity(可见性和不透明性)

1)invisible by setting its isHidden property to true/false, 不可见时只是看不见而已,其实还在,但无法接收触摸事件

2)view can be assigned a background color through its backgroundColor property. background color is nil (the default) has a transparent background

3)partially or completely transparent through its alpha property.   1.0 means opaque, 0.0 means transparent

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v.backgroundColor = .red  //small red square
        v.isHidden = true         //can not see
        self.view.addSubview(v)  //add it to main view
        
        let subV = UIView(frame:CGRect(x: 70, y: 70, width: 150, height: 250))
        subV.backgroundColor = .yellow  //small red square
        v.addSubview(subV)  //add it to main view

        let v2 = UIView(frame:CGRect(x: 20, y: 130, width: 200, height: 250))
        v2.backgroundColor = .green  //small green square
        v2.alpha = 0.5    //half of 1
        self.view.addSubview(v2)  //add it to main view
    }

iphoneXR simulator effect:

也验证了,父view可见性被子view 继承了

 

Frame, Bounds and Center 

A view’s frame property, a CGRect, is the position of its rectangle within its super view, in the superview’s coordinate system.  

--  注意:是指在父view坐标系中的位置

--  When a UIView is instantiated from a nib, its init(frame:) is not called init(coder:) is called instead. 

The CGRect that describes a view’s rectangle in its own coordinates is the view’s bounds property.

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v1.backgroundColor = .blue  //small red square
        self.view.addSubview(v1)  //add it to main view
        
        let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10))
        v2.backgroundColor = UIColor(red:1, green:1,blue:0, alpha: 1)
        v1.addSubview(v2)
        
    }

iphoneXR simulator effect:

如果 let v2 = UIView(frame: v1.bounds)  v2 will overlay v1  

if v2 bounds 基础上扩展20,也是在自己坐标系的基础上,中心不变, 因此view的bounds 和中心是正交的,frame只是中心和边界的表示,通常只用frame 就够了,例如初始化的时候是init(frame:) ,可以改变frame, 中心和边界会随之改变, 然而最合适和可靠的放置和缩放一个view的方法是使用边界和中心而不是frame, 通过边界和中心总是有效的。

 

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v1.backgroundColor = .blue  //small red square
        self.view.addSubview(v1)  //add it to main view
        
        let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10))
        v2.backgroundColor = UIColor(red:1, green:1,blue:0, alpha: 1)
        v1.addSubview(v2)
        
        v2.bounds.size.height += 20
        v2.bounds.size.width += 20
        
    }

iphoneXR simulator effect:

调整父view的bounds 原点,改变的是子view的位置, 子view 以相反的方向移动

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v1.backgroundColor = .blue  //small red square

        print(v1.bounds)          //(0.0, 0.0, 150.0, 250.0)
        print(v1.frame)           //(50.0, 50.0, 150.0, 250.0)
        let v2 = UIView(frame:v1.bounds.insetBy(dx: 10, dy: 10))
        v2.backgroundColor = UIColor(red:1, green:1,blue:0, alpha: 1)
        
        v1.bounds.origin.x += 10
        v1.bounds.origin.y += 10
        
        v1.addSubview(v2)
        self.view.addSubview(v1)  //add it to main view
        
        print(v1.bounds)            //(10.0, 10.0, 150.0, 250.0)
        print(v1.frame)             //(50.0, 50.0, 150.0, 250.0)
        
    }

iphoneXR simulator effect:

 

 if v1 is the superview of v2, how to center v2 within v1 ?  - 如何将View放到父view的中心?

v2.center = v1.convert(v1.center, from:v1.superview)   or

v2.center = CGPoint(x: v1.bounds.midX, y: v1.bounds.midY)

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v1.backgroundColor = .blue  //small red square

        print(v1.bounds)          //(0.0, 0.0, 150.0, 250.0)
        print(v1.frame)           //(50.0, 50.0, 150.0, 250.0)
        let v2 = UIView(frame:CGRect(x: 20, y: 50, width: 100, height: 100))
        v2.backgroundColor = UIColor(red:1, green:1,blue:0, alpha: 1)
        v2.center = CGPoint(x: v1.bounds.midX, y: v1.bounds.midY)
        
        print(v2.bounds)          //(0.0, 0.0, 100, 100)
        print(v2.frame)           //(25.0, 75.0, 100, 100)
        
        v1.addSubview(v2)
        self.view.addSubview(v1)  //add it to main view
    }

iphoneXR simulator effect:

 

Transform ,变换

A transform value is a CGAffineTransform,三种变换:rotation, scaling, and translation

1) 旋转45° CGAffineTransform(rotationAngle: 45 * .pi/180)

 

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v1.backgroundColor = .blue  //small red square

        print(v1.bounds)          //(0.0, 0.0, 150.0, 250.0)
        print(v1.frame)           //(50.0, 50.0, 150.0, 250.0)
        let v2 = UIView(frame:CGRect(x: 20, y: 50, width: 100, height: 100))
        v2.backgroundColor = UIColor(red:1, green:1,blue:0, alpha: 1)
        v2.center = CGPoint(x: v1.bounds.midX, y: v1.bounds.midY)
        
        v1.addSubview(v2)
        self.view.addSubview(v1)  //add it to main view
        
        v1.transform = CGAffineTransform(rotationAngle: 45 * .pi/180)
        print(v1.frame)
    }

效果图

 

 

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 50, y: 50, width: 150, height: 250))
        v1.backgroundColor = .blue  //small red square

        print(v1.bounds)          //(0.0, 0.0, 150.0, 250.0)
        print(v1.frame)           //(50.0, 50.0, 150.0, 250.0)
        let v2 = UIView(frame:CGRect(x: 20, y: 50, width: 100, height: 100))
        v2.backgroundColor = UIColor(red:1, green:1,blue:0, alpha: 1)
        v2.center = CGPoint(x: v1.bounds.midX, y: v1.bounds.midY)
        
        v1.addSubview(v2)
        self.view.addSubview(v1)  //add it to main view
        
        //v1.transform = CGAffineTransform(rotationAngle: 45 * .pi/180)
        v1.transform = CGAffineTransform(scaleX: 1.2, y: 1)
        print(v1.frame)          //(35.0, 50.0, 180.0, 250.0)
    }

效果图

根据frame 打印可知 宽度150 -> 180   确实增加了20%,起点小了15,中心不变

 

平移和旋转混合

1)先平移后旋转

   override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 20, y: 100, width: 120, height: 200))
        v1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1)
        let v2 = UIView(frame:v1.bounds)
        v2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1)
        self.view.addSubview(v1)
        v1.addSubview(v2)
        
        //v1.transform = CGAffineTransform(rotationAngle: 45 * .pi/180)
        v2.transform =
            CGAffineTransform(translationX:100, y:0).rotated(by: 45 * .pi/180)
        print(v1.frame, v1.center)
        print(v2.frame, v2.center)
    }

效果图

2)先旋转后平移

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let v1 = UIView(frame:CGRect(x: 20, y: 100, width: 120, height: 200))
        v1.backgroundColor = UIColor(red: 1, green: 0.4, blue: 1, alpha: 1)
        let v2 = UIView(frame:v1.bounds)
        v2.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0, alpha: 1)
        self.view.addSubview(v1)
        v1.addSubview(v2)
        
        //v1.transform = CGAffineTransform(rotationAngle: 45 * .pi/180)
        //v2.transform = CGAffineTransform(translationX:100, y:0).rotated(by: 45 * .pi/180)
        v2.transform = CGAffineTransform(rotationAngle: 45 * .pi/180).translatedBy(x: 100, y: 0)
        print(v1.frame, v1.center)
        print(v2.frame, v2.center)
    }

效果图

 

方法二:  concatenating 连接函数实现先旋转后平移

        let r = CGAffineTransform(rotationAngle: 45 * .pi/180)

        let t = CGAffineTransform(translationX:100, y:0)

        v2.transform = t.concatenating(r) // not r.concatenating(t)

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值