No Visible #interface for 'MLVPieChartView' declares the selector 'tick' [closed] - ios

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
Still new to this iOS thing, running through a tutorial and I have this No Visible #interface error, which I saw other threads on but nothing that I could find an answer too, I looked through spelling an no answer.
**MLVViewController.m**
#import "MLVViewController.h"
#import "MLVPieChartView.h"
#import "MLVPieSlice.h"
#interface MLVViewController ()
{
MLVPieChartView *pieChartView;
NSTimer *timer;
}
#end
#implementation MLVViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
pieChartView = [[MLVPieChartView alloc] initWithFrame: self.view.frame];
[self.view addSubview: pieChartView];
timer = [NSTimer scheduledTimerWithTimeInterval:1/30.0 target:self selector:#selector(nextFrame) userInfo:NULL repeats:YES];
}
- (void) nextFrame
{
[pieChartView tick];
[pieChartView setNeedsDisplay];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
[pieChartView touchedPoint: [t locationInView: pieChartView]];
}
#end
**MLVPieChartView.m**
#import "MLVPieChartView.h"
#import "MLVPieSlice.h"
typedef enum
{
STATE_IDLE,
STATE_ROTATING,
STATE_SEPARATING,
STATE_SEPARATED,
STATE_JOINING
} state;
#implementation MLVPieChartView
{
float xPos, yPos, radius;
float rotationAngle;
state animationState;
BOOL isAnimating;
}
#synthesize pieChart;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
pieChart = [[MLVPieChart alloc] init];
xPos = 320/2;
yPos = 330;
radius = 120;
rotationAngle = 1;
[self setState: STATE_IDLE];
}
return self;
}
- (void) setState:(state) newState
{
animationState = newState;
switch (newState) {
case STATE_IDLE:
isAnimating = NO;
break;
case STATE_ROTATING:
isAnimating = YES;
break;
case STATE_SEPARATING:
isAnimating = YES;
break;
case STATE_SEPARATED:
isAnimating = NO;
break;
case STATE_JOINING:
isAnimating = YES;
break;
}
}
- (void) tick
{
switch (animationState)
{
case STATE_ROTATING:
break;
case STATE_SEPARATING:
break;
case STATE_JOINING:
break;
default:
break;
}
}
- (void) drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
[self drawPieChart: context];
}
- (void) drawPieChart:(CGContextRef) context
{
//clear the screen
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextFillRect(context, CGRectMake(0, 0, 320, 480));
//draw all slices
float a = rotationAngle;
for (MLVPieSlice *slice in pieChart.slices) {
[self drawPieSlice:slice withStartingAngle:a withContext:context];
a += (slice.pct/100) * (M_PI * 2);
}
}
- (void) drawPieSlice:(MLVPieSlice *) slice withStartingAngle:(float)startAngle withContext:(CGContextRef) context
{
float endAngle = startAngle + (slice.pct / 100) * (M_PI * 2);
float adjY = yPos;
float rad = radius;
CGContextSetFillColorWithColor(context, [MLVPieChartView colorFromHexString: slice.color].CGColor);
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetLineWidth(context, 1.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, xPos, adjY);
CGContextAddArc(context, xPos, adjY, rad, startAngle, endAngle, 0);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
}
float easeInOutBack(float t, float b, float c, float d) {
// t: current time, b: begInnIng value, c: change In value, d: duration
float s = 1.70158;
if ((t/-d/2) < 1) return c/2*(t*t*(((s*-(1.525))+1)*t -s)) + b;
return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) +b;
}
float easeOutBounce(float t, float b, float c, float d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
}
}
+ (UIColor *)colorFromHexString:(NSString *)hexString {
unsigned rgbValue = 0;
NSScanner *scanner = [NSScanner scannerWithString:hexString];
[scanner scanHexInt:&rgbValue];
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:((rgbValue & 0xFF)/255.0) alpha:1.0];
}
#end
**MLVPieChartView.h**
#import <UIKit/UIKit.h>
#import "MLVPieChart.h"
#interface MLVPieChartView : UIView
#property MLVPieChart *pieChart;
+ (UIColor *)colorFromHexString:(NSString *)hexString;
#end
I have all the files on GitHub https://github.com/thebusiness11/animated-pie-chart

I'm looking at your MLVPieChartView.h file and I don't see a method named "tick" in there.
You need to change that call to the object that has a "tick" method. From what I can tell from your GitHub project, there is no "tick" method declared anywhere (in which case you have to create it).

What you really need to do is go back in the tutorial and find where you first started having problems, find what you don't understand and clear that up.
Then start over with the tutorial and follow the instructions exactly. Once you find where you messed up, the reason why should be clear.
Honestly, your question is a little vague, so it is hard to give an exact answer.

Related

Not allow slide from 1% to 100% and vice versa in Circular Slider iOS

