3
\$\begingroup\$

I'm combining 2 UISliders made from scratch -- one horizontal and one vertical -- to make a single slider that controls 2 parameters. They are set up so that the vertical slider is perpendicular to the horizontal one. (Like a cross) The thumb knob can move both horizontally and vertically, and if it's moved horizontally, the vertical tracker will move left and right to follow the thumb.

I'm having trouble setting the boundaries of the thumb. Its leftmost limit is supposed to be reached when the left edge of the v. slider touches the left edge of the horizontal slider, and the rightmost limit is when the right edges of the sliders intersect. For the sake of consistency, I took whatever code I needed to obtain the previous conditions and used a similar structure for the top and bottom limits -- even though there is no actual intersection.

This is what I came up with. (This is in a custom UIView which holds both sliders. Also, the size of the UIView is 100 x 100, and the sliders are each 90 points long.)

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {   

CGPoint touchPoint = [touch locationInView:self];

CGFloat hLimitLeft = horizontalSliderFrame.origin.x + .5* ksliderThickness;
CGFloat hLimitRight = horizontalSliderFrame.origin.x + horizontalSliderFrame.size.width - .5* ksliderThickness;
CGFloat vLimitTop = verticalSliderFrame.origin.y + .5* ksliderThickness;
CGFloat vLimitBottom = verticalSliderFrame.origin.y +  verticalSliderFrame.size.height - .5* ksliderThickness;

CGRect thumbBoundaries = CGRectMake(hLimitLeft, vLimitTop, hLimitRight - hLimitLeft, vLimitBottom - vLimitTop) ;

if (CGRectContainsPoint(thumbBoundaries, touchPoint)) {


    self.thumb.center = CGPointMake(touchPoint.x, touchPoint.y);

    [self setNeedsDisplay];
    [self updateValues];


}

return YES;

}

Generally, it works fine. However, it doesn't move at the edges because the touch usually lies outside the boundaries even when it's holding on to the thumb knob.

I'm wondering if there's a better way to design this code.

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Once your control is active, just keep tracking until the touch ends, even if the touch moves outside of the view:

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchPoint = [touch locationInView:self];

    CGFloat hLimitLeft = horizontalSliderFrame.origin.x + .5* ksliderThickness;
    CGFloat hLimitRight = hLimitLeft + horizontalSliderFrame.size.width - ksliderThickness;
    CGFloat vLimitTop = verticalSliderFrame.origin.y + .5* ksliderThickness;
    CGFloat vLimitBottom = vLimitTop +  verticalSliderFrame.size.height - ksliderThickness;

    self.thumb.center.x = MAX(hLimitLeft, MIN(hLimitRight, touchPoint.x));
    self.thumb.center.y = MAX(vLimitTop, MIN(vLimitBottom, touchPoint.y));

    [self setNeedsDisplay];
    [self updateValues];

    return YES;
}

Note also that I changed the calculation of hLimitLeft and vLimitTop. I think this approach is clearer (in particular I missed the different signs on the .5 * ksliderThickness term the first couple of times through).

It's been a while since I've done iOS development, so there might be some minor mistakes, but this should get you going in the right direction.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.