Desmond
Desmond

Reputation: 5011

how to do dual circular slider (clock like function)

i will like to know how to do a dual slider in the attached image.

i am looking at this codes to modified it. i will like to know how to have 2 slider to allow user to choose the desired time.

The problem i encounter are how do i have 2 slider to show something like the image?

http://www.cocoacontrols.com/controls/tb_circularslider

any comment are greatly appreciated here.

enter image description here

Upvotes: 3

Views: 2448

Answers (1)

user207616
user207616

Reputation:

for the dual slider positions you have this excerpt in code

CGContextAddArc(imageCtx, self.frame.size.width/2  , self.frame.size.height/2, radius, 0, ToRad(self.angle), 0);

the first zero (0) is the starting point, so you want to use a different angle here

CGContextAddArc(imageCtx, self.frame.size.width/2  , self.frame.size.height/2, radius, ToRad(self.startAngle), ToRad(self.endAngle), 0);

(you need those two ivar's in your header of course)

EDIT: here is the edited code to find the nearest knob and lock it for modification. The old code didn't locked it, so it would change upon hover from one knob to another.
First of all add the enum above your implementation:

enum SliderLockType {
    SliderLockedNone = 0,
    SliderLockedStart,
    SliderLockedEnd
};

#pragma mark - Implementation -

@implementation TBCircularSlider
enum SliderLockType sliderLock;

// … some code here …
   //Initialize the Angle at 0
   //self.startAngle = 0;
   //self.endAngle = 270;

/** Tracking is started **/
-(BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
    [super beginTrackingWithTouch:touch withEvent:event];

    // find nearest knob …
    CGPoint lastPoint = [touch locationInView:self];
    CGPoint pStart = [self centerPointFromAngel:self.startAngle];
    CGPoint pEnd   = [self centerPointFromAngel:self.endAngle];
    float diffA = [self distanceBetween:lastPoint and:pStart];
    float diffB = [self distanceBetween:lastPoint and:pEnd];

    // … and lock it
    if (diffA <= TB_LINE_WIDTH) { // the tolerance is the width of the circle
        sliderLock = SliderLockedStart;
    } else if (diffB <= TB_LINE_WIDTH) {
        sliderLock = SliderLockedEnd;
    }

    //We need to track continuously
    return YES;
}

// continueTrackingWithTouch:withEvent: stays unchanged

/** Track is finished **/
-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
    [super endTrackingWithTouch:touch withEvent:event];

    // reset the lock before starting a new touch event
    sliderLock = SliderLockedNone;
}

- (CGPoint)centerPointFromAngel:(int)angleInt {
    CGPoint point = [self pointFromAngle:angleInt];
    point.x += TB_LINE_WIDTH/2;
    point.y += TB_LINE_WIDTH/2;
    return point;
}

- (CGFloat)distanceBetween:(CGPoint)p1 and:(CGPoint)p2 {
    CGFloat xDist = (p2.x - p1.x);
    CGFloat yDist = (p2.y - p1.y);
    return sqrt((xDist * xDist) + (yDist * yDist));
}

// … some more code …

- (void)drawTheHandle:(CGContextRef)ctx {

    CGContextSaveGState(ctx);

    //I Love shadows
    CGContextSetShadowWithColor(ctx, CGSizeMake(0, 0), 3, [UIColor blackColor].CGColor);

    //Get the handle position!
    CGPoint handleCenterA =  [self pointFromAngle: self.startAngle];
    CGPoint handleCenterB =  [self pointFromAngle: self.endAngle];

    //Draw It!
    [[UIColor colorWithWhite:1.0 alpha:0.7]set];
    CGContextFillEllipseInRect(ctx, CGRectMake(handleCenterA.x, handleCenterA.y, TB_LINE_WIDTH, TB_LINE_WIDTH));
    CGContextFillEllipseInRect(ctx, CGRectMake(handleCenterB.x, handleCenterB.y, TB_LINE_WIDTH, TB_LINE_WIDTH));

    CGContextRestoreGState(ctx);
}

- (void)movehandle:(CGPoint)lastPoint {

    //Get the center
    CGPoint centerPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);

    //Calculate the direction from the center point to an arbitrary position.
    float currentAngle = AngleFromNorth(centerPoint, lastPoint, NO);
    int angleInt = 360 - floor(currentAngle);

    if (sliderLock == SliderLockedStart) {
        self.startAngle = angleInt;
    } else if (sliderLock == SliderLockedEnd) {
        self.endAngle = angleInt;
    }

    //Redraw
    [self setNeedsDisplay];
}

the result:
modified TBCircularSlider Lib

EDIT2: if you like to have the slider switching from hour to hour you can modify the movehandle: method as follows:

int angleInt = (int)(360 - floor(currentAngle)) / 30 * 30; // 360/30 = 12 -> hours

if (sliderLock == SliderLockedStart && angleInt%360 != self.endAngle%360) {
    self.startAngle = angleInt;
} else if (sliderLock == SliderLockedEnd && angleInt%360 != self.startAngle%360) {
    self.endAngle = angleInt;
}

Upvotes: 7

Related Questions