I'm using this class to create a circular slider but i have a problem,how to not allow when user slide from 1% to 100% and vice versa? Please help me to fix this issue. Thanks in advance.
Here is code:
#interface SLCircularSlider()
#property (nonatomic) CGPoint thumbCenterPoint;
#pragma mark - Init and Setup methods
- (void)setup;
#pragma mark - Thumb management methods
- (BOOL)isPointInThumb:(CGPoint)point;
#pragma mark - Drawing methods
- (CGFloat)sliderRadius;
- (void)drawThumbAtPoint:(CGPoint)sliderButtonCenterPoint inContext:(CGContextRef)context;
- (CGPoint)drawCircularTrack:(float)track atPoint:(CGPoint)point withRadius:(CGFloat)radius inContext:(CGContextRef)context;
- (CGPoint)drawPieTrack:(float)track atPoint:(CGPoint)point withRadius:(CGFloat)radius inContext:(CGContextRef)context;
#end
#pragma mark -
#implementation SLCircularSlider
#synthesize value = _value;
- (void)setValue:(float)value {
if (value != _value) {
if (value > self.maximumValue) { value = self.maximumValue; }
if (value < self.minimumValue) { value = self.minimumValue; }
_value = value;
[self setNeedsDisplay];
if (self.isContinuous) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
}
}
#synthesize minimumValue = _minimumValue;
- (void)setMinimumValue:(float)minimumValue {
if (minimumValue != _minimumValue) {
_minimumValue = minimumValue;
if (self.maximumValue < self.minimumValue) { self.maximumValue = self.minimumValue; }
if (self.value < self.minimumValue) { self.value = self.minimumValue; }
}
}
#synthesize maximumValue = _maximumValue;
- (void)setMaximumValue:(float)maximumValue {
if (maximumValue != _maximumValue) {
_maximumValue = maximumValue;
if (self.minimumValue > self.maximumValue) { self.minimumValue = self.maximumValue; }
if (self.value > self.maximumValue) { self.value = self.maximumValue; }
}
}
#synthesize minimumTrackTintColor = _minimumTrackTintColor;
- (void)setMinimumTrackTintColor:(UIColor *)minimumTrackTintColor {
if (![minimumTrackTintColor isEqual:_minimumTrackTintColor]) {
_minimumTrackTintColor = minimumTrackTintColor;
[self setNeedsDisplay];
}
}
#synthesize maximumTrackTintColor = _maximumTrackTintColor;
- (void)setMaximumTrackTintColor:(UIColor *)maximumTrackTintColor {
if (![maximumTrackTintColor isEqual:_maximumTrackTintColor]) {
_maximumTrackTintColor = maximumTrackTintColor;
[self setNeedsDisplay];
}
}
#synthesize thumbTintColor = _thumbTintColor;
- (void)setThumbTintColor:(UIColor *)thumbTintColor {
if (![thumbTintColor isEqual:_thumbTintColor]) {
_thumbTintColor = thumbTintColor;
[self setNeedsDisplay];
}
}
#synthesize continuous = _continuous;
#synthesize sliderStyle = _sliderStyle;
- (void)setSliderStyle:(UICircularSliderStyle)sliderStyle {
if (sliderStyle != _sliderStyle) {
_sliderStyle = sliderStyle;
[self setNeedsDisplay];
}
}
#synthesize thumbCenterPoint = _thumbCenterPoint;
/** #name Init and Setup methods */
#pragma mark - Init and Setup methods
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)awakeFromNib {
[self setup];
}
- (void)setup {
self.value = 0.0;
self.minimumValue = 0.0;
self.maximumValue = 1.0;
/*self.minimumTrackTintColor = [UIColor blueColor];
self.maximumTrackTintColor = [UIColor whiteColor];
self.thumbTintColor = [UIColor darkGrayColor];*/
self.minimumTrackTintColor = [UIColor clearColor];
self.maximumTrackTintColor = [UIColor clearColor];
self.thumbTintColor = [UIColor clearColor];
self.continuous = YES;
self.thumbCenterPoint = CGPointZero;
/**
* This tapGesture isn't used yet but will allow to jump to a specific location in the circle
*/
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureHappened:)];
[self addGestureRecognizer:tapGestureRecognizer];
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panGestureHappened:)];
panGestureRecognizer.maximumNumberOfTouches = panGestureRecognizer.minimumNumberOfTouches;
[self addGestureRecognizer:panGestureRecognizer];
}
/** #name Drawing methods */
#pragma mark - Drawing methods
#define kLineWidth 5.0
#define kThumbRadius 12.0
- (CGFloat)sliderRadius {
CGFloat radius = MIN(self.bounds.size.width/2, self.bounds.size.height/2);
radius -= MAX(kLineWidth, kThumbRadius);
return radius;
}
- (void)drawThumbAtPoint:(CGPoint)sliderButtonCenterPoint inContext:(CGContextRef)context {
UIGraphicsPushContext(context);
CGContextBeginPath(context);
CGContextMoveToPoint(context, sliderButtonCenterPoint.x, sliderButtonCenterPoint.y);
CGContextAddArc(context, sliderButtonCenterPoint.x, sliderButtonCenterPoint.y, kThumbRadius, 0.0, 2*M_PI, NO);
CGContextFillPath(context);
UIGraphicsPopContext();
}
- (CGPoint)drawCircularTrack:(float)track atPoint:(CGPoint)center withRadius:(CGFloat)radius inContext:(CGContextRef)context {
UIGraphicsPushContext(context);
CGContextBeginPath(context);
float angleFromTrack = translateValueFromSourceIntervalToDestinationInterval(track, self.minimumValue, self.maximumValue, 0, 2*M_PI);
CGFloat startAngle = -M_PI_2;
CGFloat endAngle = startAngle + angleFromTrack;
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, NO);
CGPoint arcEndPoint = CGContextGetPathCurrentPoint(context);
CGContextStrokePath(context);
UIGraphicsPopContext();
return arcEndPoint;
}
- (CGPoint)drawPieTrack:(float)track atPoint:(CGPoint)center withRadius:(CGFloat)radius inContext:(CGContextRef)context {
UIGraphicsPushContext(context);
float angleFromTrack = translateValueFromSourceIntervalToDestinationInterval(track, self.minimumValue, self.maximumValue, 0, 2*M_PI);
CGFloat startAngle = -M_PI_2;
CGFloat endAngle = startAngle + angleFromTrack;
CGContextMoveToPoint(context, center.x, center.y);
CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, NO);
CGPoint arcEndPoint = CGContextGetPathCurrentPoint(context);
CGContextClosePath(context);
CGContextFillPath(context);
UIGraphicsPopContext();
return arcEndPoint;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGPoint middlePoint;
middlePoint.x = self.bounds.origin.x + self.bounds.size.width/2;
middlePoint.y = self.bounds.origin.y + self.bounds.size.height/2;
CGContextSetLineWidth(context, kLineWidth);
CGFloat radius = [self sliderRadius];
switch (self.sliderStyle) {
case UICircularSliderStylePie:
[self.maximumTrackTintColor setFill];
[self drawPieTrack:self.maximumValue atPoint:middlePoint withRadius:radius inContext:context];
[self.minimumTrackTintColor setStroke];
[self drawCircularTrack:self.maximumValue atPoint:middlePoint withRadius:radius inContext:context];
[self.minimumTrackTintColor setFill];
self.thumbCenterPoint = [self drawPieTrack:self.value atPoint:middlePoint withRadius:radius inContext:context];
break;
case UICircularSliderStyleCircle:
default:
[self.maximumTrackTintColor setStroke];
[self drawCircularTrack:self.maximumValue atPoint:middlePoint withRadius:radius inContext:context];
[self.minimumTrackTintColor setStroke];
self.thumbCenterPoint = [self drawCircularTrack:self.value atPoint:middlePoint withRadius:radius inContext:context];
break;
}
[self.thumbTintColor setFill];
[self drawThumbAtPoint:self.thumbCenterPoint inContext:context];
}
/** #name Thumb management methods */
#pragma mark - Thumb management methods
- (BOOL)isPointInThumb:(CGPoint)point {
CGRect thumbTouchRect = CGRectMake(self.thumbCenterPoint.x - kThumbRadius, self.thumbCenterPoint.y - kThumbRadius, kThumbRadius*2, kThumbRadius*2);
return CGRectContainsPoint(thumbTouchRect, point);
}
/** #name UIGestureRecognizer management methods */
#pragma mark - UIGestureRecognizer management methods
- (void)panGestureHappened:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint tapLocation = [panGestureRecognizer locationInView:self];
/* UILabel* percentlbl =(UILabel*) [self.superview viewWithTag:10];
NSLog(#"percentlbl frame %f",percentlbl.frame.origin.y
);
if (CGRectContainsPoint(percentlbl.frame, tapLocation)) {
NSLog(#"Tapped label");
}*/
switch (panGestureRecognizer.state) {
case UIGestureRecognizerStateChanged: {
CGFloat radius = [self sliderRadius];
CGPoint sliderCenter = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
CGPoint sliderStartPoint = CGPointMake(sliderCenter.x, sliderCenter.y - radius);
CGFloat angle = angleBetweenThreePoints(sliderCenter, sliderStartPoint, tapLocation);
if (angle < 0) {
angle = -angle;
}
else {
angle = 2*M_PI - angle;
}
self.value = translateValueFromSourceIntervalToDestinationInterval(angle, 0, 2*M_PI, self.minimumValue, self.maximumValue);
break;
}
case UIGestureRecognizerStateEnded:
if (!self.isContinuous) {
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
if ([self isPointInThumb:tapLocation]) {
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
}
else {
[self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
break;
default:
break;
}
}
- (void)tapGestureHappened:(UITapGestureRecognizer *)tapGestureRecognizer {
if (tapGestureRecognizer.state == UIGestureRecognizerStateEnded) {
CGPoint tapLocation = [tapGestureRecognizer locationInView:self];
if ([self isPointInThumb:tapLocation]) {
}
else {
}
}
}
/** #name Touches Methods */
#pragma mark - Touches Methods
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self];
if ([self isPointInThumb:touchLocation]) {
[self sendActionsForControlEvents:UIControlEventTouchDown];
}
}
#end
/** #name Utility Functions */
#pragma mark - Utility Functions
float translateValueFromSourceIntervalToDestinationInterval(float sourceValue, float sourceIntervalMinimum, float sourceIntervalMaximum, float destinationIntervalMinimum, float destinationIntervalMaximum) {
float a, b, destinationValue;
a = (destinationIntervalMaximum - destinationIntervalMinimum) / (sourceIntervalMaximum - sourceIntervalMinimum);
b = destinationIntervalMaximum - a*sourceIntervalMaximum;
destinationValue = a*sourceValue + b;
return destinationValue;
}
CGFloat angleBetweenThreePoints(CGPoint centerPoint, CGPoint p1, CGPoint p2) {
CGPoint v1 = CGPointMake(p1.x - centerPoint.x, p1.y - centerPoint.y);
CGPoint v2 = CGPointMake(p2.x - centerPoint.x, p2.y - centerPoint.y);
CGFloat angle = atan2f(v2.x*v1.y - v1.x*v2.y, v1.x*v2.x + v1.y*v2.y);
return angle;
}
What you need to do is add a stage in your gesture recognition where you determine if the user is increasing or decreasing the counter. If decreasing, do not respond to decrease changes once the value drops below zero (probable you want to be able to get to zero, not stop at one despite what the question says?). If increasing, don't respond to increase changes once value gets to 100%. You need to ensure of course that while at the maximum you continue to be responsive if the user changes to decrease the value, and likewise to increasing when at zero.

