Force JBChartView to use a 0-100 Y-axis - ios

I'm using the excellent JBChartView in my project and It's working great. Here's my current code:
self.lineChart = [[JBLineChartView alloc] initWithFrame:CGRectMake(320, 400, 680, 300)];
self.lineChart.dataSource = self;
self.lineChart.delegate = self;
self.lineChart.backgroundColor = [UIColor clearColor];
JBLineChartFooterView *footerView = [[JBLineChartFooterView alloc] initWithFrame:CGRectMake(10, ceil(self.view.bounds.size.height * 0.5) - ceil(10 * 0.5), self.view.bounds.size.width - (10 * 2), 10)];
footerView.backgroundColor = [UIColor clearColor];
footerView.leftLabel.text = #"yesterday";
footerView.leftLabel.textColor = [UIColor whiteColor];
footerView.rightLabel.text = #"now";
footerView.rightLabel.textColor = [UIColor whiteColor];
footerView.sectionCount = 10;
self.lineChart.footerView = footerView;
[self.view addSubview:self.lineChart];
[self.lineChart setState:JBChartViewStateCollapsed animated:YES];
Nothing fancy, really.
JBChartView automatically chooses the Y-axis scale based on what data is passed to it in lineChartView: heightForIndex:. This is nice in most situations. My data, however, is on CPU usage, and thus I'd like to force the Y-axis to always be 0 at the bottom and 100 at the top.
Actually, I'd like it to be 0 on the bottom and MAX(100, highestPoint) at the top (because CPU usage can sometimes be over 100%) - is this possible?

As of v2.2.1, JBChartView allows you to supply a minimumValue and/or maximumValue for the y-axis.
Notes:
If no value(s) are supplied, the min and max values of the chart's data source are used.
If value(s) are supplied, they must be >= 0, otherwise an assertion will be thrown.
The min/max values are clamped to the ceiling and floor of the actual min/max values of the chart's data source.
For example, if a maximumValue of 20 is supplied & the chart's actual max is 100, then 100 will be used.
Lastly, for min/max modifications to take effect, reloadData must be called.
Hope this helps!

It turned out that all I needed to do was modify line 240 of JBLineChartView.m:
self.cachedMaxHeight = maxHeight;
to say:
self.cachedMaxHeight = MAX(100,maxHeight);

Related

Coded UIStepper not displaying

