我想在视图中添加UILabel,当发生错误时向下滑动以向用户发送错误消息。它的原型就像Facebook或Instagram显示的那样。这是我到目前为止编写的代码:
func sendErrorMessage(errorString: String) {
self.errorLabel.text = errorString
UIView.animateWithDuration(1, animations: {
self.errorLabel.frame.height = 30 //Cannot assign to the result of this expression
self.topView.layoutIfNeeded()
}, completion: {
(finished: Bool) in var timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: Selector(), userInfo: nil, repeats: false)
})
}
errorLabel
现在已经在故事板中,但高度为0,topView
是errorLabel
的超级视图。我对这些方法很陌生,所以我被困在这里。我不明白为什么会发生错误以及selector
应该在这里做些什么。还有一个步骤我在这里没有完成,errorLabel
应该在三秒后滑动消失,这就是我在这里需要timer
的原因。
另外:如果我在需要的时候创建一个新的errorLabel
而不是在故事板之前准备好它,那会有什么不同吗?我的意思是应用程序内存管理性能。
更新
我在许多errorLabel
中需要ViewController
,所以按照@Sajjon的想法,我尝试了UILabel
的子类。这是我的子类ErrorLabel
:
class ErrorLabel: UILabel {
var errorString: String?
func sendErrorMessage() {
self.text = errorString
showErrorLabel()
let timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: "hideErrorLabel", userInfo: nil, repeats: false)
}
func animateFrameChange() {
UIView.animateWithDuration(1, animations: { self.layoutIfNeeded() }, completion: nil)
}
func showErrorLabel() {
let oldFrame = self.frame
let newFrame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, oldFrame.height + 30, oldFrame.width)
self.frame = newFrame
self.animateFrameChange()
}
func hideErrorLabel() {
let oldFrame = self.frame
let newFrame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, oldFrame.height - 30, oldFrame.width)
self.frame = newFrame
self.animateFrameChange()
}
}
答案 0 :(得分:1)
一般来说,视图用于其框架或边界属性的CGRect对象是不可变的。不要试图直接修改视图的框架,而是创建一个包含所需最终大小和位置的新CGRect,并将其分配给动画块中的视图框架。
//Don't do this.
myView.frame.size.height = 30;
// Do this instead.
CGRect oldRect = myView.frame;
CGRect newFrame = CGRectMake(oldRect.origin.x, oldRect.origin.y, oldRect.size.width, 30);
[UIView animateWithDuration:0.4 animations:^{
myView.frame = newFrame;
};
另外,我强烈建议让标签显示并隐藏我在屏幕顶部和屏幕顶部更改其y位置,而不是将高度更改为0,这可能会产生一些意想不到的布局后果
答案 1 :(得分:0)
换高度尝试:
self.errorLabel.frame.size.height = 30
答案 2 :(得分:0)
你需要设置Frame of UILable而不是它的高度。
String DATABASE_CREATE_SQL =
"CREATE TABLE " + DATABASE_TABLE
+ " (" + KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ KEY_TRANSACTION + " TEXT NOT NULL, "
+ KEY_ITEM + " TEXT NOT NULL, "
+ KEY_SUM + " TEXT"
+ ");";
答案 3 :(得分:0)
你应该为此使用autolayout,当显示errorLabel(或它在里面的某个容器视图)时,我会给出你想要的值的高度约束(30)。并通过赋予约束值0来再次隐藏它。
我会创建一个UIView扩展并放置代码来设置此高度变化的动画。
这是未经测试的代码,但会让您了解如何实现它。
class MyViewController: UIViewController {
@IBOutlet weak var errorLabelHeightConstraint: NSLayoutConstraint!
private let errorLabelHeightVisible: CGFloat = 30
private let hideDelay: NSTimeInterval = 3
private var timer: NSTimer!
func sendErrorMessage(errorString: String) {
errorLabel.text = errorString
showOrHideErrorView(false)
}
func showOrHideErrorView(hide: Bool = true, animated: Bool = true) {
if hide {
errorLabelHeightConstraint.constant = 0
} else {
errorLabelHeightConstraint.constant = errorLabelHeightVisible
}
let automaticallyHideErrorViewClosure: () -> Void = {
/* Only scheduling hiding of error message, if we just showed it. */
if !hide {
dispatch_async(dispatch_get_main_queue(), {
() -> Void in
automaticallyHideErrorMessage()
})
}
}
if animated {
view.animateConstraintChange(completion: {
(finished: Bool) -> Void in
automaticallyHideErrorViewClosure()
})
} else {
view.layoutIfNeeded()
automaticallyHideErrorViewClosure()
}
}
/* Selector method */
func hideError() {
showOrHideErrorView()
}
func automaticallyHideErrorMessage() {
if timer != nil {
if timer.valid {
timer.invalidate()
}
timer = nil
}
timer = NSTimer.scheduledTimerWithTimeInterval(hideDelay, target: self, selector: "hideError", userInfo: nil, repeats: false)
}
}
extension UIView {
static var standardDuration: NSTimeInterval { get { return 0.3 } }
func animateConstraintChange(duration: NSTimeInterval = standardDuration, completion: ((Bool) -> Void)? = nil) {
UIView.animate(durationUsed: duration, animations: {
() -> Void in
self.layoutIfNeeded()
}, completion: completion)
}
}