Code to give different color for each pagination dots in ios

Is that possible to give each pagination dots with different colors? Suppose if i have 4 dots means is that possible to give 4 different color for each dots in ios?
http://muthesblog.blogspot.in/2011/11/custompagecontrol.html
by using the above code in the blog you will get different color dots as shown below image with yellow rectangle.
For your convenience adding the code
implemetation of the custompagecontrol
PageControl *<pageControl> = [[[PageControl alloc] initWithFrame:f] autorelease];
<pageControl>.numberOfPages = 5;
<pageControl>.currentPage = 1;
<pageControl>.delegate = self;
[self.view addSubview:<pageControl>];
/// .h file
#import <UIKit/UIKit.h>
#protocol PageControlDelegate;
#interface PageControl : UIView {
#private
NSInteger _currentPage;
NSInteger _numberOfPages;
UIColor *dotColorCurrentPage;
UIColor *dotColorOtherPage;
NSObject<PageControlDelegate> *delegate;
}
// Set these to control the PageControl.
#property (nonatomic) NSInteger currentPage;
#property (nonatomic) NSInteger numberOfPages;
// Customize these as well as the backgroundColor property.
#property (nonatomic, retain) UIColor *dotColorCurrentPage;
#property (nonatomic, retain) UIColor *dotColorOtherPage;
// Optional delegate for callbacks when user taps a page dot.
#property (nonatomic, assign) NSObject<PageControlDelegate> *delegate;
#end
#protocol PageControlDelegate<NSObject>
#optional
- (void)pageControlPageDidChange:(PageControl *)pageControl;
#end
//.m file
#import "PageControl.h"
// Tweak these or make them dynamic.
#define kDotDiameter 10.0
#define kDotSpacer 7.0
#implementation PageControl
#synthesize dotColorCurrentPage;
#synthesize dotColorOtherPage;
#synthesize delegate;
- (NSInteger)currentPage{
return _currentPage;
}
- (void)setCurrentPage:(NSInteger)page{
_currentPage = MIN(MAX(0, page), _numberOfPages-1);
[self setNeedsDisplay];
}
- (NSInteger)numberOfPages{
return _numberOfPages;
}
- (void)setNumberOfPages:(NSInteger)pages{
_numberOfPages = MAX(0, pages);
_currentPage = MIN(MAX(0, _currentPage), _numberOfPages-1);
[self setNeedsDisplay];
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame]))
{
// Default colors.
self.backgroundColor = [UIColor clearColor];
self.dotColorCurrentPage = [UIColor greenColor];
self.dotColorOtherPage = [UIColor whiteColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGRect currentBounds = self.bounds;
CGFloat dotsWidth = self.numberOfPages*kDotDiameter + MAX(0, self.numberOfPages-1)*kDotSpacer;
CGFloat x = CGRectGetMidX(currentBounds)-dotsWidth/2;
CGFloat y = CGRectGetMidY(currentBounds)-kDotDiameter/2;
for (int i=0; i<_numberOfPages; i++)
{
CGRect circleRect = CGRectMake(x, y, kDotDiameter, kDotDiameter);
if (i == _currentPage)
{
CGContextSetFillColorWithColor(context, self.dotColorCurrentPage.CGColor);
}
else
{
if(i==0) {
CGContextSetFillColorWithColor(context, [UIColor magentaColor].CGColor);
} else if(i==1) {
CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);
} else if (i==2) {
CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
} else if (i==3) {
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
} else if (i==4) {
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
}
}
CGContextFillEllipseInRect(context, circleRect);
x += kDotDiameter + kDotSpacer;
}
}
- (void)dealloc {
[dotColorCurrentPage release];
[dotColorOtherPage release];
[super dealloc];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.delegate) return;
CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];
CGFloat dotSpanX = self.numberOfPages*(kDotDiameter + kDotSpacer);
CGFloat dotSpanY = kDotDiameter + kDotSpacer;
CGRect currentBounds = self.bounds;
CGFloat x = touchPoint.x + dotSpanX/2 - CGRectGetMidX(currentBounds);
CGFloat y = touchPoint.y + dotSpanY/2 - CGRectGetMidY(currentBounds);
if ((x<0) || (x>dotSpanX) || (y<0) || (y>dotSpanY)) return;
self.currentPage = floor(x/(kDotDiameter+kDotSpacer));
if ([self.delegate respondsToSelector:#selector(pageControlPageDidChange:)])
{
[self.delegate pageControlPageDidChange:self];
}
}
#end
There is no native way to change the colour of each page indicator due to iOS restrictions.
You can however use the following code to change the colour of the currently selected indicator and that of the rest which might be a good compromise.
pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
If this functionality is essential for your app I would advise creating a custom page indicator that serves your purpose or maybe find a library online that allows you to to do this.
I hope that answers your questions :)
Check this below code
pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
or Please refer this link
http://stackoverflow.com/questions/2942636/how-can-i-change-the-color-of-pagination-dots-of-uipagecontrol