After not finding an answer I have to again ask you all for help. I am creating a UIStepper programatically but it will not display. Labels, buttons, and switches are all displaying properly so I must be missing something related to the stepper.
Elsewhere in my code I declare and initialize UIView *v and NSMutableArray *steppers, and declare UIStepper *st. The code to create the stepper is:
st = [[UIStepper alloc] init];
st.frame = CGRectMake(xnear, ypos, 0, 0);
[st addTarget:self action:#selector(stepper1:) forControlEvents:UIControlEventValueChanged];
[st setMinimumValue:0];
[st setMaximumValue:99];
[st setWraps:NO];
[st setContinuous:NO];
[v addSubview:st];
[steppers addObject:st];
At runtime xnear = 100 and ypos = 250, so the stepper is within the display. A label immediately above, and a text field immediately below, are displaying. Other questions regarding the UIStepper state the width and height are ignored, so I used 0 for both. Is there anything obviously wrong with this code?
You are setting height and width of UIStepper as 0
st.frame = CGRectMake(xnear, ypos, 0, 0);
give some height and width
st.frame = CGRectMake(xnear, ypos,200, 100);
The answer is, quite frankly, embarrassing. A custom background color was set for the UIView and no color was set for the control. I was able to get the stepper to show up with the following line of code:
st.backgroundColor = [UIColor whiteColor];
Similarly, the UISegmentedControl *sc showed up when I added:
sc.backgroundColor = [UIColor whiteColor];
Thanks for the help and sorry to waste your time!

how to programmatically align a label to an x, y coordinate

below are some other properties of the label. obviously nstextalignmentleft is not what i'm going for. having trouble understanding where to enter coordinates.
self.lblTimer = [[UILabel alloc] init];
self.lblTimer.translatesAutoresizingMaskIntoConstraints = NO;
self.lblTimer.textAlignment = NSTextAlignmentLeft;
self.lblTimer.font = [UIFont systemFontOfSize:10];
self.lblTimer.textColor = [UIColor redColor];`self.lblTimer = [[UILabel alloc] init];
I think you're misunderstanding what textAlignment does. This simply controls the alignment within the label, not on the screen. If you want to position the label on screen you must change its frame property:
self.lblTimer.frame = CGRectMake(x,y,width,height);
As you've set self.lblTimer.translatesAutoresizingMaskIntoConstraints to NO I am guessing you want to use Auto Layout and if so, I highly recommend taking a look at Masonry.
An alternative is to set the frame property on the label with requires a CGRect where you give it the x and y coordinates as well as the width and height.

iOs 8 seems to be ignoring my UILabel's X and Y coordinates

I have a somewhat old Objective C function that adds a UILabel to my UIView. It keeps track of the last label's Y in the variable _nextFieldY so it can put the next label below it. When I'm adding the label, I init it with its Width, Height, X and Y, and add it to my view. In iOs 7, this works, and correctly puts everything in its place. However, with any devices running the same app in iOs 8+, it appears the labels are all put at (0,0); the labels are all on top of each other in the top left corner. Was there a change between these versions that would cause this? I usually avoid programmatically adding things to my XIBs, so I don't know if there's certain work I have to do to get them to behave.
CGFloat labelWidth = 100;
CGFloat labelHeight = 40;
CGFloat labelY = _nextFieldY-REG_FORM_PADDING_Y;
UIFont *labelFont = [UIFont boldSystemFontOfSize:12.0f];
UILabel *currLabel = [[UILabel alloc] initWithFrame:CGRectMake(REG_FORM_OFFSET_X, labelY, labelWidth, labelHeight)];
currLabel.text = label;
[currLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[currLabel setFont:labelFont];
[currLabel setTextAlignment:NSTextAlignmentLeft];
[_formView addSubview:currLabel];
_nextFieldY += currLabel.frame.size.height + REG_FORM_PADDING_Y;
Since you're setting the frame directly to position your view, you should be leaving translatesAutoresizingMaskIntoConstraints set to YES. Setting it to NO tells the system that it can ignore the frame you set.

Color of bar chart not displaying in JBChartView

I'm trying to implement a bar chart into my iOS app. I am using JBChartView. Everything is working fine, but there is no colour to the bars except when I press on them using the touchEvent.
Does anyone have any experience with this particular plugin to help me get it working correctly?
Thanks
- (void)viewDidLoad
{
_barChartView = [[JBBarChartView alloc] init];
_barChartView.delegate = self;
_barChartView.dataSource = self;
_tableView.backgroundColor =[UIColor clearColor];
_barChartView.frame = CGRectMake(0,0,200,200);
_barChartView.backgroundColor = [UIColor clearColor];
[_barChartView reloadData];
[_barChart addSubview: _barChartView];
}
- (UIColor *)barSelectionColorForBarChartView:(JBBarChartView *)barChartView
{
return [UIColor greenColor]; // color of selection view
}
- (BOOL)slideNavigationControllerShouldDisplayLeftMenu
{
return YES;
}
- (UIColor *)barChartView:(JBBarChartView *)barChartView colorForBarViewAtIndex:(NSUInteger)index
{
return [UIColor greenColor];
}
- (NSUInteger)numberOfBarsInBarChartView:(JBBarChartView *)barChartView
{
return 4;
}
- (CGFloat)barChartView:(JBBarChartView *)barChartView heightForBarViewAtAtIndex:(NSUInteger)index
{
return 100.0;
}
The problem appears to be with how JBBarChartView "normalizes" the values. Per the header file for JBBarChartView.h:
/**
* Height for a bar at a given index (left to right). There is no ceiling on the the height;
* the chart will automatically normalize all values between the overal min and max heights.
*
* #param barChartView The bar chart object requesting this information.
* #param index The 0-based index of a given bar (left to right, x-axis).
*
* #return The y-axis height of the supplied bar index (x-axis)
*/
Because of this "normalization" when all of your values are the same (100.0f) it normalizes them all to 0, so there is no bar to display. Luckily, it is open-source, so you just need to open up the implementation file and make a little modification:
- (CGFloat)normalizedHeightForRawHeight:(NSNumber*)rawHeight
{
CGFloat minHeight = [self minimumValue];
CGFloat maxHeight = [self maximumValue];
CGFloat value = [rawHeight floatValue];
if ((maxHeight - minHeight) <= 0)
{
return self.availableHeight; // change this line to return the max height instead of 0
}
return ((value - minHeight) / (maxHeight - minHeight)) * [self availableHeight];
}
The correct solution to your problem is to supply a minimum value on the chart.
Please look # the documentation for JBChartView:
/**
* The minimum and maxmimum values of the chart.
* If no value(s) are supplied:
*
* minimumValue = chart's data source min value.
* maxmimumValue = chart's data source max value.
*
* If value(s) are supplied, they must be >= 0, otherwise an assertion will be thrown.
* The min/max values are clamped to the ceiling and floor of the actual min/max values of the chart's data source;
* for example, if a maximumValue of 20 is supplied & the chart's actual max is 100, then 100 will be used.
*
* For min/max modifications to take effect, reloadData must be called.
*/
#property (nonatomic, assign) CGFloat minimumValue;
#property (nonatomic, assign) CGFloat maximumValue;
If all of your data is equal to a single value (ie. 100), supplying a minimum value of 0 will ensure all bars are drawn at equal (visible) height (in relation to 0).
Hope this helps.

How do I put an RTLabel on an iOS image?

I am trying to use https://github.com/honcheng/RTLabel to get a rich text label, but my immediate goal is to display "Hello, world!"
My code is:
UIImageView *noteImage = [[UIImageView alloc] initWithFrame:bounds];
noteImage.image = image;
[self.view addSubview:noteImage];
CJSHCardView *noteView = [[CJSHCardView alloc] initWithImage:image];
[noteView setFrame:CGRectMake(100 * i, 20, 100 * scale, 100 * scale)];
noteView.transform = CGAffineTransformScale(noteView.transform, scale_x, scale_y);
NSString *text = #"Hello, world!";
RTLabel *label = [[RTLabel alloc] initWithFrame:CGRectMake(100 * i, 20, 100 * scale, 100 * scale)];
[noteImage addSubview:label];
[label setText:text];
I tried both noteImage and noteView in the second-to-last line. The rectangle has the same dimensions as the original image, which is displaying correctly. However, none of the approaches I've tried seem apt to display a label on top of the noteImage / noteView as backgrounds.
What is an appropriate way to get a label (preferably one that supports rich text) to display on top of an image meant to serve as background for it?
iOS 7's UILabel supports attributed strings, so unless you need to target an earlier version, I suggest simply building your UI in interface builder and setting the attributed text as needed in your code.

Resources