เป้าหมายที่เรียบง่ายของฉันคือการทำให้การซ่อนและการแสดงฟังก์ชั่นจางหายไป
Button.hidden = YES;
เรียบง่ายพอสมควร อย่างไรก็ตามเป็นไปได้หรือไม่ที่มันจะหายไปแทนที่จะหายไป? มันดูไม่เป็นมืออาชีพเลยทีเดียว
เป้าหมายที่เรียบง่ายของฉันคือการทำให้การซ่อนและการแสดงฟังก์ชั่นจางหายไป
Button.hidden = YES;
เรียบง่ายพอสมควร อย่างไรก็ตามเป็นไปได้หรือไม่ที่มันจะหายไปแทนที่จะหายไป? มันดูไม่เป็นมืออาชีพเลยทีเดียว
คำตอบ:
ใน iOS 4 และใหม่กว่ามีวิธีการเพียงแค่ใช้วิธีการเปลี่ยน UIView โดยไม่จำเป็นต้องนำเข้า QuartzCore คุณสามารถพูดได้ว่า:
[UIView transitionWithView:button
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
button.hidden = YES;
}
completion:NULL];
UIView.transition(with: button, duration: 0.4,
options: .transitionCrossDissolve,
animations: {
button.hidden = false
})
วิธีแก้ปัญหาของ Michail จะได้ผล แต่ก็ไม่ใช่วิธีที่ดีที่สุด
ปัญหาเกี่ยวกับการซีดจางของอัลฟาคือบางครั้งเลเยอร์มุมมองที่ทับซ้อนกันดูแปลก ๆ เมื่อมันหายไป มีทางเลือกอื่น ๆ โดยใช้ Core Animation ก่อนอื่นให้รวมเฟรมเวิร์กของ QuartzCore ในแอปของคุณและเพิ่มไว้#import <QuartzCore/QuartzCore.h>
ในส่วนหัวของคุณ ตอนนี้คุณสามารถทำอย่างใดอย่างหนึ่งต่อไปนี้:
1) ตั้งค่าbutton.layer.shouldRasterize = YES;
แล้วใช้รหัสภาพเคลื่อนไหวอัลฟ่าที่ Michail ระบุไว้ในคำตอบของเขา สิ่งนี้จะป้องกันเลเยอร์จากการผสมอย่างแปลก ๆ แต่มีโทษประสิทธิภาพเล็กน้อยและสามารถทำให้ปุ่มดูพร่ามัวถ้ามันไม่ได้อยู่ในแนวเดียวกันกับขอบเขตของพิกเซล
อีกวิธีหนึ่งคือ:
2) ใช้รหัสต่อไปนี้เพื่อทำให้จางหายแทน:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
สิ่งที่ดีเกี่ยวกับวิธีนี้คือคุณสามารถข้ามคุณสมบัติของปุ่มใด ๆ ได้แม้ว่ามันจะไม่สามารถเคลื่อนไหวได้ (เช่นข้อความหรือรูปภาพของปุ่ม) เพียงแค่ตั้งค่าการเปลี่ยนภาพแล้วตั้งค่าคุณสมบัติของคุณทันทีหลังจากนั้น
transitionWithView
พารามิเตอร์เพื่อให้แน่ใจว่าประสบความสำเร็จในการเข้าและออก
คุณสมบัติภาพเคลื่อนไหว UIView คือ:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
อธิบายใน: ภาพเคลื่อนไหว
isHidden
ไม่ใช่หนึ่งในนั้นดังนั้นเมื่อฉันเห็นวิธีที่ดีที่สุดคือ:
สวิฟท์ 4:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
วัตถุประสงค์ C:
- (void)setView:(UIView*)view hidden:(BOOL)hidden {
[UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
[view setHidden:hidden];
} completion:nil];
}
วิธีการลบ:
Objective-C
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 0;
} completion: ^(BOOL finished) {//creates a variable (BOOL) called "finished" that is set to *YES* when animation IS completed.
button.hidden = finished;//if animation is finished ("finished" == *YES*), then hidden = "finished" ... (aka hidden = *YES*)
}];
สวิฟท์ 2
UIView.animateWithDuration(0.3, animations: {
button.alpha = 0
}) { (finished) in
button.hidden = finished
}
สวิฟท์ 3, 4, 5
UIView.animate(withDuration: 0.3, animations: {
button.alpha = 0
}) { (finished) in
button.isHidden = finished
}
จะจางหายไปใน:
Objective-C
button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 1;
}];
สวิฟท์ 2
button.alpha = 0
button.hidden = false
UIView.animateWithDuration(0.3) {
button.alpha = 1
}
สวิฟท์ 3, 4, 5
button.alpha = 0
button.isHidden = false
UIView.animate(withDuration: 0.3) {
button.alpha = 1
}
ฉันใช้ส่วนขยายSwift 3เล็กน้อยนี้:
extension UIView {
func fadeIn(duration: TimeInterval = 0.5,
delay: TimeInterval = 0.0,
completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
UIView.animate(withDuration: duration,
delay: delay,
options: UIViewAnimationOptions.curveEaseIn,
animations: {
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5,
delay: TimeInterval = 0.0,
completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
UIView.animate(withDuration: duration,
delay: delay,
options: UIViewAnimationOptions.curveEaseIn,
animations: {
self.alpha = 0.0
}, completion: completion)
}
}
สวิฟท์ 3
func appearView() {
self.myView.alpha = 0
self.myView.isHidden = false
UIView.animate(withDuration: 0.9, animations: {
self.myView.alpha = 1
}, completion: {
finished in
self.myView.isHidden = false
})
}
สวิฟท์ 4.2
ด้วยส่วนขยาย:
extension UIView {
func hideWithAnimation(hidden: Bool) {
UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
self.isHidden = hidden
})
}
}
วิธีการง่าย ๆ :
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
ใช้โซลูชันนี้เพื่อเอฟเฟ็กต์เฟดจางออกอย่างราบรื่นและเฟดอิน
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.isHidden = true
self.alpha = 0.0
}, completion: completion)
}
}
การใช้งานเป็นเหมือน
uielement.fadeIn()
uielement.fadeOut()
ขอบคุณ
fadeOut
ทำงานบน iOS 13 self.isHidden
เท่านั้นถ้าผมลบบรรทัดที่ชุด
ฉันสร้างหมวดหมู่เพื่อการนี้และดำเนินการพิเศษหน่อยบิตแนวคิดที่แตกต่างกันUIView
visibility
ข้อแตกต่างที่สำคัญของโซลูชันของฉันคือคุณสามารถโทร[view setVisible:NO animated:YES]
และตรวจสอบได้ทันทีหลังจากนั้น[view visible]
พร้อมกันและรับผลลัพธ์ที่ถูกต้อง มันค่อนข้างง่าย แต่มีประโยชน์มาก
นอกจากนี้ยังได้รับอนุญาตให้หลีกเลี่ยงการใช้ "ตรรกะบูลีนเชิงลบ" (ดู รหัสสมบูรณ์, หน้า 269, ใช้ชื่อตัวแปรบูลีนบวกสำหรับข้อมูลเพิ่มเติม)
UIView+Visibility.swift
import UIKit
private let UIViewVisibilityShowAnimationKey = "UIViewVisibilityShowAnimationKey"
private let UIViewVisibilityHideAnimationKey = "UIViewVisibilityHideAnimationKey"
private class UIViewAnimationDelegate: NSObject {
weak var view: UIView?
dynamic override func animationDidStop(animation: CAAnimation, finished: Bool) {
guard let view = self.view where finished else {
return
}
view.hidden = !view.visible
view.removeVisibilityAnimations()
}
}
extension UIView {
private func removeVisibilityAnimations() {
self.layer.removeAnimationForKey(UIViewVisibilityShowAnimationKey)
self.layer.removeAnimationForKey(UIViewVisibilityHideAnimationKey)
}
var visible: Bool {
get {
return !self.hidden && self.layer.animationForKey(UIViewVisibilityHideAnimationKey) == nil
}
set {
let visible = newValue
guard self.visible != visible else {
return
}
let animated = UIView.areAnimationsEnabled()
self.removeVisibilityAnimations()
guard animated else {
self.hidden = !visible
return
}
self.hidden = false
let delegate = UIViewAnimationDelegate()
delegate.view = self
let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = visible ? 0.0 : 1.0
animation.toValue = visible ? 1.0 : 0.0
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
animation.delegate = delegate
self.layer.addAnimation(animation, forKey: visible ? UIViewVisibilityShowAnimationKey : UIViewVisibilityHideAnimationKey)
}
}
func setVisible(visible: Bool, animated: Bool) {
let wereAnimationsEnabled = UIView.areAnimationsEnabled()
if wereAnimationsEnabled != animated {
UIView.setAnimationsEnabled(animated)
defer { UIView.setAnimationsEnabled(!animated) }
}
self.visible = visible
}
}
UIView+Visibility.h
#import <UIKit/UIKit.h>
@interface UIView (Visibility)
- (BOOL)visible;
- (void)setVisible:(BOOL)visible;
- (void)setVisible:(BOOL)visible animated:(BOOL)animated;
@end
UIView+Visibility.m
#import "UIView+Visibility.h"
NSString *const UIViewVisibilityAnimationKeyShow = @"UIViewVisibilityAnimationKeyShow";
NSString *const UIViewVisibilityAnimationKeyHide = @"UIViewVisibilityAnimationKeyHide";
@implementation UIView (Visibility)
- (BOOL)visible
{
if (self.hidden || [self.layer animationForKey:UIViewVisibilityAnimationKeyHide]) {
return NO;
}
return YES;
}
- (void)setVisible:(BOOL)visible
{
[self setVisible:visible animated:NO];
}
- (void)setVisible:(BOOL)visible animated:(BOOL)animated
{
if (self.visible == visible) {
return;
}
[self.layer removeAnimationForKey:UIViewVisibilityAnimationKeyShow];
[self.layer removeAnimationForKey:UIViewVisibilityAnimationKeyHide];
if (!animated) {
self.alpha = 1.f;
self.hidden = !visible;
return;
}
self.hidden = NO;
CGFloat fromAlpha = visible ? 0.f : 1.f;
CGFloat toAlpha = visible ? 1.f : 0.f;
NSString *animationKey = visible ? UIViewVisibilityAnimationKeyShow : UIViewVisibilityAnimationKeyHide;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 0.25;
animation.fromValue = @(fromAlpha);
animation.toValue = @(toAlpha);
animation.delegate = self;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation forKey:animationKey];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
{
if ([[self.layer animationForKey:UIViewVisibilityAnimationKeyHide] isEqual:animation]) {
self.hidden = YES;
}
}
@end
รหัสของ @Umair Afzal ทำงานได้ดีใน swift 5 หลังจากการเปลี่ยนแปลงบางอย่าง
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 0.0
}) { (completed) in
self.isHidden = true
completion(true)
}
}
}
สำหรับการใช้งาน
yourView.fadeOut()
yourView.fadeIn()
สวิฟต์ 4
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.alpha = 0.0
}) { (completed) in
self.isHidden = true
completion(true)
}
}
}
และหากต้องการใช้ให้ใช้ง่าย ๆ เรียกฟังก์ชันเหล่านี้เช่น:
yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation
isHidden
เป็นค่าในทันทีและคุณไม่สามารถส่งผลต่อภาพเคลื่อนไหวแทนได้คุณสามารถใช้ Alpha เพื่อซ่อนมุมมองของคุณ
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 0
})
และสำหรับการแสดง:
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 1
})
คุณสามารถทำได้อย่างง่ายดายโดยใช้ไลบรารี่ Animatics :
//To hide button:
AlphaAnimator(0) ~> button
//to show button
AlphaAnimator(1) ~> button
func flipViews(fromView: UIView, toView: UIView) {
toView.frame.origin.y = 0
self.view.isUserInteractionEnabled = false
UIView.transition(from: fromView, to: toView, duration: 0.5, options: .transitionFlipFromLeft, completion: { finished in
fromView.frame.origin.y = -900
self.view.isUserInteractionEnabled = true
})
}
คุณสามารถลองสิ่งนี้
func showView(objView:UIView){
objView.alpha = 0.0
UIView.animate(withDuration: 0.5, animations: {
objView.alpha = 0.0
}, completion: { (completeFadein: Bool) -> Void in
objView.alpha = 1.0
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
objView.layer.add(transition, forKey: nil)
})
}
func HideView(objView:UIView){
UIView.animate(withDuration: 0.5, animations: {
objView.alpha = 1.0
}, completion: { (completeFadein: Bool) -> Void in
objView.alpha = 0.0
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
objView.layer.add(transition, forKey: nil)
})
}
และส่งชื่อมุมมองของคุณ
showView(objView: self.viewSaveCard)
HideView(objView: self.viewSaveCard)
หากมุมมองของคุณถูกตั้งค่าให้ซ่อนตามค่าเริ่มต้นหรือคุณเปลี่ยนสถานะที่ซ่อนซึ่งฉันคิดว่าคุณควรทำในหลายกรณีแล้วไม่มีวิธีการใดในหน้านี้ที่จะให้ภาพเคลื่อนไหว FadeIn / FadeOut กับคุณทั้งสอง เหตุผลคือคุณกำลังตั้งค่าสถานะที่ซ่อนอยู่เป็นเท็จก่อนที่จะเรียกวิธีการUIView.animateซึ่งจะทำให้มองเห็นได้อย่างฉับพลันและถ้าคุณทำให้อัลฟาเคลื่อนไหวเท่านั้นพื้นที่วัตถุยังคงอยู่ที่นั่น แต่มองไม่เห็นซึ่งจะทำให้เกิดปัญหา UI บางอย่าง
ดังนั้นวิธีที่ดีที่สุดคือการตรวจสอบก่อนว่ามุมมองถูกซ่อนหรือไม่จากนั้นตั้งค่าอัลฟ่าเป็น 0.0 เช่นนี้เมื่อคุณตั้งค่าสถานะซ่อนเป็นเท็จคุณจะไม่เห็นการมองเห็นอย่างฉับพลัน
func hideViewWithFade(_ view: UIView) {
if view.isHidden {
view.alpha = 0.0
}
view.isHidden = false
UIView.animate(withDuration: 0.3, delay: 0.0, options: .transitionCrossDissolve, animations: {
view.alpha = view.alpha == 1.0 ? 0.0 : 1.0
}, completion: { _ in
view.isHidden = !Bool(truncating: view.alpha as NSNumber)
})
}
UIView.transition (พร้อม :) ฟังก์ชั่นดีและเรียบร้อย
หลายคนโพสต์ไว้ แต่ไม่มีใครสังเกตเห็นว่ามีความผิดพลาดเกิดขึ้นเฉพาะเมื่อคุณเรียกใช้
คุณสามารถเปลี่ยนคุณสมบัติที่ซ่อนอยู่ให้เป็นจริงได้อย่างสมบูรณ์แบบในขณะที่เมื่อคุณพยายามที่จะเปลี่ยนให้เป็นเท็จมุมมองจะหายไปทันทีโดยไม่ต้องมีภาพเคลื่อนไหวใด ๆ
นั่นเป็นเพราะ api นี้ใช้งานได้ในมุมมองเท่านั้นซึ่งหมายความว่าเมื่อคุณเปลี่ยนมุมมองเพื่อแสดงในความเป็นจริงตัวเองจะแสดงในทันทีเฉพาะเนื้อหาของภาพเคลื่อนไหวที่ค่อยๆ
เมื่อคุณพยายามที่จะซ่อนมุมมองนี้ตัวเองซ่อนตัวทันทีทำให้ภาพเคลื่อนไหวกับเนื้อหานั้นไม่มีความหมาย
ในการแก้ปัญหานี้เมื่อซ่อนมุมมองเป้าหมายการเปลี่ยนแปลงควรเป็นมุมมองพาเรนต์แทนมุมมองที่คุณต้องการซ่อน
func transitionView(_ view: UIView?, show: Bool, completion: BoolFunc? = nil) {
guard let view = view, view.isHidden == show, let parent = view.superview else { return }
let target: UIView = show ? view : parent
UIView.transition(with: target, duration: 0.4, options: [.transitionCrossDissolve], animations: {
view.isHidden = !show
}, completion: completion)
}
วิธีการแก้ปัญหาของฉันสำหรับสวิฟท์ 3 ดังนั้นฉันจึงสร้างฟังก์ชั่นที่ซ่อน / ยกเลิกการซ่อนมุมมองในลำดับที่ถูกต้อง (เมื่อซ่อน - ตั้งค่าอัลฟ่าเป็น 0 จากนั้น isHidden to true; unhiding - ก่อนเปิดเผยมุมมองจากนั้นตั้งค่าอัลฟ่าเป็น 1):
func hide(_ hide: Bool) {
let animations = hide ? { self.alpha = 0 } :
{ self.isHidden = false }
let completion: (Bool) -> Void = hide ? { _ in self.isHidden = true } :
{ _ in UIView.animate(withDuration: duration, animations: { self.alpha = 1 }) }
UIView.animate(withDuration: duration, animations: animations, completion: completion)
}
completion
บล็อกจึงมีภาพเคลื่อนไหวอื่นเมื่อhide
เท็จ
Swift 4 Transition
UIView.transition(with: view, duration: 3, options: .transitionCurlDown,
animations: {
// Animations
view.isHidden = hidden
},
completion: { finished in
// Compeleted
})
หากคุณใช้วิธีการสำหรับเวอร์ชันที่รวดเร็วกว่าคุณจะได้รับข้อผิดพลาด:
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
isHidden
ค่าจะแสดงผลทันที (เช่นทันทีซ่อน / แสดงมุมมอง)
รหัสนี้ให้ภาพเคลื่อนไหวเช่นการผลักดัน viewController ในตัวควบคุม uinavigation ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = true;
ใช้สำหรับภาพเคลื่อนไหวป๊อปอัพ ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromLeft;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = false;
ลองใช้คำตอบที่ออกมาบางคำตอบใช้ได้กับสถานการณ์เดียวบางคำตอบต้องเพิ่มสองฟังก์ชัน
ตัวเลือกที่ 1
view.isHidden
ไม่มีอะไรจะทำอย่างไรกับ
extension UIView {
func animate(fadeIn: Bool, withDuration: TimeInterval = 1.0) {
UIView.animate(withDuration: withDuration, delay: 0.0, options: .curveEaseInOut, animations: {
self.alpha = fadeIn ? 1.0 : 0.0
})
}
}
จากนั้นผ่านisFadeIn
( true
หรือfalse
)
view.animate(fadeIn: isFadeIn)
ตัวเลือก 2
ไม่ผ่านพารามิเตอร์ใด ๆ isUserInteractionEnabled
มันจางหายไปในหรือออกไปตาม สิ่งนี้ยังเหมาะสมกับสถานการณ์ที่เคลื่อนไหวไปมาได้ดีมาก
func animateFadeInOut(withDuration: TimeInterval = 1.0) {
self.isUserInteractionEnabled = !self.isUserInteractionEnabled
UIView.animate(withDuration: withDuration, delay: 0.0, options: .curveEaseInOut, animations: {
self.alpha = self.isUserInteractionEnabled ? 1.0 : 0.0
})
}
จากนั้นคุณโทร
yourView.animateFadeInOut()
ทำไม
self.isUserInteractionEnabled
?พยายามแทนที่
self.isUserInteractionEnabled
โดยself.isHidden
ไม่มีโชคเลย
แค่นั้นแหละ. เสียค่าใช้จ่ายบ้างในบางครั้งหวังว่ามันจะช่วยใครซักคน