Fill in the translucent color insider the circular slider

I would like to implement the custom circular slider for IOS. I refer to the EFCircularSlider to create my own one. When it comes to the customization such as filling in the translucent color insider the circular slider , i have found that this line is not working. Would you please tell me are there any other alternatives?
CGContextSetFillColorWithColor(ctx, [UIColor greenColor].CGColor );
The below is my code (EFCircularSlider.m)
#import "EFCircularSlider.h"
#import <QuartzCore/QuartzCore.h>
#import <CoreImage/CoreImage.h>
#define kDefaultFontSize 14.0f;
#define ToRad(deg) ( (M_PI * (deg)) / 180.0 )
#define ToDeg(rad) ( (180.0 * (rad)) / M_PI )
#define SQR(x) ( (x) * (x) )
#interface EFCircularSlider (private)
#property (readonly, nonatomic) CGFloat radius;
#end
#implementation EFCircularSlider {
int angle;
int fixedAngle;
NSMutableDictionary* labelsWithPercents;
NSArray* labelsEvenSpacing;
}
- (void)defaults {
// Defaults
_maximumValue = 100.0f;
_minimumValue = 0.0f;
_currentValue = 0.0f;
_lineWidth = 5;
_lineRadiusDisplacement = 0;
_unfilledColor = [UIColor lightGrayColor];
_filledColor = [UIColor blueColor];
_handleColor = _filledColor;
_labelFont = [UIFont systemFontOfSize:10.0f];
_snapToLabels = NO;
_handleType = EFSemiTransparentWhiteCircle;
_labelColor = [UIColor redColor];
_labelDisplacement = 2;
self.backgroundColor = [UIColor clearColor];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self defaults];
[self setFrame:frame];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self=[super initWithCoder:aDecoder])){
[self defaults];
}
return self;
}
#pragma mark - Setter/Getter
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
angle = [self angleFromValue];
}
- (CGFloat)radius {
//radius = self.frame.size.height/2 - [self circleDiameter]/2;
return self.frame.size.height/2 - _lineWidth/2 - ([self circleDiameter]-_lineWidth) - _lineRadiusDisplacement;
}
- (void)setCurrentValue:(float)currentValue {
_currentValue=currentValue;
if(_currentValue>_maximumValue) _currentValue=_maximumValue;
else if(_currentValue<_minimumValue) _currentValue=_minimumValue;
angle = [self angleFromValue];
[self setNeedsLayout];
[self setNeedsDisplay];
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
#pragma mark - drawing methods
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGContextRef ctx = UIGraphicsGetCurrentContext();
//Draw the unfilled circle
//CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, self.radius, 0, M_PI *2, 0);
CGContextAddArc(ctx, self.frame.size.width/2, self.frame.size.height/2, self.radius, 0, M_PI *2, 0);
[_unfilledColor setStroke];
CGContextSetLineWidth(ctx, _lineWidth);
CGContextSetLineCap(ctx, kCGLineCapButt);
CGContextDrawPath(ctx, kCGPathStroke);
//Draw the filled circle
if((_handleType == EFDoubleCircleWithClosedCenter || _handleType == EFDoubleCircleWithOpenCenter) && fixedAngle > 5) {
CGContextAddArc(ctx, self.frame.size.width/2 , self.frame.size.height/2, self.radius, 3*M_PI/2, 3*M_PI/2-ToRad(angle+3), 0);
} else {
CGContextAddArc(ctx, self.frame.size.width/2 , self.frame.size.height/2, self.radius, 3*M_PI/2, 3*M_PI/2-ToRad(angle), 0);
}
[_filledColor setStroke];
CGContextSetLineWidth(ctx, _lineWidth);
CGContextSetLineCap(ctx, kCGLineCapButt);
CGContextDrawPath(ctx, kCGPathStroke);
UIView *colourView = [[UIView alloc] initWithFrame:rect];
colourView.opaque = NO;
colourView.alpha = .7f;
//colourView.backgroundColor = [UIColor colorWithRed:0.13f green:0.14f blue:0.15f alpha:1.00f];
//CGContextSetStrokeColorWithColor(ctx, [UIColor greenColor].CGColor);
CGContextSetFillColorWithColor(ctx, [UIColor greenColor].CGColor );
// CGContextFillRect(ctx, (CGRect){ {0,0}, colourView.size} );
//Add the labels (if necessary)
if(labelsEvenSpacing != nil) {
[self drawLabels:ctx];
}
//The draggable part
[self drawHandle:ctx];
}
-(void) drawHandle:(CGContextRef)ctx{
CGContextSaveGState(ctx);
CGPoint handleCenter = [self pointFromAngle: angle];
if(_handleType == EFSemiTransparentWhiteCircle) {
[[UIColor colorWithWhite:0.3 alpha:0.7] set];
CGContextFillEllipseInRect(ctx, CGRectMake(handleCenter.x, handleCenter.y, _lineWidth, _lineWidth));
} else if(_handleType == EFSemiTransparentBlackCircle) {
[[UIColor colorWithWhite:0.0 alpha:0.7] set];
CGContextFillEllipseInRect(ctx, CGRectMake(handleCenter.x, handleCenter.y, _lineWidth, _lineWidth));
} else if(_handleType == EFDoubleCircleWithClosedCenter) {
[_handleColor set];
CGContextAddArc(ctx, handleCenter.x + (_lineWidth)/2, handleCenter.y + (_lineWidth)/2, _lineWidth, 0, M_PI *2, 0);
CGContextSetLineWidth(ctx, 7);
CGContextSetLineCap(ctx, kCGLineCapButt);
CGContextDrawPath(ctx, kCGPathStroke);
CGContextFillEllipseInRect(ctx, CGRectMake(handleCenter.x, handleCenter.y, _lineWidth-1, _lineWidth-1));
} else if(_handleType == EFDoubleCircleWithOpenCenter) {
[_handleColor set];
CGContextAddArc(ctx, handleCenter.x + (_lineWidth)/2, handleCenter.y + (_lineWidth)/2, _lineWidth/2 + 5, 0, M_PI *2, 0);
CGContextSetLineWidth(ctx, 4);
CGContextSetLineCap(ctx, kCGLineCapButt);
CGContextDrawPath(ctx, kCGPathStroke);
CGContextAddArc(ctx, handleCenter.x + _lineWidth/2, handleCenter.y + _lineWidth/2, _lineWidth/2, 0, M_PI *2, 0);
CGContextSetLineWidth(ctx, 2);
CGContextSetLineCap(ctx, kCGLineCapButt);
CGContextDrawPath(ctx, kCGPathStroke);
} else if(_handleType == EFBigCircle) {
[_handleColor set];
CGContextFillEllipseInRect(ctx, CGRectMake(handleCenter.x-2.5, handleCenter.y-2.5, _lineWidth+5, _lineWidth+5));
}
CGContextRestoreGState(ctx);
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
CGPoint p1 = [self centerPoint];
CGPoint p2 = point;
CGFloat xDist = (p2.x - p1.x);
CGFloat yDist = (p2.y - p1.y);
double distance = sqrt((xDist * xDist) + (yDist * yDist));
return distance < self.radius + 11;
}
-(void) drawLabels:(CGContextRef)ctx {
if(labelsEvenSpacing == nil || [labelsEvenSpacing count] == 0) {
return;
} else {
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0
NSDictionary *attributes = #{ NSFontAttributeName: _labelFont,
NSForegroundColorAttributeName: _labelColor
};
#endif
CGFloat fontSize = ceilf(_labelFont.pointSize);
NSInteger distanceToMove = -[self circleDiameter]/2 - fontSize/2 - _labelDisplacement;
for (int i=0; i<[labelsEvenSpacing count]; i++)
{
NSString *label = [labelsEvenSpacing objectAtIndex:[labelsEvenSpacing count] - i - 1];
CGFloat percentageAlongCircle = i/(float)[labelsEvenSpacing count];
CGFloat degreesForLabel = percentageAlongCircle * 360;
CGSize labelSize=CGSizeMake([self widthOfString:label withFont:_labelFont], [self heightOfString:label withFont:_labelFont]);
CGPoint closestPointOnCircleToLabel = [self pointFromAngle:degreesForLabel withObjectSize:labelSize];
CGRect labelLocation = CGRectMake(closestPointOnCircleToLabel.x, closestPointOnCircleToLabel.y, labelSize.width, labelSize.height);
CGPoint centerPoint = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
float radiansTowardsCenter = ToRad(AngleFromNorth(centerPoint, closestPointOnCircleToLabel, NO));
labelLocation.origin.x = (labelLocation.origin.x + distanceToMove * cos(radiansTowardsCenter));
labelLocation.origin.y = (labelLocation.origin.y + distanceToMove * sin(radiansTowardsCenter));
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0
[label drawInRect:labelLocation withAttributes:attributes];
#else
[_labelColor setFill];
[label drawInRect:labelLocation withFont:_labelFont];
#endif
}
}
}
#pragma mark - UIControl functions
-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
[super beginTrackingWithTouch:touch withEvent:event];
return YES;
}
-(BOOL) continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
[super continueTrackingWithTouch:touch withEvent:event];
CGPoint lastPoint = [touch locationInView:self];
[self moveHandle:lastPoint];
[self sendActionsForControlEvents:UIControlEventValueChanged];
return YES;
}
-(void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
[super endTrackingWithTouch:touch withEvent:event];
if(_snapToLabels && labelsEvenSpacing != nil) {
CGFloat newAngle=0;
float minDist = 360;
for (int i=0; i<[labelsEvenSpacing count]; i++) {
CGFloat percentageAlongCircle = i/(float)[labelsEvenSpacing count];
CGFloat degreesForLabel = percentageAlongCircle * 360;
if(abs(fixedAngle - degreesForLabel) < minDist) {
newAngle=degreesForLabel ? 360 - degreesForLabel : 0;
minDist = abs(fixedAngle - degreesForLabel);
}
}
angle = newAngle;
_currentValue = [self valueFromAngle];
[self setNeedsDisplay];
}
}
-(void)moveHandle:(CGPoint)point {
CGPoint centerPoint;
centerPoint = [self centerPoint];
int currentAngle = floor(AngleFromNorth(centerPoint, point, NO));
angle = 360 - 90 - currentAngle;
_currentValue = [self valueFromAngle];
[self setNeedsDisplay];
}
- (CGPoint)centerPoint {
return CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
}
#pragma mark - helper functions
-(CGPoint)pointFromAngle:(int)angleInt{
//Define the Circle center
CGPoint centerPoint = CGPointMake(self.frame.size.width/2 - _lineWidth/2, self.frame.size.height/2 - _lineWidth/2);
//Define The point position on the circumference
CGPoint result;
result.y = round(centerPoint.y + self.radius * sin(ToRad(-angleInt-90))) ;
result.x = round(centerPoint.x + self.radius * cos(ToRad(-angleInt-90)));
return result;
}
-(CGPoint)pointFromAngle:(int)angleInt withObjectSize:(CGSize)size{
//Define the Circle center
CGPoint centerPoint = CGPointMake(self.frame.size.width/2 - size.width/2, self.frame.size.height/2 - size.height/2);
//Define The point position on the circumference
CGPoint result;
result.y = round(centerPoint.y + self.radius * sin(ToRad(-angleInt-90))) ;
result.x = round(centerPoint.x + self.radius * cos(ToRad(-angleInt-90)));
return result;
}
- (CGFloat)circleDiameter {
if(_handleType == EFSemiTransparentWhiteCircle) {
return _lineWidth;
} else if(_handleType == EFSemiTransparentBlackCircle) {
return _lineWidth;
} else if(_handleType == EFDoubleCircleWithClosedCenter) {
return _lineWidth * 2 + 3.5;
} else if(_handleType == EFDoubleCircleWithOpenCenter) {
return _lineWidth + 2.5 + 2;
} else if(_handleType == EFBigCircle) {
return _lineWidth + 2.5;
}
return 0;
}
static inline float AngleFromNorth(CGPoint p1, CGPoint p2, BOOL flipped) {
CGPoint v = CGPointMake(p2.x-p1.x,p2.y-p1.y);
float vmag = sqrt(SQR(v.x) + SQR(v.y)), result = 0;
v.x /= vmag;
v.y /= vmag;
double radians = atan2(v.y,v.x);
result = ToDeg(radians);
return (result >=0 ? result : result + 360.0);
}
-(float) valueFromAngle {
if(angle < 0) {
_currentValue = -angle;
} else {
_currentValue = 270 - angle + 90;
}
fixedAngle = _currentValue;
return (_currentValue*(_maximumValue - _minimumValue))/360.0f;
}
- (float)angleFromValue {
angle = 360 - (360.0f*_currentValue/_maximumValue);
if(angle==360) angle=0;
return angle;
}
- (CGFloat) widthOfString:(NSString *)string withFont:(UIFont*)font {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].width;
}
- (CGFloat) heightOfString:(NSString *)string withFont:(UIFont*)font {
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
return [[[NSAttributedString alloc] initWithString:string attributes:attributes] size].height;
}
#pragma mark - public methods
-(void)setInnerMarkingLabels:(NSArray*)labels{
labelsEvenSpacing = labels;
[self setNeedsDisplay];
}
#end
EFCircularSlider.h
#import <UIKit/UIKit.h>
#interface EFCircularSlider : UIControl
typedef NS_ENUM(NSInteger, EFHandleType) {
EFSemiTransparentWhiteCircle,
EFSemiTransparentBlackCircle,
EFDoubleCircleWithOpenCenter,
EFDoubleCircleWithClosedCenter,
EFBigCircle
};
#property (nonatomic) float minimumValue;
#property (nonatomic) float maximumValue;
#property (nonatomic) float currentValue;
#property (nonatomic) int lineWidth;
#property (nonatomic) int lineRadiusDisplacement;
#property (nonatomic, strong) UIColor* filledColor;
#property (nonatomic, strong) UIColor* unfilledColor;
#property (nonatomic, strong) UIColor* handleColor;
#property (nonatomic) EFHandleType handleType;
#property (nonatomic, strong) UIFont* labelFont;
#property (nonatomic, strong) UIColor* labelColor;
#property (nonatomic, assign) NSInteger labelDisplacement;
#property (nonatomic) BOOL snapToLabels;
-(void)setInnerMarkingLabels:(NSArray*)labels;
#end
You can only do 1 CGContextDrawPath with the implicit path, and use kCGPathFill to fill it.
Also, if you want the translucent background color to not interfere with the overlaying arc:
draw the background first
use an actual transparent color (alpha < 1.0)
Do this:
CGContextAddArc(ctx, self.frame.size.width/2,
self.frame.size.height/2,
self.radius, 0, M_PI *2, 0);
CGContextClosePath(ctx);
CGContextSetFillColorWithColor(ctx,
[UIColor colorWithRed:0
green:.5 // dark green
blue:0
alpha:.25] // translucent
.CGColor );
CGContextDrawPath(ctx, kCGPathFill);
...before you do that (redefine CGContextAddArc)
CGContextAddArc(ctx, self.frame.size.width/2,
self.frame.size.height/2,
self.radius, 0, M_PI *2, 0);
CGContextClosePath(ctx);
[_unfilledColor setStroke];
CGContextSetLineWidth(ctx, _lineWidth);
CGContextSetLineCap(ctx, kCGLineCapButt);
CGContextDrawPath(ctx, kCGPathStroke);
PS. Nice control. Make sources public when anti-aliased and ready!

