【问题标题】:Dismiss SVProgressHUD with Tap Gesture用点击手势关闭 SVProgressHUD
【发布时间】:2016-09-01 03:28:10
【问题描述】:

我需要将 UITapGestureRecognizer 添加到 SVProgressHUD。 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。我遇到了将其放置在几个地方并导致应用程序只有一次点击的问题。在这个过程中,我几乎把自己弄糊涂了。我应该

  • 将此手势添加到视图中?
  • 添加此手势以关闭?

【问题讨论】:

  • 仔细查看后,我找到了显示图像的代码。我实现了一些小的测试代码:if (self.imageView ) { self.dismiss; } 在实现了这个测试代码之后,HudImage 在显示出来后立即消失了。所以我现在的问题是,如何为 objec-c 中的手势编写 if 语句。我需要说,如果用户发起点击,请忽略这个?

标签: ios objective-c mobile uiviewcontroller svprogresshud


【解决方案1】:

基于 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)
  }

}

【讨论】:

  • 我不得不把 [SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeClear];在 showErrorWithStatus:.. 之后,它就像一个魅力。谢谢!
  • 这是最好的方法。首先我们可能需要把 SVProgressHUDMaskTypeClear... 如果我把 TypeNone 会发生什么?
【解决方案2】:

更新 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。

完成后使用它来移除 Observer(就像在 viewDidDisappear 中一样),否则它将在应用程序的整个生命周期中一直存在。

[[NSNotificationCenter defaultCenter] removeObserver:self name:SVProgressHUDDidReceiveTouchEventNotification object:nil];

信用:http://kevsaidwhat.blogspot.my/2013/06/cancel-svprogresshud-process-by-tapping.html

【讨论】:

  • 我无法更改有关dismiss方法的任何内容。它需要留在那里,否则所有 hudview 都将留在屏幕上。如果用户选择,我需要简单地添加点击屏幕以关闭 HUD 的功能。如何将 addTapToDismiss 附加到视图?
  • 您是否尝试过实现代码?这里的dismiss方法只是viewController类中的一个本地实例,它和SVProgressHUD的dismiss方法不是一个方法。它只是在点击屏幕时调用 SVProgressHUD 的关闭。我将编辑我的答案以包含一个选项
  • 如果我不清楚,我的建议不涉及修改原始 SVProgressHUD 库(包括您发布的驳回方法)。只需将 addTapToDismiss 添加到您的 viewController 类并在必要时调用它。
  • 看起来我在代码中有一些掩码类型。还有其他想法吗?我试图在我们拥有的 BaseVC.m 中实现代码,但它不起作用。还有其他想法吗?
  • 检查我的更新答案,建议修改库文件
【解决方案3】:

完整的快速实现有人可能会觉得它很有用。这是 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()
}

【讨论】:

    【解决方案4】:

    实现这一点的简单方法是:

    1. 创建一个关闭 HUD 的类:
    class HUDManager {
        @objc
        class func dismissHUD() {
            SVProgressHUD.dismiss()
        }
    }
    
    1. 订阅SVProgressHUDDidReceiveTouchEvent 通知:
    NotificationCenter.default.addObserver(HUDManager.self,
                                           selector: #selector(HUDManager.dismissHUD),
                                           name: .SVProgressHUDDidReceiveTouchEvent,
                                           object: nil)
    

    【讨论】:

      【解决方案5】:

      感谢@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)
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多