the slider changes the position of the object to its original position. You can see whites goin on the gif below. I just want when the user changes the size for the object to stay in its original position and not revert back to its original. I guess this is all being affected by var backCon.
import UIKit
class ViewController: UIViewController {
var backBox = UIButton()
var slider = UISlider()
var panGesture = UIPanGestureRecognizer()
var backCon = [NSLayoutConstraint]()
var widthConstraints: NSLayoutConstraint?
var tim = 50.0
var slidermultiplier: CGFloat = 0.6
override func viewDidLoad() {
super.viewDidLoad()
[backBox,slider].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.backgroundColor = UIColor(
red: .random(in: 0.0...1),
green: .random(in: 0.9...1),
blue: .random(in: 0.7...1),
alpha: 1
)
}
NSLayoutConstraint.activate([
slider.bottomAnchor.constraint(equalTo: view.bottomAnchor),
slider.leadingAnchor.constraint(equalTo: view.leadingAnchor),
slider.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.1),
slider.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
])
widthConstraints = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
backCon = [
backBox.centerYAnchor.constraint(equalTo: view.centerYAnchor),
backBox.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: CGFloat(tim)),
backBox.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.5),
widthConstraints!,
]
panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.draggedView(_:)))
NSLayoutConstraint.activate(backCon)
backBox.isUserInteractionEnabled = true
slider.addTarget(self, action: #selector(increase), for: .valueChanged)
backBox.addGestureRecognizer(panGesture)
}
@objc func increase() {
slidermultiplier = CGFloat(slider.value)
widthConstraints?.isActive = false
widthConstraints = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
widthConstraints?.isActive = true
}
@objc func draggedView(_ sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
backBox.center = CGPoint(x: backBox.center.x + translation.x , y: backBox.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: self.view)
}
@objc func sliderr() {
NSLayoutConstraint.deactivate(backCon)
backCon = [
backBox.centerYAnchor.constraint(equalTo: view.centerYAnchor),
backBox.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: CGFloat(-tim)),
backBox.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.3),
widthConstraints!,
]
NSLayoutConstraint.activate(backCon)
}
}
You will almost always run into problems when using auto-layout constraints, and then explicitly setting frame values (include .center
).
So, like you did with the Width constraint, you'll want to create constraints for Leading and CenterY so you can update those instead of setting .center =
:
@objc func draggedView(_ sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
// update backBox Leading and CenterY constraints
backBoxLeading.constant += translation.x
backBoxCenterY.constant += translation.y
sender.setTranslation(CGPoint.zero, in: self.view)
}
Here's a complete implementation (modification of your code). The //
comments should make things pretty clear:
class SamViewController: UIViewController {
var backBox = UIButton()
var slider = UISlider()
var panGesture = UIPanGestureRecognizer()
// constraint we will modify when slider is changed
var backBoxWidth: NSLayoutConstraint!
// constraints we will modify when backBox is dragged
var backBoxCenterY: NSLayoutConstraint!
var backBoxLeading: NSLayoutConstraint!
var tim = 50.0
var slidermultiplier: CGFloat = 0.6
override func viewDidLoad() {
super.viewDidLoad()
[backBox,slider].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.backgroundColor = UIColor(
red: .random(in: 0.0...1),
green: .random(in: 0.9...1),
blue: .random(in: 0.7...1),
alpha: 1
)
}
NSLayoutConstraint.activate([
slider.bottomAnchor.constraint(equalTo: view.bottomAnchor),
slider.leadingAnchor.constraint(equalTo: view.leadingAnchor),
slider.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.1),
slider.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 1),
])
// backBox Width constraint
backBoxWidth = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
// backBox CenterY constraint
backBoxCenterY = backBox.centerYAnchor.constraint(equalTo: view.centerYAnchor)
// backBox Leading constraint
backBoxLeading = backBox.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: CGFloat(tim))
NSLayoutConstraint.activate([
// backBox Height is constant
backBox.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.5),
backBoxWidth,
backBoxLeading,
backBoxCenterY,
])
panGesture = UIPanGestureRecognizer(target: self, action: #selector(draggedView(_:)))
backBox.isUserInteractionEnabled = true
slider.addTarget(self, action: #selector(increase), for: .valueChanged)
backBox.addGestureRecognizer(panGesture)
// we start the backBox Width at "slidermultiplier" of view, so
// start the slider at "slidermultiplier"
slider.setValue(Float(slidermultiplier), animated: false)
}
@objc func increase() {
slidermultiplier = CGFloat(slider.value)
// update backBox Width constraint
backBoxWidth.isActive = false
backBoxWidth = backBox.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: slidermultiplier)
backBoxWidth.isActive = true
}
@objc func draggedView(_ sender: UIPanGestureRecognizer) {
let translation = sender.translation(in: self.view)
// update backBox Leading and CenterY constraints
backBoxLeading.constant += translation.x
backBoxCenterY.constant += translation.y
sender.setTranslation(CGPoint.zero, in: self.view)
}
}