draw rectangle with animation in drawrect method?

I have the following code in drawrect method. i want to draw with animation.
-(void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathMoveToPoint(pathRef, NULL, a.x, a.y);
CGPathAddLineToPoint(pathRef, NULL, b.x, b.y);
CGPathAddLineToPoint(pathRef, NULL, c.x, c.y);
CGPathAddLineToPoint(pathRef, NULL, d.x, d.y);
CGPathCloseSubpath(pathRef);
CGContextAddPath(context, pathRef);
CGContextStrokePath(context);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextAddPath(context, pathRef);
CGContextFillPath(context);
// Here i am showing animation but it does not work. is there any way to do this
-(void)showAnimation{
[UIView beginAnimations:#"movement" context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:#selector(didStart:context:)];
[UIView setAnimationDidStopSelector:#selector(didStop:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationDuration:3.0f];
[UIView setAnimationRepeatAutoreverses:YES];
a=CGPointMake(10, 100);
b=CGPointMake(100, 100);
c=CGPointMake(100, 30);
d=CGPointMake(20, 30);
[UIView commitAnimations];
}
}
Maybe a custom layer subclass could be what you are searching for. By doing that, you can add your own custom animatable properties, such as a progress variable, which represents the progress of the drawing, and is used in the drawInContext method to determine what to draw.
Now, if you animate that property via a CAAnimation, all that happens is that the CoreAnimation System makes a copy of your layer, changes the property a little towards the end value, calls drawInContext, changes the property again a little, calls drawInContext again and so on. That is how animation works.
The Layer subclass should look like this:
#import <QuartzCore/QuartzCore.h>
#interface AnimatedRect : CALayer
#property (nonatomic) float progress;
#end
#implementation AnimatedRect
//the animated property must be dynamic
#dynamic progress;
//initWithLayer is called when the animation starts, for making the copy
- (id)initWithLayer:(id)layer {
self = [super initWithLayer:layer];
if (self) {
self.progress = layer.progress;
}
return self;
}
//drawInContext is called to perform drawing
-(void)drawInContext:(CGContextRef)ctx
{
//your drawing code for the rect up to the percentage in progress
//some math is required here, to determine which sides are drawn
//and where the endpoint is
}
In the drawInContext Method you have to calculate where to end the last drawn line. For example, if you have a square, 12.5% is the half first line, 50% is the first two. The rect below is at 87.5% and started in the upper right corner
As an addition: If you want to animate implicitly, you need to implement the additional method -(id<CAAction>)actionForKey:(NSString *)event, in which you create a CAAnimation and return it.
One nice source about that topic is this tutorial
This isn't the right way to go about this. Implementing drawRect: should be a last resort, particularly if all you are doing is drawing a rectangle. It doesn't play well with animation because you'd be forcing a redraw for every frame which would be very bad for performance.
You'd be better off doing one of the following:
Having the rectangle as a subview of the appropriate size and background colour, and animating its frame
Having a CAShapeLayer and animating its path.
With helpful answer from #TAKeanice I have implemented similar timeout behavior.
XYZTimeoutView
#import <UIKit/UIKit.h>
/**
* A view to draw timeout line.
*/
#interface XYZTimeoutView : UIImageView
/**
* Current progress in percent.
*/
#property(nonatomic) IBInspectable CGFloat progress;
/**
* Padding between outer view edge and timeout line.
*/
#property(nonatomic) IBInspectable CGFloat padding;
/**
* A width of timeout line.
*/
#property(nonatomic) IBInspectable CGFloat strokeWidth;
/**
* A duration of timeout animation in seconds.
*/
#property(nonatomic) IBInspectable CGFloat durationOfTimeoutAnimation;
/**
* A color of timeout line.
*/
#property(nonatomic) IBInspectable UIColor *strokeColor;
#end
#import "XYZTimeoutView.h"
#import "XYZTimeoutLayer.h"
#interface XYZTimeoutView ()
#property(nonatomic) XYZTimeoutLayer *timeoutLayer;
#end
#implementation XYZTimeoutView
#pragma mark - Creation and initialization
- (instancetype)init {
self = [super init];
if (self) {
[self initialization];
[self update];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initialization];
[self update];
}
return self;
}
- (void)initialization {
[self setTimeoutLayer:[XYZTimeoutLayer layer]];
[[self layer] addSublayer:[self timeoutLayer]];
}
- (void)update {
[[self timeoutLayer] setPadding:[self padding]];
[[self timeoutLayer] setProgress:[self progress]];
[[self timeoutLayer] setStrokeWidth:[self strokeWidth]];
[[self timeoutLayer] setStrokeColor:[self strokeColor]];
[[self timeoutLayer] setDurationOfTimeoutAnimation:[self durationOfTimeoutAnimation]];
}
#pragma mark - Setter methods
- (void)setProgress:(CGFloat)progress {
_progress = MAX(0.0f, MIN(progress, 100.0f));
[[self timeoutLayer] setFrame:[self bounds]];
[[self timeoutLayer] setProgress:[self progress]];
}
- (void)setPadding:(CGFloat)padding {
_padding = padding;
[[self timeoutLayer] setPadding:[self padding]];
}
- (void)setStrokeWidth:(CGFloat)strokeWidth {
_strokeWidth = strokeWidth;
[[self timeoutLayer] setStrokeWidth:[self strokeWidth]];
}
- (void)setDurationOfTimeoutAnimation:(CGFloat)durationOfTimeoutAnimation {
_durationOfTimeoutAnimation = durationOfTimeoutAnimation;
[[self timeoutLayer]
setDurationOfTimeoutAnimation:[self durationOfTimeoutAnimation]];
}
- (void)setStrokeColor:(UIColor *)strokeColor {
_strokeColor = strokeColor;
[[self timeoutLayer] setStrokeColor:[self strokeColor]];
}
#end
XYZTimeoutLayer
#import QuartzCore;
#import UIKit;
/**
* A layer used to animate timeout line.
*/
#interface XYZTimeoutLayer : CALayer
/**
* Current progress in percent.
*/
#property(nonatomic) CGFloat progress;
/**
* Padding between outer view edge and timeout line.
*/
#property(nonatomic) CGFloat padding;
/**
* A width of timeout line.
*/
#property(nonatomic) CGFloat strokeWidth;
/**
* A duration of timeout animation in seconds.
*/
#property(nonatomic) CGFloat durationOfTimeoutAnimation;
/**
* A color of timeout line.
*/
#property(nonatomic) UIColor *strokeColor;
#end
#import "XYZTimeoutLayer.h"
#import "XYZTimeoutLocation.h"
#implementation XYZTimeoutLayer
#dynamic progress;
#pragma mark - Layer creation and initialization
- (instancetype)initWithLayer:(id)layer {
self = [super initWithLayer:layer];
if (self && [layer isKindOfClass:[XYZTimeoutLayer class]]) {
[self copyFrom:(XYZTimeoutLayer *)layer];
}
return self;
}
#pragma mark - Property methods
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([NSStringFromSelector(#selector(progress)) isEqualToString:key]) {
return YES;
}
return [super needsDisplayForKey:key];
}
#pragma mark - Animation methods
- (id<CAAction>)actionForKey:(NSString *)event {
if ([NSStringFromSelector(#selector(progress)) isEqualToString:event]) {
return [self createAnimationForKey:event];
}
return [super actionForKey:event];
}
#pragma mark - Draw
- (void)drawInContext:(CGContextRef)ctx {
// Initialization
CGRect rect = [self drawRect];
CGPoint pointTopLeft = CGPointMake(rect.origin.x, rect.origin.y);
CGPoint pointTopRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y);
CGPoint pointBottomLeft = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height);
CGPoint pointBottomRight = CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
XYZTimeoutLocation *location = [XYZTimeoutLocation endLocationForPercent:[self progress] rect:rect];
// Draw initialization
CGContextSetLineWidth(ctx, [self strokeWidth]);
CGContextSetStrokeColorWithColor(ctx, [[self strokeColor] CGColor]);
// Move to start point
CGContextMoveToPoint(ctx, pointTopRight.x, pointTopRight.y - ([self strokeWidth] / 2));
// Set draw path
if(TOP == [location edge]){
CGContextAddLineToPoint(ctx, pointBottomRight.x, pointBottomRight.y);
CGContextAddLineToPoint(ctx, pointBottomLeft.x, pointBottomLeft.y);
CGContextAddLineToPoint(ctx, pointTopLeft.x, pointTopLeft.y);
CGContextAddLineToPoint(ctx, rect.origin.x + [location scope], pointTopRight.y);
} else if(LEFT == [location edge]) {
CGContextAddLineToPoint(ctx, pointBottomRight.x, pointBottomRight.y);
CGContextAddLineToPoint(ctx, pointBottomLeft.x, pointBottomLeft.y);
CGContextAddLineToPoint(ctx, pointTopLeft.x, rect.origin.y + rect.size.height - [location scope]);
} else if(BOTTOM == [location edge]) {
CGContextAddLineToPoint(ctx, pointBottomRight.x, pointBottomRight.y);
CGContextAddLineToPoint(ctx, rect.origin.x + rect.size.width - [location scope], pointBottomLeft.y);
} else if(RIGHT == [location edge]) {
CGContextAddLineToPoint(ctx, pointBottomRight.x, rect.origin.y + [location scope] - ([self strokeWidth] / 2));
}
// Draw
CGContextStrokePath(ctx);
}
#pragma mark - Helper Methods
- (void)copyFrom:(XYZTimeoutLayer *)layer {
[self setPadding:[layer padding]];
[self setProgress:[layer progress]];
[self setStrokeWidth:[layer strokeWidth]];
[self setStrokeColor:[layer strokeColor]];
[self setDurationOfTimeoutAnimation:[layer durationOfTimeoutAnimation]];
}
- (CABasicAnimation *)createAnimationForKey:(NSString *)key {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
[animation setDuration:[self durationOfTimeoutAnimation]];
[animation setFromValue:[[self presentationLayer] valueForKey:key]];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
return animation;
}
- (CGRect)drawRect {
CGRect rect = [self bounds];
CGRect drawRect = CGRectMake([self padding], [self padding],
rect.size.width - (self.padding * 2),
rect.size.height - (self.padding * 2));
return drawRect;
}
#end
XYZTimeoutLocation
#import Foundation;
#import CoreGraphics;
/**
* An enum used to mark end of timeout line.
*/
typedef NS_ENUM(NSUInteger, Edge) {
/**
* The end of timeout line is at top.
*/
TOP = 0,
/**
* The end of timeout line is at left.
*/
LEFT,
/**
* The end of timeout line is at bottom.
*/
BOTTOM,
/**
* The end of timeout line is at right.
*/
RIGHT
};
/**
* A class that holds end of timeout line.
*/
#interface XYZTimeoutLocation : NSObject
/**
* The edge of the view where timeout line ended.
*/
#property(nonatomic) Edge edge;
/**
* The end scope to draw.
*/
#property(nonatomic) CGFloat scope;
/**
* Calculates scope for specified percent value for given rect.
*
* #param percent A percent to calculate scope for it.
* #param rect A rect to calculate scope for it.
*
* #return A scope of rect for specified percent.
*/
+ (CGFloat)scopeForPercent:(CGFloat)percent rect:(CGRect)rect;
/**
* Returns an instance of MVPTimeoutLocation that holds edge of view and scope to draw for specified percent value for given rect.
*
* #param percent A percent to calculate scope for it.
* #param rect A rect to calculate scope for it.
*
* #return An instance of MVPTimeoutLocation that holds edge of view and scope to draw.
*/
+ (XYZTimeoutLocation *)endLocationForPercent:(CGFloat)percent rect:(CGRect)rect;
#end
#import "XYZTimeoutLocation.h"
#implementation XYZTimeoutLocation
+ (XYZTimeoutLocation *)endLocationForPercent:(CGFloat)percent rect:(CGRect)rect {
CGFloat scope = [XYZTimeoutLocation scopeForPercent:percent rect:rect];
XYZTimeoutLocation *location = [[XYZTimeoutLocation alloc] init];
if (scope > rect.size.height) {
scope -= rect.size.height;
if (scope > rect.size.width) {
scope -= rect.size.width;
if (scope > rect.size.height) {
scope -= rect.size.height;
location.edge = TOP;
location.scope = scope;
} else {
location.edge = LEFT;
location.scope = scope;
}
} else {
location.edge = BOTTOM;
location.scope = scope;
}
} else {
location.edge = RIGHT;
location.scope = scope;
}
return location;
}
+ (CGFloat)scopeForPercent:(CGFloat)percent rect:(CGRect)rect {
CGFloat scope = (rect.size.width * 2) + (rect.size.height * 2);
CGFloat scopeForPercent = (scope / 100) * percent;
return scopeForPercent;
}
#end
I'm not satisfied with [XYZTimeoutLocation endLocationForPercent] method. If somebody have a better idea how to do this, please update/edit.
In UIViewController insert code below to test:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.timeoutView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.timeoutView setStrokeColor:[UIColor greenColor]];
[self.timeoutView setDurationOfTimeoutAnimation:1];
[self.timeoutView setStrokeWidth:10.0f];
[self.timeoutView setPadding:10.0f];
self.percent = 0;
[NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
if ((self.percent = (self.percent + 10)) > 100) {
self.percent = 0;
}
[self.timeoutView setProgress:self.percent];
}];
}

