How to change the XAxis used on my chart ShinobiCharts - iphone

I'd like to have the xAxis of my chart to look like this :
Jan, Feb, Mar, Apr, ..... Nov, Dec
Right now it's following it's default, numbering xAxis according to the number of Data Points.
How can i achieve this change to this axis ?
I've tried using Category Axis and setting an NSMutableArray containing these strings ("Jan", "Feb"...) as categories and with a numberRange going from 1 to 12 but it didn't work.
chart = [[ShinobiChart alloc] initWithFrame:chartEmbaixo.frame withPrimaryXAxisType:SChartAxisTypeCategory withPrimaryYAxisType:SChartAxisTypeNumber];
NSMutableArray * monthNames = [[NSMutableArray alloc] initWithObjects:#"Jan", #"Fev", #"Mar", #"Abr", #"Mai", #"Jun", #"Jul", #"Ago", #"Set", #"Out", #"Nov", #"Dez", nil];
SChartNumberRange * numberRange = [[SChartNumberRange alloc] initWithMinimum:[NSNumber numberWithInt:1]andMaximum:[NSNumber numberWithInt:12]];
SChartCategoryAxis *xAxis = [[SChartCategoryAxis alloc] initWithRange:numberRange];
xAxis.categories = monthNames;
chart.xAxis = xAxis;

first i use as my x axis
Edit how i make my x axis:
SChartNumberRange *r1 = [[SChartNumberRange alloc] initWithMinimum:[NSNumber numberWithInt:0] andMaximum:[NSNumber numberWithInt:2]];
SChartCategoryAxis *xAxis = [[SChartCategoryAxis alloc] initWithRange:r1];
xAxis.title = #"";
//xAxis.enableGesturePanning = YES;
xAxis.enableGesturePanning = YES;
xAxis.style.gridStripeStyle.showGridStripes = NO;
xAxis.style.majorGridLineStyle.showMajorGridLines = NO;
when you make you data points it should use the xValue as the x axis point.
like this:
dp.yValue = 1000;
dp.xValue = #"Jan";
the xValue should be set as the x point for that particular data point. This should work, but if it doesn't or you want to do something more complex you can extend this method from SChartDelegate protocol:
-(void)sChart:(ShinobiChart *)chart alterTickMark:(SChartTickMark *)tickMark beforeAddingToAxis:(SChartAxis *)axis
in this method you have the tickMark.tickLabelis the axis label for that given point where you can do your editing. Don't forget to verify what axis your on.
Hope this helps. If not tomorrow i can post you some code from my project (currently i don't have access to it from where i am)
Edit: currently i have this code:
- (void)sChart:(ShinobiChart *)chart alterTickMark:(SChartTickMark *)tickMark beforeAddingToAxis:(SChartAxis *)axis {
if (chart.yAxis == axis ) return;
for (UIView *i in tickMark.tickMarkView.subviews)
[i removeFromSuperview];
tickMark.tickMarkView.frame = CGRectMake(0, 0, 170, 75);
//center the marker at the right place because the size was changed
tickMark.tickMarkX = tickMark.tickMarkX - (tickMark.tickMarkView.frame.size.width/2) ;
tickMark.tickMarkY = 10;
//img
UIImageView *img = [[UIImageView alloc] initWithImage:[UIImage imageNamed: #"graph_bar_tag_2#2x.png"]];
img.frame = CGRectMake( 0, 0, tickMark.tickMarkView.frame.size.width, tickMark.tickMarkView.frame.size.height);
[tickMark.tickMarkView addSubview:img];
//label with the markView's size with 7px padding on the left and on the right
UILabel *label = [[UILabel alloc] initWithFrame: CGRectMake( 7, 5, tickMark.tickMarkView.frame.size.width-14, 15)];
label.backgroundColor = [UIColor clearColor];
//tikMark.tickLabel has an pair of indexes so that i can easily find the data for this particular data point and series.
label.text = [_dataSource getNameFor: tickMark.tickLabel.text];
label.textAlignment = UITextAlignmentCenter;
//color_other_light is a UIColor var
[label setTextColor: color_other_light];
[tickMark.tickMarkView addSubview:label];
...
}

Related

To make 16 uilabels and align them in circular path.

NSMutableArray *views = [[NSMutableArray alloc]initWithCapacity:0];
for (NSInteger i = 0; i<16; i++)
{
UIView *circle = [[UIView alloc]init];
circle.backgroundColor = [UIColor clearColor];
UIImageView *circleImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)];
circleImage.image = [UIImage imageNamed:#"circle"];
[circle addSubview:circleImage];
UILabel *labelInsideCircle = [[UILabel alloc]initWithFrame:CGRectMake(10, 10, 40, 40)];
labelInsideCircle.backgroundColor = [UIColor clearColor];
labelInsideCircle.textColor = [UIColor greenColor];
labelInsideCircle.font = [UIFont fontWithName:#"Helvetica" size:30.0];
labelInsideCircle.center = circleImage.center;
NSInteger int_ = [self getRandomNumber:0 to:(arrOfOptions.count-1)];
labelInsideCircle.text = [NSString stringWithFormat:#"%#",[arrOfOptions objectAtIndex:int_]];
labelInsideCircle.textAlignment = NSTextAlignmentCenter;
[arrOfOptions removeObjectAtIndex:int_];
[circle addSubview:labelInsideCircle];
[labelInsideCircle release];
[views addObject:circle];
[circle release];
[circleImage release];
}
/* Rotating circles with angles */
float curAngle = 0;
float incAngle = ( 360.0/(views.count) )*3.14/180.0;
CGPoint circleCenter = CGPointMake(380, 580); /* given center */
float circleRadius = 250; /* given radius */
for (UIView *view in views)
{
CGPoint viewCenter;
viewCenter.x = circleCenter.x + cos(curAngle)*circleRadius;
viewCenter.y = circleCenter.y + sin(curAngle)*circleRadius;
view.transform = CGAffineTransformRotate(view.transform, curAngle);
view.center = viewCenter;
[self.view addSubview:view];
curAngle += incAngle;
}
The problem is here the text of UILabel is also getting transformed, which is obvious. What I want is 16 circular views with labels on them without the label's text transformed. Can anyone please help me out with this ?
In this case, you just need to change their location coordinates, not rotate them.
NSMutableArray *views = [[NSMutableArray alloc] initWithCapacity:0];
for (NSInteger i = 0; i<16; i++)
{
UIView *circle = [[UIView alloc]init];
circle.backgroundColor = [UIColor clearColor];
UIImageView *circleImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 80, 80)];
circleImage.image = [UIImage imageNamed:#"circle"];
[circle addSubview:circleImage];
UILabel *labelInsideCircle = [[UILabel alloc]initWithFrame:CGRectMake(10, 10, 40, 40)];
labelInsideCircle.backgroundColor = [UIColor clearColor];
labelInsideCircle.textColor = [UIColor greenColor];
labelInsideCircle.font = [UIFont fontWithName:#"Helvetica" size:30.0];
labelInsideCircle.center = circleImage.center;
NSInteger int_ = arc4random()%[arrOfOptions count];
labelInsideCircle.text = [NSString stringWithFormat:#"%#",[arrOfOptions objectAtIndex:int_]];
labelInsideCircle.textAlignment = NSTextAlignmentCenter;
[arrOfOptions removeObjectAtIndex:int_];
[circle addSubview:labelInsideCircle];
[labelInsideCircle release];
[views addObject:circle];
[self.view addSubview:circle];
[circle release];
[circleImage release];
}
/* Rotating circles with angles */
float curAngle = 0;
float incAngle = ( 360.0/(views.count) )*3.14/180.0;
CGPoint circleCenter = CGPointMake(380, 580); /* given center */
float circleRadius = 250; /* given radius */
for (UIView *view in views)
{
CGPoint viewCenter;
viewCenter.x = circleCenter.x + cos(curAngle)*circleRadius;
viewCenter.y = circleCenter.y + sin(curAngle)*circleRadius;
//view.transform = CGAffineTransformRotate(view.transform, curAngle);
view.center = viewCenter;
[self.view addSubview:view];
curAngle += incAngle;
}
Some coding suggestions:
You can use arc4random() function if you don't have anything special in your own random number generator.
You can turn on ARC in xCode!
In a loop set their centers accordingly, don't rotate them nor their super view.
The following is not directly related to your question but may be helpful:
Aparaently you have got all the math available. I suggest to measure how much cpu time gets lost on the cos and sin etc. calls. If you find that significant then think about your algorithm. You will (most probably) find out that you call cos and sin hundrets or thousands of times for a limited number of angles.
You may then try it and find out that possible pre-calculations or just "caching and reusing" earlier results may save significant processing time.
Plus pre-calculating or caching of sinus would do. You can derrive cosinus values from sinus (and vice versa) by adding (or substracting respectively) an offset of pi/2 (or 90 degrees respectively) to the argument.
For similar tasks I was working with degrees (not radiants) and found out that I could not predict the angles but that a significant of full degrees (1°, 2°, 3°, ... and nothing in between) was exact enough for the job. Then I maintained an array of 360 sinus values and used that instead of calling the real function again and again. (Plus I only had to calculate 90 of them and mirrored the results of the other 270 degrees according to the nature of the sinus function) 180 floats is not too much of memory compared to the speed that I gained. Something like that can be suitable for you too. In your case your potenital agruments to sin and cos are limited to full-number multipilers of incAngle.
Which means there are only [views count] number of potential values each.

UITextView - Horizontal Scrolling?

How can I create a horizontal scrolling UITextView?
When I set my text programmatically it adds automatic line breaks, so I can only scroll vertically...
titleView.text = #"this is a very long text. this is a very long text. this is a very long text. this is a very long text. this is a very long text.";
Thanks for your answers.
EDIT:
So far I tried this:
UIScrollview *yourScrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0 ,0 , self.view.frame.size.width, 50)];
CGFloat textLength = [titleView.text sizeWithFont:titleView.font constrainedToSize:CGSizeMake(9999, 50) lineBreakMode:NSLineBreakByWordWrapping].width;
yourScrollview.contentSize = CGSizeMake(textLength + 200, 500); //or some value you like, you may have to try this out a few times
titleView.frame = CGRectMake(titleView.frame.origin.x, titleView.frame.origin.y, textLength, titleView.frame.size.height);
[yourScrollview addSubview: titleView];
NSLog(#"%f", textLength);
but I received: 'Threat 1: signal SIGABRT'
I have not yet done something like this, but I would try the following steps to accomplish this:
Create a UIScrollview *yourScrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0 ,0 , self.view.frame.size.width, 50)]; //
Use CGFloat textLength = [titleView.text sizeWithFont:titleView.font constrainedToSize:CGSizeMake(9999, 50) lineBreakMode:NSLineBreakByWordWrapping].width;
to get the final length of your text
Set yourScrollView.contentSize = CGSizeMake(textLength + 20, 50); //or some value you like, you may have to try this out a few times
Also set titleTextView.frame = CGRectMake(titleTextView.frame.origin.x, titleTextView.frame.origin.y, textLength, titleTextView.frame.size.height);
Make titleView a subview of yourScrollView: [yourScrollView addSubview: titleView];
Hope this gives you a good start!
EDIT: This Code will work:
Please notice I used a UILabel instead of a UITextView.
UILabel *titleView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 40)];
titleView.text = #"this is a very long text. this is a very long text. this is a very long text. this is a very long text. this is a very long text.";
titleView.font = [UIFont systemFontOfSize:18];
titleView.backgroundColor = [UIColor clearColor];
titleView.numberOfLines = 1;
UIScrollView *myScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
CGFloat textLength = [titleView.text sizeWithFont:titleView.font constrainedToSize:CGSizeMake(9999, 50) lineBreakMode:NSLineBreakByWordWrapping].width;
myScrollView.contentSize = CGSizeMake(textLength + 20, 50); //or some value you like, you may have to try this out a few times
titleView.frame = CGRectMake(titleView.frame.origin.x, titleView.frame.origin.y, textLength, titleView.frame.size.height);
[myScrollView addSubview: titleView];
[self.view addSubview:myScrollView];
[titleView release];
[myScrollView release];

Sizing UITextView to its content isn't working

Here's the code for a UITextView that I want to size to the height of its content.
If I write the textView.frame height explicitly like:
textView.frame = CGRectMake(100, 12, 320, 458);
the textView sizes to it's content as expected.
If, however, I write it like the following. It doesn't even display although the NSLog statement says that there's a value to textView.contentSize.height
UITextView *textView = [[UITextView alloc] init];
textView.layer.borderWidth = 5.0f;
textView.layer.borderColor = [[UIColor redColor] CGColor];
textView.text = [item objectForKey:#"description"];
textView.frame = CGRectMake(100, 12, 320, textView.contentSize.height);
NSLog(#"%f textviewcontnet size", textView.contentSize.height);
textView.editable = NO;
[self.view addSubview:textView];
When I log the output of:
NSLog(#"%f textviewcontent size", textView.contentSize.height);
I get "458.000000 textviewcontent size"
thanks for any help
I'd suggest trying:
UITextView *textView = [[UITextView alloc] init];
textView.layer.borderWidth = 5.0f;
textView.layer.borderColor = [[UIColor redColor] CGColor];
textView.text = [item objectForKey:#"description"];
textView.frame = CGRectMake(100, 12, 320, 458);
textView.editable = NO;
[self.view addSubview:textView];
textView.frame = CGRectMake(100, 12, 320, textView.contentSize.height);
I've heard that textView.contentSize.height doesn't work until it's been added to a view (though that's not my experience). More importantly, I don't know how it would interpret textView.contentSize.height if it doesn't yet know what the width of the control is. So go ahead, set the initial frame, do addSubview and then readjust the size based upon textView.contentSize.height.
Quickly copied out of one of my projects:
AppDelegate *appDelegate;
CGSize textSize1, textSize2;
appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
textSize1 = [self.subjectLabel.text sizeWithFont:[appDelegate fontNormal] constrainedToSize:CGSizeMake(300.0f, 10000.0f) lineBreakMode:NSLineBreakByWordWrapping];
self.subjectLabel.frame = CGRectMake(10, 5, 300, textSize1.height);
textSize2 = [self.descriptionLabel.text sizeWithFont:[appDelegate fontNormal] constrainedToSize:CGSizeMake(300.0f, 10000.0f) lineBreakMode:NSLineBreakByWordWrapping];
self.descriptionLabel.frame = CGRectMake(10, 5 + textSize1.height + 5, 300, textSize2.height);
[appDelegate fontNormal] just returns a UIFont object, the one that I am using for all "normal" text items. Don't worry about that too much. But it is important that you use the same font that is used for the text view too.
My example is a bit easier because it is a UILable. That works with a text view too but you will have to consider the insects. Easy solution, just substract some "fuzzy offset" from the width compared to the frame width of your text view.

Changing the Range of a UISlider Programmatically

How is it possible to set the min max ranges of the UISlider programmatically?
For example (dummy code)
UISlider* slider = [[UISlider alloc] init];
slider.min = -3;
slider.max = 3;
EDIT:
So I have the following:
sl.minimumValue = 5;
NSLog(#"MIN VAL: %d", sl.minimumValue);
This doesn't work, I still get it logging the value 0. Is this because I have set values in interface builder?
Here is it.
UISlider* slider = [[UISlider alloc] init];
slider.minimumValue = -3.0f;
slider.maximumValue = 3.0f;
In the case updating selected values of IBOutlet-ed RangeSeekSlider
rangeSeekSlider.selectedMinValue = 10.0
rangeSeekSlider.selectedMaxValue = 100.0
rangeSeekSlider.setNeedsLayout()
// Add a frame where you want to place the slider. This will place it at (x,y) = 0,0
with a height of 10 and width of 200
CGRect frame = CGRectMake(0.0, 0.0, 200.0, 10.0);
// sliderAction will respond to the updated slider value
UISlider *slider = [[UISlider alloc] initWithFrame:frame];
[slider addTarget:self action:#selector(sliderAction:) forControlEvents:UIControlEventValueChanged];
// Set minimum and maximum value
slider.minimumValue = 0.0;
slider.maximumValue = 50.0;
slider.continuous = YES;
// Initial value
slider.value = 25.0;
// Add slider to view
[self.view addSubview:slider];
Swift 5 :
self.yourSlider.minimumValue = 0.0
self.yourSlider.maximumValue = 4
self.yourSlider.value = 0

What are the ranges of the accelerator on the iPhone?

I can't seem to find any documentation online about this, and what I am googling is giving me a lot of conflicting information...
From iphonedevsdk.com:
The accelerometers used in the first
and second generation iPhones (and I
assume also the iPod touches) operate
in two modes: +/- 2 g, and +/- 8 g.
(Actually, as you observed, they
report accelerations somewhat outside
the nominal range. Accuracy is not
spec'ed outside that range, though.)
Apple operates them in the +/- 2 g
mode. There is a tradeoff: The current
resolution is nominally 0.018 g,
according to the datasheet (though my
first generation iPhone uses
0.018168604, according to a modified version of AccelerometerGraph). In the
+/- 8 g mode, the resolution would be four times cruder.
I assume Apple decided that the finer
resolution would be more useful than
the wider range. (I'd rather see finer
resolution than 0.018 g. So neither of
us is fully satisfied.)
You cannot change the mode with any
published feature of the APIs. Since
they are passing acceleration as a
double, they could theoretically allow
a change in mode, and simply look at
the mode when rescaling the A/D value,
before reporting acceleration. (The
obvious place to set the mode would be
in the call which sets up the
application to receive accelerometer
information.) However, for backward
compatibility, the OS would have to
set the accelerometer mode to +/- 2 g
at the beginning of the application.
And none of the background processes
could be allowed to set the
accelerometer mode.
The aGauge app displays this raw data coming from the accelerometer as you move the device. It can also help you find the "flip" threshold for your device.
I created the following application to try to test out the ranges...
UIAccelerometer *objAccelerometer;
UILabel *lblxmin, *lblxmax, *lblymin, *lblymax, *lblzmin, *lblzmax;
UILabel *lblxnow, *lblynow, *lblznow;
float xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0, zmin = 0.0, zmax = 0.0, xnow = 0.0, ynow = 0.0, znow = 0.0;
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
//NSLog (#"%f, %f, %f", acceleration.x, acceleration.y, acceleration.z);
xnow = acceleration.x;
ynow = acceleration.y;
znow = acceleration.z;
if (xnow < xmin) { xmin = xnow; }
if (ynow < ymin) { ymin = ynow; }
if (znow < zmin) { zmin = znow; }
if (xnow > xmax) { xmax = xnow; }
if (ynow > ymax) { ymax = ynow; }
if (znow > zmax) { zmax = znow; }
lblxmin.text = [NSString stringWithFormat:#"%f", xmin];
lblymin.text = [NSString stringWithFormat:#"%f", ymin];
lblzmin.text = [NSString stringWithFormat:#"%f", zmin];
lblxmax.text = [NSString stringWithFormat:#"%f", xmax];
lblymax.text = [NSString stringWithFormat:#"%f", ymax];
lblzmax.text = [NSString stringWithFormat:#"%f", zmax];
lblxnow.text = [NSString stringWithFormat:#"%f", xnow];
lblynow.text = [NSString stringWithFormat:#"%f", ynow];
lblznow.text = [NSString stringWithFormat:#"%f", znow];
}
-(void) invokeAccelerometer {
objAccelerometer = [UIAccelerometer sharedAccelerometer];
objAccelerometer.delegate = self;
objAccelerometer.updateInterval = (1.0 / 10.0);
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
lblxmin = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 40)];
lblxnow = [[UILabel alloc] initWithFrame:CGRectMake(100, 10, 100, 40)];
lblxmax = [[UILabel alloc] initWithFrame:CGRectMake(200, 10, 100, 40)];
lblymin = [[UILabel alloc] initWithFrame:CGRectMake(10, 60, 100, 40)];
lblynow = [[UILabel alloc] initWithFrame:CGRectMake(100, 60, 100, 40)];
lblymax = [[UILabel alloc] initWithFrame:CGRectMake(200, 60, 100, 40)];
lblzmin = [[UILabel alloc] initWithFrame:CGRectMake(10, 110, 100, 40)];
lblznow = [[UILabel alloc] initWithFrame:CGRectMake(100, 110, 100, 40)];
lblzmax = [[UILabel alloc] initWithFrame:CGRectMake(200, 110, 100, 40)];
[self.view addSubview:lblxmin];
[self.view addSubview:lblxnow];
[self.view addSubview:lblxmax];
[self.view addSubview:lblymin];
[self.view addSubview:lblynow];
[self.view addSubview:lblymax];
[self.view addSubview:lblzmin];
[self.view addSubview:lblznow];
[self.view addSubview:lblzmax];
[self invokeAccelerometer];
[super viewDidLoad];
}
The problem is, when I rotate my iPod along the horizontal/vertical axes and then flip it over, I get values like:
xmin -1.271802
xmax 1.180959
ymin -1.344477
ymax 1.108285
zmin -2.30713
zmax 2.325581
If I take the iPod and shake the heck out of it, I get...
x -2.325581 to 2.307413
y -2.325581 to 2.307413
z -2.307413 to 2.325581
Any ideas what it's measuring?
The best I've come up with is:
vertical axis
x = -1 if tilted to the left ( <| )
x = +1 if tilted all the way to the right ( |> )
where < is the way the screen faces, and | is the bottom of the iPod
y ~ -1 if screen is facing you, perpendicular to floor ("standing up")
y ~ 1 if facing away from you (and upside down)