PanGestureRecognizer 自动布局约束
NSPanGestureRecognizer Autolayout Constriants
我正在使用下面的代码在超级视图的边界内移动一个视图,它工作正常但我想改用自动布局。以下是可移动视图应具有的初始约束,当我使用手势移动它时,我想更新 trailingConstraints 和 bottomConstraints。
width - super view width / 4
height = 9/16 of width
trailingConstraints = 0
bottomConstraints = 0
是否可以通过自动布局使用 NSPanGestureRecognizer?
import Cocoa
class ViewController: NSViewController {
var movableView = NSView()
// MARK: - IBOutlet
@IBOutlet weak var panView: NSView!
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
panView.wantsLayer = true
panView.layer?.backgroundColor = NSColor.white.cgColor
movableView.setFrameSize(NSSize(width: 100, height: 100))
movableView.setFrameOrigin(NSPoint(x: self.panView.frame.size.width - movableView.frame.size.width, y: 0))
movableView.wantsLayer = true
if let myLayer1 = movableView.layer {
myLayer1.backgroundColor = NSColor.red.cgColor
}
panView.addSubview(movableView)
let panRecognizer1 = NSPanGestureRecognizer.init(target: self, action: #selector(panPictureView(_:)))
movableView.addGestureRecognizer(panRecognizer1)
}
// MARK: - Pan gesture
@objc func panPictureView(_ sender: NSPanGestureRecognizer) {
if let movingObject = sender.view {
let translation = sender.translation(in: self.panView)
sender.setTranslation(CGPoint.zero, in: self.panView)
let newX = movingObject.frame.origin.x + translation.x
let newY = movingObject.frame.origin.y + translation.y
let maxX = panView.frame.width - movingObject.frame.width
let maxY = panView.frame.height - movingObject.frame.height
if newX <= 0 && newY <= 0 {
let newPosition = CGPoint(x: 0, y: 0)
movingObject.setFrameOrigin(newPosition)
} else if newX <= 0 {
let newPosition = CGPoint(x: 0, y: newY < maxY ? newY : maxY)
movingObject.setFrameOrigin(newPosition)
} else if newY <= 0 {
let newPosition = CGPoint(x: newX < maxX ? newX : maxX, y: 0)
movingObject.setFrameOrigin(newPosition)
} else if newX >= maxX && newY >= maxY {
let newPosition = CGPoint(x: maxX, y: maxY)
movingObject.setFrameOrigin(newPosition)
} else if newX >= maxX {
let newPosition = CGPoint(x: maxX, y: newY)
movingObject.setFrameOrigin(newPosition)
} else if newY >= maxY {
let newPosition = CGPoint(x: newX, y: maxY)
movingObject.setFrameOrigin(newPosition)
} else {
let newPosition = CGPoint(x: newX, y: newY)
movingObject.setFrameOrigin(newPosition)
}
}
}
}
使用 auto-layout / 约束条件很简单...
我们将为 Leading 和 Top 约束添加 var 属性:
var leadingC: NSLayoutConstraint!
var topC: NSLayoutConstraint!
在我们的平移手势处理程序中,我们将更新这些约束常量:
let translation = sender.translation(in: self.panView)
sender.setTranslation(CGPoint.zero, in: self.panView)
// update movable view Leading and Top constraints
leadingC.constant += translation.x
topC.constant -= translation.y
作为一个额外的好处,我们可以通过给可移动视图 Required 约束限制并给出“可调整的”Leading 和 Top 约束来避免所有 if/else 检查less-than-Required 个优先级。
这是一个完整的示例实现(假设您已经 @IBOutlet var panView
设置):
import Cocoa
class ViewController: NSViewController {
@IBOutlet var panView: NSView!
var movableView = NSView()
var leadingC: NSLayoutConstraint!
var topC: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
super.viewDidLoad()
panView.wantsLayer = true
panView.layer?.backgroundColor = NSColor.blue.cgColor
// we don't need these, since we'll be using constraints
//movableView.setFrameSize(NSSize(width: 100, height: 100))
//movableView.setFrameOrigin(NSPoint(x: self.panView.frame.size.width - movableView.frame.size.width, y: 0))
movableView.wantsLayer = true
if let myLayer1 = movableView.layer {
myLayer1.backgroundColor = NSColor.red.cgColor
}
panView.addSubview(movableView)
// let's use constraints
movableView.translatesAutoresizingMaskIntoConstraints = false
// initialize the constraints we'll use to
// move the subview
leadingC = movableView.leadingAnchor.constraint(equalTo: panView.leadingAnchor)
topC = movableView.topAnchor.constraint(equalTo: panView.topAnchor)
// give them less-than-required priority
// we'll use stronger constraints to prevent dragging
// outside the frame of panView
leadingC.priority = .required - 1
topC.priority = .required - 1
NSLayoutConstraint.activate([
// width and height
movableView.widthAnchor.constraint(equalToConstant: 100.0),
movableView.heightAnchor.constraint(equalTo: movableView.widthAnchor),
// these will prevent dragging outside the panView frame
movableView.topAnchor.constraint(greaterThanOrEqualTo: panView.topAnchor),
movableView.leadingAnchor.constraint(greaterThanOrEqualTo: panView.leadingAnchor),
movableView.trailingAnchor.constraint(lessThanOrEqualTo: panView.trailingAnchor),
movableView.bottomAnchor.constraint(lessThanOrEqualTo: panView.bottomAnchor),
])
let panRecognizer1 = NSPanGestureRecognizer.init(target: self, action: #selector(panPictureView(_:)))
movableView.addGestureRecognizer(panRecognizer1)
}
override func viewDidLayout() {
super.viewDidLayout()
// start movable view at bottom-right corner
// need to wait until auto-layout has setup the frames
// and, to make sure this only happens once,
// only execute if our "movable" constraints are not yet activated
if movableView.frame.size.width != 0 && !leadingC.isActive {
leadingC.constant = self.panView.frame.size.width - movableView.frame.size.width
topC.constant = self.panView.frame.size.height - movableView.frame.size.height
leadingC.isActive = true
topC.isActive = true
}
}
// MARK: - Pan gesture
@objc func panPictureView(_ sender: NSPanGestureRecognizer) {
let translation = sender.translation(in: self.panView)
sender.setTranslation(CGPoint.zero, in: self.panView)
// update movable view Leading and Top constraints
leadingC.constant += translation.x
topC.constant -= translation.y
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
我正在使用下面的代码在超级视图的边界内移动一个视图,它工作正常但我想改用自动布局。以下是可移动视图应具有的初始约束,当我使用手势移动它时,我想更新 trailingConstraints 和 bottomConstraints。
width - super view width / 4 height = 9/16 of width trailingConstraints = 0 bottomConstraints = 0
是否可以通过自动布局使用 NSPanGestureRecognizer?
import Cocoa
class ViewController: NSViewController {
var movableView = NSView()
// MARK: - IBOutlet
@IBOutlet weak var panView: NSView!
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
panView.wantsLayer = true
panView.layer?.backgroundColor = NSColor.white.cgColor
movableView.setFrameSize(NSSize(width: 100, height: 100))
movableView.setFrameOrigin(NSPoint(x: self.panView.frame.size.width - movableView.frame.size.width, y: 0))
movableView.wantsLayer = true
if let myLayer1 = movableView.layer {
myLayer1.backgroundColor = NSColor.red.cgColor
}
panView.addSubview(movableView)
let panRecognizer1 = NSPanGestureRecognizer.init(target: self, action: #selector(panPictureView(_:)))
movableView.addGestureRecognizer(panRecognizer1)
}
// MARK: - Pan gesture
@objc func panPictureView(_ sender: NSPanGestureRecognizer) {
if let movingObject = sender.view {
let translation = sender.translation(in: self.panView)
sender.setTranslation(CGPoint.zero, in: self.panView)
let newX = movingObject.frame.origin.x + translation.x
let newY = movingObject.frame.origin.y + translation.y
let maxX = panView.frame.width - movingObject.frame.width
let maxY = panView.frame.height - movingObject.frame.height
if newX <= 0 && newY <= 0 {
let newPosition = CGPoint(x: 0, y: 0)
movingObject.setFrameOrigin(newPosition)
} else if newX <= 0 {
let newPosition = CGPoint(x: 0, y: newY < maxY ? newY : maxY)
movingObject.setFrameOrigin(newPosition)
} else if newY <= 0 {
let newPosition = CGPoint(x: newX < maxX ? newX : maxX, y: 0)
movingObject.setFrameOrigin(newPosition)
} else if newX >= maxX && newY >= maxY {
let newPosition = CGPoint(x: maxX, y: maxY)
movingObject.setFrameOrigin(newPosition)
} else if newX >= maxX {
let newPosition = CGPoint(x: maxX, y: newY)
movingObject.setFrameOrigin(newPosition)
} else if newY >= maxY {
let newPosition = CGPoint(x: newX, y: maxY)
movingObject.setFrameOrigin(newPosition)
} else {
let newPosition = CGPoint(x: newX, y: newY)
movingObject.setFrameOrigin(newPosition)
}
}
}
}
使用 auto-layout / 约束条件很简单...
我们将为 Leading 和 Top 约束添加 var 属性:
var leadingC: NSLayoutConstraint!
var topC: NSLayoutConstraint!
在我们的平移手势处理程序中,我们将更新这些约束常量:
let translation = sender.translation(in: self.panView)
sender.setTranslation(CGPoint.zero, in: self.panView)
// update movable view Leading and Top constraints
leadingC.constant += translation.x
topC.constant -= translation.y
作为一个额外的好处,我们可以通过给可移动视图 Required 约束限制并给出“可调整的”Leading 和 Top 约束来避免所有 if/else 检查less-than-Required 个优先级。
这是一个完整的示例实现(假设您已经 @IBOutlet var panView
设置):
import Cocoa
class ViewController: NSViewController {
@IBOutlet var panView: NSView!
var movableView = NSView()
var leadingC: NSLayoutConstraint!
var topC: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
super.viewDidLoad()
panView.wantsLayer = true
panView.layer?.backgroundColor = NSColor.blue.cgColor
// we don't need these, since we'll be using constraints
//movableView.setFrameSize(NSSize(width: 100, height: 100))
//movableView.setFrameOrigin(NSPoint(x: self.panView.frame.size.width - movableView.frame.size.width, y: 0))
movableView.wantsLayer = true
if let myLayer1 = movableView.layer {
myLayer1.backgroundColor = NSColor.red.cgColor
}
panView.addSubview(movableView)
// let's use constraints
movableView.translatesAutoresizingMaskIntoConstraints = false
// initialize the constraints we'll use to
// move the subview
leadingC = movableView.leadingAnchor.constraint(equalTo: panView.leadingAnchor)
topC = movableView.topAnchor.constraint(equalTo: panView.topAnchor)
// give them less-than-required priority
// we'll use stronger constraints to prevent dragging
// outside the frame of panView
leadingC.priority = .required - 1
topC.priority = .required - 1
NSLayoutConstraint.activate([
// width and height
movableView.widthAnchor.constraint(equalToConstant: 100.0),
movableView.heightAnchor.constraint(equalTo: movableView.widthAnchor),
// these will prevent dragging outside the panView frame
movableView.topAnchor.constraint(greaterThanOrEqualTo: panView.topAnchor),
movableView.leadingAnchor.constraint(greaterThanOrEqualTo: panView.leadingAnchor),
movableView.trailingAnchor.constraint(lessThanOrEqualTo: panView.trailingAnchor),
movableView.bottomAnchor.constraint(lessThanOrEqualTo: panView.bottomAnchor),
])
let panRecognizer1 = NSPanGestureRecognizer.init(target: self, action: #selector(panPictureView(_:)))
movableView.addGestureRecognizer(panRecognizer1)
}
override func viewDidLayout() {
super.viewDidLayout()
// start movable view at bottom-right corner
// need to wait until auto-layout has setup the frames
// and, to make sure this only happens once,
// only execute if our "movable" constraints are not yet activated
if movableView.frame.size.width != 0 && !leadingC.isActive {
leadingC.constant = self.panView.frame.size.width - movableView.frame.size.width
topC.constant = self.panView.frame.size.height - movableView.frame.size.height
leadingC.isActive = true
topC.isActive = true
}
}
// MARK: - Pan gesture
@objc func panPictureView(_ sender: NSPanGestureRecognizer) {
let translation = sender.translation(in: self.panView)
sender.setTranslation(CGPoint.zero, in: self.panView)
// update movable view Leading and Top constraints
leadingC.constant += translation.x
topC.constant -= translation.y
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}