我正在使用带有正常和高亮状态图片的UIButton。它们按预期工作,但我想要一些渐变/融合转换效果而不仅仅是突然切换。
我该如何做到这一点?
我该如何做到这一点?
可以使用UIView的过渡动画来实现。即使isHighlighted
属性不可动画化,也没关系,因为它会过渡整个视图。
UIView.transition(with: button,
duration: 4.0,
options: .transitionCrossDissolve,
animations: { button.isHighlighted = true },
completion: nil)
[UIView transitionWithView:button
duration:4.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{ button.highlighted = YES; }
completion:nil];
为了实现这一点,我扩展了UIButton。添加了一个名为hilightedImage的新属性,代码如下:
- (void)setHilightImage:(UIImageView *)_hilightImage
{
if (hilightImage != _hilightImage) {
[hilightImage release];
hilightImage = [_hilightImage retain];
}
[hilightImage setAlpha:0];
[self addSubview:hilightImage];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.14];
if(hilightImage){
[hilightImage setAlpha:1];
}
[UIView commitAnimations];
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.highlighted = FALSE;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.14];
if(hilightImage){
[hilightImage setAlpha:0];
}
[UIView commitAnimations];
[super touchesEnded:touches withEvent:event];
}
UIButton
继承自 UIView
因此,您可以获取其视图并调用 beginAnimations:context:
然后从那里调用所有适当的 setAnimation 方法。
UIView
类的以下属性可进行动画处理:
参考:UIView 类参考
这里有一个自包含的解决方案,也支持布尔型animated
标志。
- (void)setEnabled:(BOOL)enabled animated:(BOOL)animated
{
if (_button.enabled == enabled) {
return;
}
void (^transitionBlock)(void) = ^void(void) {
_button.enabled = enabled;
};
if (animated) {
[UIView transitionWithView:_button
duration:0.15
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
transitionBlock();
}
completion:nil];
} else {
transitionBlock();
}
}
@marián-Černý在 Swift 中的回答:
Swift 2
UIView.transitionWithView(button,
duration: 4.0,
options: .TransitionCrossDissolve,
animations: { button.highlighted = true },
completion: nil)
Swift 3, 4, 5
UIView.transition(with: button,
duration: 4.0,
options: .transitionCrossDissolve,
animations: { button.isHighlighted = true },
completion: nil)
如果你在 iOS 15 之后来到这里并使用新的 UIButton.Configuration
,你可能会使用 configurationUpdateHandler
来确定和设置配置。在这种情况下,你可以使用 UIView.transition(with: button
API 设置配置(可能是函数中最后要做的事情),像这样:
UIView.transition(with: button,
duration: 0.2,
options: [.transitionCrossDissolve,
.beginFromCurrentState,
.allowUserInteraction,
.curveEaseInOut],
animations: { button.configuration = configuration })
我使用了CustomButton代替UIButton
并重写了isHighlighted
属性,这对我很有效;
class KeypadButton: UIButton {
var highlightDuration: TimeInterval = 0.25
override var isHighlighted: Bool {
didSet {
if oldValue == false && isHighlighted {
highlight()
} else if oldValue == true && !isHighlighted {
unHighlight()
}
}
}
func highlight() {
animateBackground(to: highlightedBackgroundColor, duration: highlightDuration)
}
func unHighlight() {
animateBackground(to: normalBackgroundColor, duration: highlightDuration)
}
private func animateBackground(to color: UIColor?, duration: TimeInterval) {
guard let color = color else { return }
UIView.animate(withDuration: highlightDuration) {
self.backgroundColor = color
}
}
}
highlighted
属性不可动画化。 - Martyhighlighted
属性不可动画化,因此必须使用+transitionWithView:duration:options:animations:completion:
而不是+animateWithDuration:delay:options:animations:completion:
。 - Marián Černý.transitionCrossDissolve
。其他动画样式不能可靠地进行动画化。@MariánČerný- 我建议你扩展这个例子,并提出一个 where 的想法,例如在... isHighlighted { didSet {} }
内部执行。 - brandonscript