ios - 仅在其父视图内拖动 UIImageView
问题描述
假设我有:
- 一个
UIImageView
叫fox
- 一个父 ImageView 调用
fence
- 默认
UIView
嵌入的大师ViewControllers
现在换句话说,我只想fox
在它里面移动fence
在我的viewDidLoad()
:
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(fence)
fence.addSubview(fox)
}
现在这部分工作正常,我想通过一些修改来移动fox
子类:UIImageView
class DraggableImageView: UIImageView {
var dragStartPositionRelativeToCenter : CGPoint?
override init(image: UIImage!) {
super.init(image: image)
self.isUserInteractionEnabled = true
addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(handlePan(nizer:))))
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 3)
layer.shadowOpacity = 0.5
layer.shadowRadius = 2
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func handlePan(nizer: UIPanGestureRecognizer!) {
if nizer.state == UIGestureRecognizer.State.began {
let locationInView = nizer.location(in: superview)
dragStartPositionRelativeToCenter = CGPoint(x: locationInView.x - center.x, y: locationInView.y - center.y)
layer.shadowOffset = CGSize(width: 0, height: 20)
layer.shadowOpacity = 0.3
layer.shadowRadius = 6
return
}
if nizer.state == UIGestureRecognizer.State.ended {
dragStartPositionRelativeToCenter = nil
layer.shadowOffset = CGSize(width: 0, height: 3)
layer.shadowOpacity = 0.5
layer.shadowRadius = 2
return
}
let locationInView = nizer.location(in: superview)
UIView.animate(withDuration: 0.1) {
self.center = CGPoint(x: locationInView.x - self.dragStartPositionRelativeToCenter!.x,
y: locationInView.y - self.dragStartPositionRelativeToCenter!.y)
}
}}
现在我可以将fox
对象拖到任何我喜欢的地方,但是;如果我只想移动对象fox
内部怎么办fence
?,因为它是一个子视图,我认为这是可能的。
解决方案
为了将图像视图保持在其父级中,我在更新视图的中心之前添加了一个检查,以确保视图框架将位于父级框架中。仅当更新将视图保持在其父框架内时,中心才会更新。
我还更新了平移处理程序以使用翻译(类似于平移手势文档中的示例),而不是 locationInView。这使得阻力表现更好。
我已经对此进行了测试,我相信它会按照您想要的方式运行。希望这可以帮助:
@objc func handlePan(nizer: UIPanGestureRecognizer!) {
if nizer.state == UIGestureRecognizer.State.began {
dragStartPositionRelativeToCenter = self.center
layer.shadowOffset = CGSize(width: 0, height: 20)
layer.shadowOpacity = 0.3
layer.shadowRadius = 6
return
}
if nizer.state == UIGestureRecognizer.State.ended {
dragStartPositionRelativeToCenter = nil
layer.shadowOffset = CGSize(width: 0, height: 3)
layer.shadowOpacity = 0.5
layer.shadowRadius = 2
return
}
if let initialCenter = dragStartPositionRelativeToCenter {
let translation = nizer.translation(in: self.superview)
let newCenter = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + translation.y)
if frameContainsFrameFromCenter(containingFrame: superview!.frame, containedFrame: self.frame, center: newCenter) {
UIView.animate(withDuration: 0.1) {
self.center = newCenter
}
}
}
}
func frameContainsFrameFromCenter(containingFrame: CGRect, containedFrame: CGRect, center: CGPoint) -> Bool {
let leftMargin = containedFrame.width / 2
let topMargin = containedFrame.height / 2
let testFrame = CGRect(
x: leftMargin,
y: topMargin,
width: containingFrame.width - (2*leftMargin),
height: containingFrame.height - (2*topMargin)
)
return testFrame.contains(center)
}
推荐阅读
- javascript - 悬停时显示标题属性,然后在不悬停时恢复为原始文本
- python - Python Pandas:根据条件用第二个数据帧的值填充一个数据帧的值
- selenium - “通过 .Net 应用程序通过浏览器登录 Google 帐户网站”
- embedded-jetty - 嵌入式码头的 JDBC 会话(9.4 以上版本)
- bluetooth-lowenergy - 2020 年在哪里可以找到 BLE GATT 规范 xml?
- php - 如何从 MySQL 和 PHP 中的多个表中检索数据?
- vue.js - 如何在 Vuetify 中根据设备自动调整所有文本的大小?
- typescript - 如何在不复制共享模块的情况下由不同项目共享 Typescript 模块?
- javascript - 如何在没有提交按钮的情况下提交表单?
- php - Cakephp CSRF 不匹配