[英]Dismiss SVProgressHUD with Tap Gesture
我需要向 SVProgressHUD 添加一個UITapGestureRecognizer 。 SVProgressHUD 已經可以使用-(void) dismiss;
. 此代碼將根據秒關閉動畫。
- (void)dismiss {
for (UIGestureRecognizer *gesture in [[[self class] sharedView] gestureRecognizers]) {
[[[self class] sharedView] removeGestureRecognizer:gesture];
}
NSDictionary *userInfo = [self notificationUserInfo];
[[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification
object:nil
userInfo:userInfo];
self.activityCount = 0;
[UIView animateWithDuration:0.15
delay:0
options:UIViewAnimationCurveEaseIn | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 0.8, 0.8);
if(self.isClear) // handle iOS 7 UIToolbar not answer well to hierarchy opacity change
self.hudView.alpha = 0;
else
self.alpha = 0;
}
completion:^(BOOL finished){
if(self.alpha == 0 || self.hudView.alpha == 0) {
self.alpha = 0;
self.hudView.alpha = 0;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self cancelRingLayerAnimation];
[self addTapGestureToDismiss];
[_hudView removeFromSuperview];
_hudView = nil;
[_overlayView removeFromSuperview];
_overlayView = nil;
[_indefiniteAnimatedView removeFromSuperview];
_indefiniteAnimatedView = nil;
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
[[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification
object:nil
userInfo:userInfo];
// Tell the rootViewController to update the StatusBar appearance
UIViewController *rootController = [[UIApplication sharedApplication] keyWindow].rootViewController;
if ([rootController respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) {
[rootController setNeedsStatusBarAppearanceUpdate];
}
// uncomment to make sure UIWindow is gone from app.windows
//NSLog(@"%@", [UIApplication sharedApplication].windows);
//NSLog(@"keyWindow = %@", [UIApplication sharedApplication].keyWindow);
}
}];
}
我的思考過程是將tapGesture 代碼添加到dismiss 方法中。 這是我到目前為止所寫的。
- (void)addTapGestureToDismiss {
// Creation and initializer of the tap gesture
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(dismiss)];
// Specify that the gesture must be a single tap
tapRecognizer.numberOfTapsRequired = 1;
// Add the tap gesture recognizer to the view
[[[self class] sharedView] addGestureRecognizer:tapRecognizer];
}
如您所見,我只是在初始化 tapGesture。 我遇到了將它放在幾個地方並導致應用程序只有一次點擊的問題。 我在這個過程中非常困惑。 我該不該
基於 Z.Hung 的回答,您可以在 SVProgressHUD 上創建一個類別,這樣您就不必在每個使用它的視圖控制器中重復此代碼。
用法
只需導入此類別並調用
[SVProgressHUD showDismissableErrorWithStatus:@"Error message here"];
代碼
@interface SVProgressHUD (Dismissable)
+ (void)showDismissableErrorWithStatus:(NSString*)status;
@end
@implementation SVProgressHUD (Dismissable)
+ (void)showDismissableErrorWithStatus:(NSString*)status {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleHUDTappedNotification:) name:SVProgressHUDDidReceiveTouchEventNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleHUDDisappearedNotification:) name:SVProgressHUDWillDisappearNotification object:nil];
[SVProgressHUD showErrorWithStatus: status];
}
#pragma mark - NSNotificationCenter
+ (void)handleHUDTappedNotification: (NSNotification *)notification {
[SVProgressHUD dismiss];
}
+ (void)handleHUDDisappearedNotification: (NSNotification *)notification {
[[NSNotificationCenter defaultCenter] removeObserver:self name:SVProgressHUDDidReceiveTouchEventNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:SVProgressHUDWillDisappearNotification object:nil];
}
@end
斯威夫特 4
import SVProgressHUD
/// Ref: https://stackoverflow.com/a/41111242/425694
extension SVProgressHUD {
public static func showDismissableError(with status: String) {
let nc = NotificationCenter.default
nc.addObserver(
self, selector: #selector(hudTapped(_:)),
name: NSNotification.Name.SVProgressHUDDidReceiveTouchEvent,
object: nil
)
nc.addObserver(
self, selector: #selector(hudDisappeared(_:)),
name: NSNotification.Name.SVProgressHUDWillDisappear,
object: nil
)
SVProgressHUD.showError(withStatus: status)
SVProgressHUD.setDefaultMaskType(.clear)
}
@objc
private static func hudTapped(_ notification: Notification) {
SVProgressHUD.dismiss()
SVProgressHUD.setDefaultMaskType(.none)
}
@objc
private static func hudDisappeared(_ notification: Notification) {
let nc = NotificationCenter.default
nc.removeObserver(self, name: NSNotification.Name.SVProgressHUDDidReceiveTouchEvent, object: nil)
nc.removeObserver(self, name: NSNotification.Name.SVProgressHUDWillDisappear, object: nil)
SVProgressHUD.setDefaultMaskType(.none)
}
}
更新 2.0
一段時間后,我偶然發現了這個解決方案並記住了這個問題,據我測試,它有效。 只需在 ViewController 類的 viewWillAppear 中添加一個觀察者。 無需像我之前的答案一樣修改庫。
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tapToDismiss:) name:SVProgressHUDDidReceiveTouchEventNotification object:nil];
//Other initializing
}
-(void)tapToDismiss:(NSNotification *)notification{
[SVProgressHUD dismiss];
//maybe other code to stop whatever your progress is
}
即使您有掩碼類型,這也應該關閉 SVProgressHUD。
完成后使用它來刪除觀察者(如在 viewDidDisappear 中),否則它將在應用程序的整個生命周期中都存在。
[[NSNotificationCenter defaultCenter] removeObserver:self name:SVProgressHUDDidReceiveTouchEventNotification object:nil];
信用: http : //kevsaidwhat.blogspot.my/2013/06/cancel-svprogresshud-process-by-tapping.html
完整的 swift 實現有人可能會發現它很有用。 這是 BaseViewController
func showProgressHud(){
SVProgressHUD.show()
SVProgressHUD.setDefaultMaskType(.clear)
}
func hideProgressHud(){
SVProgressHUD.dismiss()
}
//Hide progress hud on user tap on unresponsive api call
func hideProgressHudOnUserTap(){
NotificationCenter.default.addObserver(self, selector: #selector(self.tapToDismiss(notification:)), name: NSNotification.Name.SVProgressHUDDidReceiveTouchEvent, object: nil)
}
@objc func tapToDismiss(notification: Notification) {
hideProgressHud()
}
func removeProgressHudObserver(){
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.SVProgressHUDDidReceiveTouchEvent, object: nil)
}
然后你像這樣在你的視圖控制器中調用它
override func viewWillAppear(_ animated: Bool) {
hideProgressHudOnUserTap()
}
override func viewDidDisappear(_ animated: Bool) {
removeProgressHudObserver()
}
實現這一點的簡單方法是:
class HUDManager {
@objc
class func dismissHUD() {
SVProgressHUD.dismiss()
}
}
SVProgressHUDDidReceiveTouchEvent
通知:NotificationCenter.default.addObserver(HUDManager.self,
selector: #selector(HUDManager.dismissHUD),
name: .SVProgressHUDDidReceiveTouchEvent,
object: nil)
謝謝@charmingToad,如果在這里回答,我想在上面發布一些更優化和功能更強大的解決方案。
在我的情況下,如果用戶點擊並取消,我需要知道取消操作以取消操作。
import SVProgressHUD
extension SVProgressHUD {
private static var dismissCompletion: (() -> ())?
public static func showDismissable(with status: String, tapDismissed: (() -> ())? = nil) {
dismissCompletion = tapDismissed
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(
self, selector: #selector(hudTapped(_:)),
name: NSNotification.Name.SVProgressHUDDidReceiveTouchEvent,
object: nil
)
notificationCenter.addObserver(
self, selector: #selector(hudDisappeared(_:)),
name: NSNotification.Name.SVProgressHUDWillDisappear,
object: nil
)
SVProgressHUD.show(withStatus: status)
SVProgressHUD.setDefaultMaskType(.black)
}
@objc
private static func hudTapped(_ notification: Notification) {
SVProgressHUD.dismiss()
SVProgressHUD.setDefaultMaskType(.none)
dismissCompletion?()
}
@objc
private static func hudDisappeared(_ notification: Notification) {
dismissCompletion = nil
let notificationCenter = NotificationCenter.default
notificationCenter.removeObserver(self, name: NSNotification.Name.SVProgressHUDDidReceiveTouchEvent, object: nil)
notificationCenter.removeObserver(self, name: NSNotification.Name.SVProgressHUDWillDisappear, object: nil)
SVProgressHUD.setDefaultMaskType(.none)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.