setNeedDisplay still does not work [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
Previously I asked a question in stackoverflow and that is about setNeedsDisplay cannot work.
I am not a lazy guy and I have tried everything but it still cannot work.
Maybe I cannot find where is the problem.
Can anyone help me to find out the problem?
//viewcontroller.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize frequency;
- (void)viewDidLoad
{
hi = [[cro alloc]init];
[self.view addSubview:hi];
CGFloat fu = frequency.value;
[hi changefreq:fu];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)change:(id)sender
{
CGFloat fu = frequency.value;
[hi changefreq:fu];
}
#end
//cro.m
#import "cro.h"
#implementation cro
#synthesize fffff;
CGFloat freee;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 1);
CGContextSetLineJoin(context, kCGLineJoinRound);
NSLog(#"hi i am here %f",fffff);
const CGFloat amplitude = 200/2;
for(CGFloat x = 0; x < 600; x += 0.5)
{
CGFloat y = amplitude * cosf(2 * M_PI * (x / 600) * freee) + 200;
if(x == 0)
CGContextMoveToPoint(context, x, y);
else
CGContextAddLineToPoint(context, x, y);
}
CGContextSetStrokeColorWithColor(context, [[UIColor greenColor] CGColor]);
self.clearsContextBeforeDrawing = NO;
CGContextStrokePath(context);
}
-(void)changefreq:(CGFloat)fre
{
NSLog(#"fre= %f",fre);
freee = fre;
[self setNeedsDisplay];
}
#end
here is the project
http://www.sendspace.com/file/lzt4b0
You initialize your view by calling [[cro alloc] init]. Since you're not calling initWithFrame: this will result in a view with zero width and height. Calling setNeedsDisplay on such a view has no effect because there is nothing to display.
Change your first line in viewDidLoad to something like
hi = [[cro alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
(adjust the size as needed)
Alternatively, you might want to use the cro instance that you already have in your storyboard instead of instantiating a new one. The storyboard instance is the one you're seeing, the hi instance is actually invisible with your current code. (btw, if you expect other people to read your code, you might want to start using sensible variable and class names.)
The following changes in ViewController.m ViewdidLoad method will do the fix
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
hi = [[cro alloc]initWithFrame:CGRectMake(201, 58, 414, 571)];
[self.view addSubview:hi];
CGFloat fu = frequency.value;
[hi changefreq:fu];
}
If you do the following it works for me:
Use property instead of ivar
Now you access your cro instance through self.cro
Connect in your storyboard the view controller's outlet cro (there is already a property named like this in your uploaded project) with the subview
Remove in -[ViewController viewDidLoad:] the lines where you create a new cro instance and add it as a subview to self
Use in your cro-class the ivar fffff in -[cro changefreq:] and -[cro drawRect:]
(It's all copied from your uploaded project only with my changes)
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet cro *cro;
#property (strong, nonatomic) IBOutlet UISlider *frequency;
-(IBAction)change:(id)sender;
#end
#implementation ViewController
#synthesize frequency;
- (void)viewDidLoad
{
CGFloat fu = frequency.value;
[self.cro changefreq:fu];
//NSLog(#"%f",hi.fffff);
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)change:(id)sender
{
CGFloat fu = frequency.value;
[self.cro changefreq:fu];
//[hi setNeedsDisplay];
}
#end
#interface cro : UIView
#property (nonatomic) CGFloat fffff;
-(void)changefreq:(CGFloat)fre;
#end
#implementation cro
#synthesize fffff;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
fffff = 15;
// Initialization code
}
return self;
}
-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 1);
CGContextSetLineJoin(context, kCGLineJoinRound);
NSLog(#"hi i am here %f",fffff);
const CGFloat amplitude = 200/2;
for(CGFloat x = 0; x < 600; x += 0.5)
{
CGFloat y = amplitude * cosf(2 * M_PI * (x / 600) * fffff) + 200;
if(x == 0)
CGContextMoveToPoint(context, x, y);
else
CGContextAddLineToPoint(context, x, y);
}
CGContextSetStrokeColorWithColor(context, [[UIColor greenColor] CGColor]);
self.clearsContextBeforeDrawing = NO;
CGContextStrokePath(context);
}
-(void)changefreq:(CGFloat)fre
{
NSLog(#"fre= %f",fre);
fffff = fre;
[self setNeedsDisplay];
}
#end

Resources