Skip to content
This repository has been archived by the owner on Sep 11, 2022. It is now read-only.

Block front view "Push" button action while rear view is active. #7

Closed
sunglee opened this issue Jan 4, 2012 · 4 comments
Closed
Labels

Comments

@sunglee
Copy link

sunglee commented Jan 4, 2012

I am thinking when the rear view is revealed, the "Push!" button in the sample code should not push other view inside the hidden front view. I am expecting the behavior of the front view while the rear view is active is either of these:

  1. Only "Reveal" button in the front view should listen to the event
  2. or like the implementation of other app, i.e. Path, the whole area of hidden front view should be able to toggle.
@pkluz
Copy link
Owner

pkluz commented Jan 4, 2012

I consider this problem to be too specific for me to solve it for you. The rationale behind it is as follows: Not everyone might appreciate this kind of behavior in every situation. Take the iPad as an example. It wouldn't make sense to disable user interaction with the FrontView on a screen that big.

I agree with the iPhone though. It doesn't make sense to have the user still be able to hit buttons or similar on the front view (if say in portrait mode) seeing how the area of interaction is about 40 points wide. Give or take.

Thus I provide you with a protocol you can conform to. The ZUUIRevealControllerDelegate.

The usual approach would be no different from what you do when subclassing UITableViewController.

  1. Create a subclass:
    @interface MyRevealController : ZUUIRevealController <ZUUIRevealControllerDelegate>

  2. Assign the delegate to self.

  3. Implement one of these to control the interaction/flow:

    - (BOOL)revealController:(ZUUIRevealController*)revealController shouldRevealRearViewController:(UIViewController*)rearViewController;
    - (BOOL)revealController:(ZUUIRevealController*)revealController shouldHideRearViewController:(UIViewController*)rearViewController;
    - (void)revealController:(ZUUIRevealController*)revealController willRevealRearViewController:(UIViewController*)rearViewController;
    - (void)revealController:(ZUUIRevealController*)revealController didRevealRearViewController:(UIViewController*)rearViewController;
    - (void)revealController:(ZUUIRevealController*)revealController willHideRearViewController:(UIViewController*)rearViewController;
    - (void)revealController:(ZUUIRevealController*)revealController didHideRearViewController:(UIViewController*)rearViewController;
    

For example, in order to achieve your desired Path way, a quick and dirty solution would be:

- (void)revealController:(ZUUIRevealController *)revealController didRevealRearViewController:(UIViewController *)rearViewController
{
    UIView *touchIntercepterView = [[UIView alloc] initWithFrame:revealController.frontViewController.view.frame];
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:revealController action:@selector(revealToggle:)];
    [touchIntercepterView addGestureRecognizer:tapGestureRecognizer];
    [tapGestureRecognizer release];
    [revealController.frontViewController.view insertSubview:touchIntercepterView atIndex:INT_MAX];
    [touchIntercepterView release];
}

- (void)revealController:(ZUUIRevealController *)revealController didHideRearViewController:(UIViewController *)rearViewController
{
    NSArray *subviews = [revealController.frontViewController.view subviews];
    UIView *touchInterceptionView = [subviews lastObject];
    [touchInterceptionView removeFromSuperview];
}

Note: I don't recommend using the snippet above in production the way I just provided it. It makes my eyes bleed. That's just to show you how it can be done with the least amount of effort.

Nonetheless, everything you need to implement your custom behavior and device differentiation (iPhone <-> iPad) is available to you. You can even achieve a perfect recreation of the Facebook way by say,...swapping the "Back" button (if you popped a few things onto the navigation stack the "reveal" button disappears ,..obviously) with a "Reveal" button whenever didRevealRearViewController: is triggered and swapping it back once didHideRearViewController: occurred. Just some thoughts.

In the end it's up to you to make use of the barebones I provide.

Did that solve your issue or do you still think there should be something I should implement on my side? Please do elaborate I'm open to ideas :-)

@ghost
Copy link

ghost commented May 21, 2012

The facebook/path behavior is so entirely expected for the iphone that being able to manipulate the front view controller (by default) is nearly a bug. Subclassing and delegation should be required for the uncommon behavior, not the (95%? )expect one.

I know I know: "patches welcome" :P

@matthavener
Copy link

I added this to the touch interceptor view to more closely mimic facebook on the iPad, which allows you to drag the front view back into place in addition to tapping it.

    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:revealController action:@selector(revealGesture:)];
    [touchIntercepterView addGestureRecognizer:panGestureRecognizer];

@matthavener
Copy link

One other small issue, this method - (void)revealController:(ZUUIRevealController *)revealController didHideRearViewController:(UIViewController *)rearViewController can be called even when - (void)revealController:(ZUUIRevealController *)revealController didRevealRearViewController:(UIViewController *)rearViewController was never called. Essentially, you can start to reveal the rearViewController with a pan gesture on the NavBar, and then cancel it. This causes the nav bar to disappear since it is the top subview. Here's what I'm using now:

@interface RevealController()
@property (nonatomic, retain) UIView *touchIntercepterView;
@end

@implementation RevealController
@synthesize touchIntercepterView;

- (id)initWithFrontViewController:(UIViewController *)frontViewController rearViewController:(UIViewController *)rearViewController
{
    self = [super initWithFrontViewController:frontViewController rearViewController:rearViewController];
    if (self)
    {
        self.delegate = self;
    }
    return self;
}

- (void)revealController:(ZUUIRevealController *)revealController didRevealRearViewController:(UIViewController *)rearViewController
{
    if (self.touchIntercepterView) 
        return;
    self.touchIntercepterView = [[UIView alloc] initWithFrame:revealController.frontViewController.view.frame];
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:revealController action:@selector(revealToggle:)];
    [self.touchIntercepterView addGestureRecognizer:tapGestureRecognizer];
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:revealController action:@selector(revealGesture:)];
    [self.touchIntercepterView addGestureRecognizer:panGestureRecognizer];
    [revealController.frontViewController.view insertSubview:self.touchIntercepterView atIndex:INT_MAX];
}

- (void)revealController:(ZUUIRevealController *)revealController didHideRearViewController:(UIViewController *)rearViewController
{
    [self.touchIntercepterView removeFromSuperview];
    self.touchIntercepterView = nil;
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants