Question

I have a main view in my program with a draggable view in it. This view can be dragged around with pan gestures. Currently though it uses a lot of code which I want to put in a subclass to reduce complexity. (I eventually want to increase functionality by allowing the user to expand with view with further pan gestures. This means there will be lots more code clogging up my view controller if I can't sort this out first)

Is it possible to have the code for a gesture recogniser in the subclass of a class and still interact with views in the parent class.

This is the current code I am using to enable pan gesture in the parent class:

-(void)viewDidLoad {

    ...


   UIView * draggableView = [[UIView alloc]initWithFrame:CGRectMake(highlightedSectionXCoordinateStart, highlightedSectionYCoordinateStart, highlightedSectionWidth, highlightedSectionHeight)];
draggableView.backgroundColor = [UIColor colorWithRed:121.0/255.0 green:227.0/255.0 blue:16.0/255.0 alpha:0.5];
   draggableView.userInteractionEnabled = YES;

   [graphView addSubview:draggableView];

   UIPanGestureRecognizer * panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panWasRecognized:)];

   [draggableView addGestureRecognizer:panner];

}

- (void)panWasRecognized:(UIPanGestureRecognizer *)panner {

    UIView * draggedView = panner.view;
    CGPoint offset = [panner translationInView:draggedView.superview];
    CGPoint center = draggedView.center;

    // We want to make it so the square won't go past the axis on the left
    // If the centre plus the offset

    CGFloat xValue = center.x + offset.x;

    draggedView.center = CGPointMake(xValue, center.y);

    // Reset translation to zero so on the next `panWasRecognized:` message, the
    // translation will just be the additional movement of the touch since now.
    [panner setTranslation:CGPointZero inView:draggedView.superview];
}

(Thanks to Rob Mayoff for getting me this far)

I have now added a subclass of the view but can't figure out how or where I need to create the gesture recogniser as the view is now being created in the subclass and added to the parent class.

I really want the target for the gesture recogniser to be in this subclass but when I try to code it nothing happens.

I have tried putting all the code in the subclass and adding the pan gesture to the view but then I get a bad access crash when I try to drag it.

I am currently trying to use

[graphView addSubview:[[BDraggableView alloc] getDraggableView]];

To add it to the subview and then setting up the view (adding the pan gesture etc) in the function getDraggableView in the subclass

There must be a more straight forward way of doing this that I haven't conceptualised yet - I am still pretty new dealing with subclasses and so am still learning how they all fit together.

Thanks for any help you can give

Was it helpful?

Solution

I think I might of figured this one out.

In the parent class I created the child class variable:

BDraggableView * draggableViewSubClass;
draggableViewSubClass = [[BDraggableView alloc] initWithView:graphView andRangeChart:   [rangeSelector getRangeChart]];

This allowed me to initialise the child class with the view I wanted to have the draggable view on: graphView

Then in the child view I set up the pan gesture as I normally would but added it to this view carried through:

- (id)initWithView:(UIView *) view andRangeChart: (ShinobiChart *)chart {
    self = [super initWithNibName:nil   bundle:nil];
    if (self) {
        // Custom initialization
        parentView = view;

        [self setUpViewsAndPans];
    }
return self;
}

- (void)setUpViewsAndPans {

    draggableView = [[UIView alloc]initWithFrame:CGRectMake(highlightedSectionXCoordinateStart, highlightedSectionYCoordinateStart, highlightedSectionWidth, highlightedSectionHeight)];
    draggableView.backgroundColor = [UIColor colorWithRed:121.0/255.0 green:227.0/255.0 blue:16.0/255.0 alpha:0.5];
    draggableView.userInteractionEnabled = YES;

    // Add the newly made draggable view to our parent view
    [parentView addSubview:draggableView];
    [parentView bringSubviewToFront:draggableView];

    // Add the pan gesture
    UIPanGestureRecognizer * panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panWasRecognized:)];
    [draggableView addGestureRecognizer:panner];
}

- (void)panWasRecognized:(UIPanGestureRecognizer *)panner {

    UIView * draggedView = panner.view;
    CGPoint offset = [panner translationInView:draggedView.superview];
    CGPoint center = draggedView.center;

    CGFloat xValue = center.x + offset.x;

    draggedView.center = CGPointMake(xValue, center.y);

    // Reset translation to zero so on the next `panWasRecognized:` message, the
    // translation will just be the additional movement of the touch since now.
    [panner setTranslation:CGPointZero inView:draggedView.superview];
}

It took me a while to straighten it in my head that we want to do all the setting up in our subclass and then add this view with its characteristics to the parent view.

Thanks for all the answers provided they got me thinking along the right lines to solve it

OTHER TIPS

I think you want to subclass UIView and make your own DraggableView class. Here, you can add swipe and pan gesture recognizers. This would be in the implementation of a subclass of UIView

- (id)initWithFrame:(CGRect)frame
{
     if (self = [super initWithFrame:frame]) {
         UIGestureRecognizer *gestRec = [[UIGestureRecognizer alloc] initWithTarget:self 
                                                                             action:@selector(detectMyMotion:)];
         [self addGestureRecognizer:gestRec];
     }
     return self;
}

- (void)detectMyMotion:(UIGestureRecognizer *)gestRect
{
    NSLog(@"Gesture Recognized");
    // maybe even, if you wanted to alert your VC of a gesture...
    [self.delegate alertOfGesture:gestRect];
    // your VC would be alerted by delegation of this action.
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top