space position objects by proportion

87 Views Asked by At

My swift code below is positioning objects. I want both objects to be to cover 10 percent of the x axis each. So the first object which is fight[0].image and the 2nd object is fight1.image. As you can see on the image on the left is what the current code below is producing. The image on the right is what I would like the code to produce. Since I can not constraint the code below I don't know how to achieve this result. So fight[0].image should cover 10 percent of the x axis then fight1.image should cover the next 10 percent of the x axis. Together these 2 objects should cover 20 percent of the x axis.

enter image description here

import UIKit

class ViewController: UIViewController {


    let fight = (0..<10).map { _ in UIImageView() }
    var textEnter = UITextField()
    var g2 = UIPanGestureRecognizer()
    var g3 = UIPanGestureRecognizer()


    override func viewDidLoad() {
        super.viewDidLoad()

        fight[0].image  = UIImage(named: "a.png")
        fight[1].image  = UIImage(named: "m.png")
        fight.forEach{
            $0.isUserInteractionEnabled = true
        }
        [textEnter].forEach{
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
            $0.backgroundColor = .blue
        }



        g2 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))
        g3 = UIPanGestureRecognizer(target: self, action: #selector(ViewController.g1Method))


        fight[0].addGestureRecognizer(g2)
        fight[1].addGestureRecognizer(g3)


        fight.forEach{
            $0.backgroundColor = .clear
            view.addSubview($0)

        }


        // need a non-rendering "spacer" to vertically separate textEnter from Pic
        let spacer = UILayoutGuide()
        view.addLayoutGuide(spacer)

        // NOTE: do NOT constrain any elements relative to fight views

        NSLayoutConstraint.activate ([

            // constrain textEnter top / leading / trailing to view
            textEnter.topAnchor.constraint(equalTo: view.topAnchor, constant : 0),
            textEnter.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant : 0),
            textEnter.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant :0),
            // constrain textEnter height to 0.1 * view height
            textEnter.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.1, constant: 0),

            // constrain spacer top to bottom of textEnter
            spacer.topAnchor.constraint(equalTo: textEnter.bottomAnchor, constant: 0.0),
            // constrain spacer leading to view leading
            spacer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0),
            // constrain spacer height to 0.1 * view height
            spacer.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.10),
            // spacer width doesn't matter
            spacer.widthAnchor.constraint(equalToConstant: 1.0),



        ])

        textEnter.textAlignment = .center



    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // set fight[0] frame *after* textEnter has been laid-out
        fight[0].frame.size = CGSize(width: view.frame.width * 0.10, height: view.frame.height * 0.10)
        let x = view.frame.origin.x
        let y = textEnter.frame.origin.y + textEnter.frame.size.height
        fight[0].frame.origin = CGPoint(x: x, y: y)



        fight[1].frame.size = CGSize(width: view.frame.width * 0.10, height: view.frame.height * 0.10)
        let x1 = view.frame.origin.x * 0.10
        let y1 = textEnter.frame.origin.y + textEnter.frame.size.height
        fight[1].frame.origin = CGPoint(x: x1, y: y1)
    }


}
1

There are 1 best solutions below

0
On

You likely want your fight image views to be square (so the image will be round), so calculate the width once as:

let w = view.frame.width * 0.10

and set the height to the same value as the width

let h = w

You'll start with y being the bottom of textEnter, and x as 0, then loop through the image views in your fight array, setting the frame and incrementing x by w:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // set fight frames *after* textEnter has been laid-out

    // width should be 10% of view width
    let w = view.frame.width * 0.10

    // height should be the same as width
    let h = w

    // start x-position at 0
    var x: CGFloat = 0

    // y-position is bottom of textEnter frame
    let y = textEnter.frame.origin.y + textEnter.frame.size.height

    // set frames for all imageViews in fight array
    fight.forEach { v in
        // set the frame
        v.frame = CGRect(x: x, y: y, width: w, height: h)
        // increment x by the width
        x += w
    }
}

You will now have 10 fight image views aligned across the view (I used random colors for the backgrounds):

enter image description here