移动子视图 - 偏移量错误,但视觉上正确?
Posted
技术标签:
【中文标题】移动子视图 - 偏移量错误,但视觉上正确?【英文标题】:moving subview - offset amount wrong, but visually correct? 【发布时间】:2015-06-04 04:54:03 【问题描述】:我编写了这个示例程序来尝试弄清楚发生了什么。我有一个文本字段,单击时会显示子视图而不是显示键盘。在子视图中,有一个关闭按钮,它可以移动子视图,使顶部与屏幕底部对齐。
这样我就可以在故事板中构建子视图,子视图在启动时与屏幕的底部边缘和hidden
对齐。 viewDidLoad
然后调用hideSubView
在开始之前将其移出屏幕。
每次轮班前后我都有println
告诉我子视图的位置。
我遇到的问题是数字不加起来。我特别告诉 swift 将 Y 偏移 210,但不知何故,它只将它移动了 68.5,这是屏幕底部的 NOT(请注意,这不是通过将子视图设置为文本字段的输入视图来完成的)。然而,当我单击文本字段时,子视图从下往上动画,而不是中间点。谁能解释为什么会发生这两件事?另一件事是 - 初始 minY 的 457.0 来自哪里?我检查了子视图的初始高度,奇怪的是 143(不是 141.5)。
控制台输出(// - 我为澄清而添加的行)
//hideSubview called from viewDidLoad
Before. minY:457.0 screenheight:667.0 offset:210.0
After. minY:525.5 screenheight:667.0 offset:210.0 //NOTE:457+210 is 667, not 525.5
//1st showSubView called by clicking on myTextField
Before. minY:525.5 screenheight:667.0 subview Height:141.5
After. minY:525.5 subView height:141.5
//hideSubView called by clicking on dismiss button
Before. minY:525.5 screenheight:667.0 offset:141.5
After. minY:667.0 screenheight:667.0 offset:141.5
//2nd showSubView called by clicking on myTextField
Before. minY:667.0 screenheight:667.0 subview Height:141.5
After. minY:525.5 subView height:141.5
//hideSubView called by clicking on dismiss button
Before. minY:525.5 screenheight:667.0 offset:141.5
After. minY:667.0 screenheight:667.0 offset:141.5
Main.storyboard ViewController.swift
import UIKit
class ViewController: UIViewController, UITextFieldDelegate
@IBOutlet weak var myTextField: UITextField!
@IBOutlet weak var mySubView: UIView!
var screenSize = UIScreen.mainScreen().bounds
var subViewIsVisible = false
override func viewDidLoad()
super.viewDidLoad()
myTextField.delegate = self
hideSubView()
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
@IBAction func dismissButtonClicked(sender: AnyObject)
if subViewIsVisible
hideSubView()
func textFieldDidBeginEditing(textField: UITextField)
myTextField.endEditing(true)
if !subViewIsVisible
showSubView()
func hideSubView ()
var offsetAmount = screenSize.height - mySubView.frame.minY
println("Before. minY:\(mySubView.frame.minY) screenheight:\(screenSize.height) offset:\(offsetAmount)")
UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut , animations:
self.mySubView.frame.offset(dx: 0, dy: offsetAmount)
, completion: _ in
self.subViewIsVisible = false
self.mySubView.hidden = true
println("After. minY:\(self.mySubView.frame.minY) screenheight:\(self.screenSize.height) offset:\(offsetAmount)")
)
func showSubView ()
mySubView.hidden = false
println("Before. minY:\(mySubView.frame.minY) screenheight:\(screenSize.height) subview Height:\(mySubView.frame.height)")
UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut , animations:
self.mySubView.frame.offset(dx: 0, dy: -self.mySubView.frame.height)
, completion: _ in
self.subViewIsVisible = true
println("After. minY:\(self.mySubView.frame.minY) subView height:\(self.mySubView.frame.height)")
)
编辑:
mySubView 的约束:(比我对 Bannings 的评论更容易看到)
【问题讨论】:
为什么不将mySubView
分配给myTextField
的inputAccessoryView
?
@Bannings 这是我遇到问题的程序的简化版本。在那一个中,我有一个TextField
和一个Searchbar
,它们都可以拉起mySubView
。我有限的知识是,一个视图不能有超过 1 个父视图。在这个例子中,如果我按照你说的设置它,那么mySubView
将有 2 个父视图 - 我在故事板上绘制它的主视图和 TextField
。这是正确的吗?
您是否在mySubView
中添加了任何约束?
@Bannings 外部约束 for mySubView
: 1. 将中心 X 与超级视图对齐。 2. 前导空间到 superview = 50。 3. 底部空间 = 底部布局指南。 Internal Constraints(在子视图内):所有 4 个标签(将 Center X 与 Superview 对齐)。所有 4 个标签的顶部和底部 = 10。因此对子视图没有明确的约束来定义它的精确高度。高度由内部组件上设置的约束定义,即关闭按钮的高度 + L1+L2+L3 和 5x10 个空格。
我猜 457 和 143 来自推断的大小,如 mySubView
的约束屏幕截图所示。但是,我已将 ios 模拟器设置为 iPhone6,因此当 viewDidLoad 运行时,它应该具有所有正确的数字。假设起始大小为 143,我希望自动布局将 mySubView
放置在 667-143 = 524...
【参考方案1】:
457 和 143 来自您的故事板,如下所示:
出现这种行为是因为 viewDidLoad
方法中视图的来源不正确。虽然Bottom Layout Guide
有底部约束,但是框架还没有调整。
因此,如果您将视图的 y 设置为 500,那么您将获得如下日志:
Before. minY:500.0 screenheight:667.0 offset:167.0
After. minY:524.5 screenheight:667.0 offset:167.0
在 AutoLayout 调用 viewDidLoad
后,您的 mySubView
的框架将正确。
【讨论】:
感谢您试用。但你确实看到了问题吗?有多个问题,但我遇到的最明显、未解决的问题是:在这两个println
之间,有一个 self.mySubView.frame.offset(dx: 0, dy: offsetAmount)
(来自 hideSubView)。在您的情况下,偏移量是 167。500 + 167 是 NOT 524.5。另请注意 - 524.5 不是屏幕底部,但是当您单击文本字段时,视图将从底部出现,根据控制台输出,它不在!
这是因为您有一个bottom constraint
,这将导致它始终在屏幕上。您可以尝试将行设置为self.mySubView.hidden = true
无论这个offset
的值是多少都不会影响它在屏幕上的位置
我取消了mySubView
(在情节提要中)的“隐藏”选项并注释掉了self.mySubView.hidden = true
。运行时,如您所说,它位于底部边缘(基本上忽略了我放置在 viewDidLoad 中的 hideSubView 函数)。但是,当您单击文本字段时 - 它应该将子视图从当前位置动画到当前位置减去子视图的高度,它来自自下而上而不是静止不动,因为它已经在该位置。
您确实可以更新其frame
,但这是不安全的,自动布局将在下一次绘图更新(例如旋转屏幕)中再次更新其frame
,因此无法保证结果。如果你真的想改变它,你应该做一个 IBOutlet,像这样:***.com/questions/23655096/…以上是关于移动子视图 - 偏移量错误,但视觉上正确?的主要内容,如果未能解决你的问题,请参考以下文章
网格视图(UICollectionView)的偏移量随着分页滚动而逐渐移动