代码之家  ›  专栏  ›  技术社区  ›  Erent

如何将一个UIImage放在另一个具有特定维度的UIImage上

  •  0
  • Erent  · 技术社区  · 5 年前

    enter image description here

    我正在以编程方式创建视图,以便可以重用它。以下是目前为止我的代码。

    import UIKit
    
    @IBDesignable
    class ProfileView: UIView {
    
        fileprivate var imageView: UIImageView!
        fileprivate var onlineStatusView: UIView!
        fileprivate var onlineStatusDotView: UIView!
    
    
        @IBInspectable
        var image: UIImage? {
            get { return imageView.image }
            set { imageView.image = newValue }
        }
    
        @IBInspectable
        var shouldShowStatusDot: Bool = true
    
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            initialize()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            initialize()
        }
    
        private func initialize() {
            backgroundColor = .clear
    
            imageView = UIImageView(frame: bounds)
            imageView.backgroundColor = .lightGray
            imageView.clipsToBounds = true
            imageView.layer.cornerRadius = imageView.frame.height / 2
            addSubview(imageView)
    
            onlineStatusView = UIView(frame: CGRect(x: 0, y: 0, width: (bounds.height / 5), height: (bounds.height / 5)))
            onlineStatusView.backgroundColor = .white
            onlineStatusView.clipsToBounds = true
            onlineStatusView.layer.cornerRadius = onlineStatusView.frame.height / 2
            addSubview(onlineStatusView)
    
            onlineStatusDotView = UIView(frame: CGRect(x: 0, y: 0, width: (onlineStatusView.bounds.height / 1.3), height: (onlineStatusView.bounds.height / 1.3)))
            onlineStatusDotView.center = onlineStatusView.center
            onlineStatusDotView.backgroundColor = UIColor(red: 0.17, green: 0.71, blue: 0.45, alpha: 1.0)
            onlineStatusDotView.clipsToBounds = true
            onlineStatusDotView.layer.cornerRadius = onlineStatusDotView.frame.height / 2
            onlineStatusView.addSubview(onlineStatusDotView)
        }
    }
    

    enter image description here

    我失去的是如何在 圆形的

    我需要设置哪些自动布局约束才能将其放置到正确的位置?

    我上传了一个 demo project 这里也是。

    0 回复  |  直到 5 年前
        1
  •  5
  •   vacawama    5 年前

    要将绿色小圆圈放在大圆圈的右上角,请执行以下操作:

    1. 使小圆成为大圆的子视图。
    2. 使用添加约束 .centerX .trailing 在一个大圆圈里 multiplier 属于 0.8536
    3. 使用添加约束 .centerY 小圆的大小等于 .bottom 在一个大圆圈里 乘数 属于 0.1464 .

    注: 乘数 s是用 三角学 通过查看单位圆并计算比率: (distance from top of square containing unit circle)/(height of unit circle) (distance from left edge of square containing unit circle)/(width of unit circle) . 在下面的示例代码中,我提供了 func computeMultipliers(angle:) 它计算任何 angle 以度为单位。准确避开角度 90 180 因为这可以创造出 0 哪一个 不喜欢。


    以下是独立示例:

    class ViewController: UIViewController {
    
        var bigCircle: UIView!
        var littleCircle: UIView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            bigCircle = UIView()
            bigCircle.translatesAutoresizingMaskIntoConstraints = false
            bigCircle.backgroundColor = .red
            view.addSubview(bigCircle)
    
            bigCircle.widthAnchor.constraint(equalToConstant: 240).isActive = true
            bigCircle.heightAnchor.constraint(equalToConstant: 240).isActive = true
    
            littleCircle = UIView()
            littleCircle.translatesAutoresizingMaskIntoConstraints = false
            littleCircle.backgroundColor = .green
            bigCircle.addSubview(littleCircle)
    
            bigCircle.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            bigCircle.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    
            littleCircle.widthAnchor.constraint(equalToConstant: 60).isActive = true
            littleCircle.heightAnchor.constraint(equalToConstant: 60).isActive = true
    
            let (hMult, vMult) = computeMultipliers(angle: 45)
    
            // position the little green circle using a multiplier on the right and bottom
            NSLayoutConstraint(item: littleCircle!, attribute: .centerX, relatedBy: .equal, toItem: bigCircle!, attribute: .trailing, multiplier: hMult, constant: 0).isActive = true
            NSLayoutConstraint(item: littleCircle!, attribute: .centerY, relatedBy: .equal, toItem: bigCircle!, attribute: .bottom, multiplier: vMult, constant: 0).isActive = true
    
        }
    
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
    
            bigCircle.layer.cornerRadius = 0.5 * bigCircle.frame.height
    
            littleCircle.layoutIfNeeded()
            littleCircle.layer.cornerRadius = 0.5 * littleCircle.frame.height
        }
    
        func computeMultipliers(angle: CGFloat) -> (CGFloat, CGFloat) {
            let radians = angle * .pi / 180
    
            let h = (1.0 + cos(radians)) / 2
            let v = (1.0 - sin(radians)) / 2
    
            return (h, v)
        }
    }
    

    image of sample code running in the simulator


    这是您的代码的修改版本。我添加了约束来设置小圆圈的大小,并移动了设置 cornerRadius layoutSubviews() :

    class ProfilePictureView: UIView {
        var bigCircle: UIView!
        var borderCircle: UIView!
        var littleCircle: UIView!
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            initialize()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            initialize()
        }
    
        private func initialize() {
            bigCircle = UIView(frame: bounds)
            bigCircle.backgroundColor = .red
            addSubview(bigCircle)
    
            borderCircle = UIView()
            borderCircle.translatesAutoresizingMaskIntoConstraints = false
            borderCircle.backgroundColor = .white
            bigCircle.addSubview(borderCircle)
    
            borderCircle.widthAnchor.constraint(equalTo: bigCircle.widthAnchor, multiplier: 1/3).isActive = true
            borderCircle.heightAnchor.constraint(equalTo: bigCircle.heightAnchor, multiplier: 1/3).isActive = true
    
            littleCircle = UIView()
            littleCircle.translatesAutoresizingMaskIntoConstraints = false
            littleCircle.backgroundColor = .green
            borderCircle.addSubview(littleCircle)
    
            littleCircle.widthAnchor.constraint(equalTo: borderCircle.widthAnchor, multiplier: 1/1.3).isActive = true
            littleCircle.heightAnchor.constraint(equalTo: borderCircle.heightAnchor, multiplier: 1/1.3).isActive = true
            littleCircle.centerXAnchor.constraint(equalTo: borderCircle.centerXAnchor).isActive = true
            littleCircle.centerYAnchor.constraint(equalTo: borderCircle.centerYAnchor).isActive = true
    
            let (hMult, vMult) = computeMultipliers(angle: 45)
    
            // position the border circle using a multiplier on the right and bottom
            NSLayoutConstraint(item: borderCircle!, attribute: .centerX, relatedBy: .equal, toItem: bigCircle!, attribute: .trailing, multiplier: hMult, constant: 0).isActive = true
            NSLayoutConstraint(item: borderCircle!, attribute: .centerY, relatedBy: .equal, toItem: bigCircle!, attribute: .bottom, multiplier: vMult, constant: 0).isActive = true
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            bigCircle.layer.cornerRadius = bigCircle.frame.height / 2
            borderCircle.layoutIfNeeded()
            borderCircle.layer.cornerRadius = borderCircle.frame.height / 2
            littleCircle.layoutIfNeeded()
            littleCircle.layer.cornerRadius = littleCircle.frame.height / 2
        }
    
        private func computeMultipliers(angle: CGFloat) -> (CGFloat, CGFloat) {
            let radians = angle * .pi / 180
    
            let h = (1.0 + cos(radians)) / 2
            let v = (1.0 - sin(radians)) / 2
    
            return (h, v)
        }
    }
    

    second image with white border


    背后的数学解释 计算机万用钳(角度:)

    关于 是不是应该为 水平约束 垂直约束 0个 1 哪里 0个 顶部 0个 左边 1个 底部 垂直约束和 1个 水平约束的圆边缘。

    乘法器是通过查看 the unit circle 1个 (0, 0) 在坐标系上。单位圆(根据定义)的好处是圆上的一条线(从原点开始)与圆相交的点是 (cos(angle), sin(angle)) 从正开始测量角度 x-axis 逆时针到与圆相交的线。注意单位圆的宽度和高度分别为 2 .

    sin(angle) cos(angle) 各不相同 -1 .

    方程式:

    1 + cos(angle)
    

    会有所不同 0个 2个 0个 1个 ,我们把这个除以 2个

    // compute the horizontal multiplier based upon the angle
    let h = (1.0 + cos(radians)) / 2
    

    在垂直方向,我们首先注意到坐标系是从数学意义上翻转的。在iOS中, y 向下发展,但在数学上, 是的 向上生长。为此,垂直计算使用- - 而不是 +

    1 - sin(angle)
    

    又一次,因为 sin 变化范围 ,此计算将来自 0个 2个 ,所以我们除以 2个

    // compute the vertical multiplier based upon the angle
    let h = (1.0 - sin(radians)) / 2
    

    这给了我们想要的结果。当角度是 90个 .pi/2 弧度, 1个 ,所以垂直乘数为 . 当角度是 270 度(或 3*.pi/2 弧度, -1个 垂直乘数是 .

    一旦你了解弧度是什么,弧度就是直观的。它们只是沿单位圆圆周的弧长。圆周长的公式是 circumference = 2 * .pi * radius 对于单位圆,周长是 2 * .pi . 所以 360 度是 2*π

        2
  •  1
  •   Ashish Gupta    5 年前

    使用以下命令更改初始化函数:

      private func initialize() {
        backgroundColor = .clear
    
        imageView = UIImageView(frame: bounds)
        imageView.backgroundColor = .lightGray
        imageView.clipsToBounds = true
        imageView.layer.cornerRadius = imageView.frame.height / 2
        addSubview(imageView)
    
        onlineStatusView = UIView(frame: CGRect(x: 0, y: 0, width: (bounds.height / 5), height: (bounds.height / 5)))
        onlineStatusView.center = CGPoint(x: bounds.width / 7, y: bounds.height / 7)
        onlineStatusView.backgroundColor = .white
        onlineStatusView.clipsToBounds = true
        onlineStatusView.layer.cornerRadius = onlineStatusView.frame.height / 2
        addSubview(onlineStatusView)
    
        onlineStatusDotView = UIView(frame: CGRect(x: 0, y: 0, width: (onlineStatusView.bounds.height / 1.3), height: (onlineStatusView.bounds.height / 1.3)))
          onlineStatusDotView.center = CGPoint(x: onlineStatusView.frame.width / 2, y: onlineStatusView.frame.height / 2)
        onlineStatusDotView.backgroundColor = UIColor(red: 0.17, green: 0.71, blue: 0.45, alpha: 1.0)
        onlineStatusDotView.clipsToBounds = true
        onlineStatusDotView.layer.cornerRadius = onlineStatusDotView.frame.height / 2
        onlineStatusView.addSubview(onlineStatusDotView)
    }