Dynamically change UIView width based on a number in UILabel - ios

I have a UIView that displays like a bar and its width should change based on a NSNumber value displayed on a UILabel.
Image below shows the ui
For instance: As shown in the image, all 3 orange bars have different values. I need the bar's width should also be different based on the value. The bars with value 14 and 10 should be less in width than the bar with value 18.
Following is the code I wrote but it doesn't work.
//Get the value as string
NSString *countString = cell.numberOfTuneIn.text;
//MAximum size of the bar
CGSize maxSize = CGSizeMake(cell.numberOfTuneIn.bounds.size.width, CGFLOAT_MAX);
CGRect s = [countString boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:cell.numberOfTuneIn.font} context:nil];
//set the frame of the bar
CGRect rect = cell.barView.frame;
rect.size.width = s.size.width;
cell.barView.frame = rect;
Can someone please help with:
How do I change the width of the bar based on the value?

This is the basic logic you should follow:
Get bar number range (e.g. 0-100)
Get width pixel range (e.g. 0-320)
Create ratio (e.g. 320 / 100) or 3.2 pixels of width for each 1 you
increment...
So according to the example above:
If the bar is 100, it's width is 100 * 3.2 = 320 px width
If the bar is 50, it's width is 50 * 3.2 = 160 px width
Hope it helped.
- (CGFloat)getViewlWidth:(float)labelValue {
// Setup view bar settings, you can take those settings outside of this method if needed
int maxLabelValue = 100;
int viewMaxWidth = 320; // You can make it dynamic according to screen width
float widthPixelRatio = viewMaxWidth / maxLabelValue;
// Calculate width
CGFloat pixelsResult = labelValue * widthPixelRatio;
// Return value
return pixelsResult;
}
// Lets assume that here you get the label value from the server and you called it labelValue
NSString * labelValue = // Value from server
/*
Create UILabel here, showing the value from server
*/
// Get the width of the UIView to be
CGFloat myViewWidth = [self getViewlWidth:[labelValue floatValue]];
/*
Create the UIView here and set its witdh to the result of the CGFloat above (myViewWidth)
*/

Related

Read CGFloat from Anchor Constraints

I created an UIView and then added the Anchor constraints but I have a problem when I want to read the values ...
In this case as you see, I created an NSLayoutConstraint property to get the Anchor Width of my uiview ... I then created a CGFloat that contains constraint but my NSLog always returns me a ZERO value.
where am I wrong? how can I get the width values of my UIView assigned to the Anchors?
UIView *trackLine = [[UIView alloc] init];
trackLine.backgroundColor = [self trackLineColor];
trackLine.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:trackLine];
[trackLine.topAnchor constraintEqualToAnchor:mediaTitle.bottomAnchor constant:25].active = YES;
[trackLine.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES;
[trackLine.heightAnchor constraintEqualToConstant:1].active = YES;
self.width = [trackLine.widthAnchor constraintEqualToAnchor:self.widthAnchor multiplier:.8];
self.width.active = YES;
CGFloat trackLineLenght = self.width.constant;
NSLog(#"TRACK LINE %f", trackLineLenght );
NSLog Result:
**2017-10-21 17:10:35.096562+0200 [5501:1994879] TRACK LINE 0.000000**
OK - a little confusion...
First, don't use "width" as a property name... very confusing, since width is used in so many places already.
So, let's assume you have:
#property NSLayoutConstraint *trackLineWidthConstraint;
A .widthAnchor doesn't really have a width in terms of "what's the width of the anchor." The way you are defining your constraints:
self.trackLineWidthConstraint = [trackLine.widthAnchor constraintEqualToAnchor:self.widthAnchor multiplier:.8];
Says "set the .trackLineWidthConstraint property to 80% of the width of self. So, whenever the actual width of self changes, the actual width of your trackLine view will change to 80% of the new width.
The .constant is Zero. If it was something other than zero, that value would be added after calculating 80%. For example:
self.trackLineWidthConstraint = [trackLine.widthAnchor constraintEqualToAnchor:self.widthAnchor multiplier:.8];
// if self is 200-pts wide, trackLine will be 160-pts
self.trackLineWidthConstraint.constant = 10
// trackLine width is now (200 * 0.8) + 10, or 170-pts
If you want to get the current width of trackLine, you can get it from its .frame (after auto-layout has finished).
Hopefully, that didn't just make it more confusing :)

UITextField does not show text out of bounds correctly

I want to have a UITextField that has the behaviour like this with the same fontsize:
But when I enter the same min fontsize as the original fontsize I get this behaviour:
What causes this behaviour and how do I solve that?
I do not want to resize the font. So adjusting the fontsize won't work
I think you have a setting wrong. By default, as you type on a UITextField it will keep the curser visible at the last entered character as the first example you provided does but with no change to font size. The shrinking behavior will only occur if you set adjustsFontSizeToFitWidth to YES. Try deleting the minimumFontSize and adjustsFontSizeToFitWidth settings.
Good question. AFAIK, it can't be done. But, you could write your own custom control to do this. I would start by dropping a label on top and take keyboard input to set the contents of the label.
Here's the code that should do the trick. You need to put your label in another view so it clips the text as it's being adjusted.
- (IBAction)field1_editing_changed:(id)sender {
NSString *text = self.field1.text;
NSAttributedString *attributedText =
[[NSAttributedString alloc]
initWithString:text
attributes:#{NSFontAttributeName:self.field1.font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){CGFLOAT_MAX, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGFloat padding = 5;
CGFloat width = rect.size.width;
width += 2*padding;
CGRect frame = self.field1.frame;
if (width > frame.size.width)
frame.origin.x -= width - frame.size.width;
frame.origin.y += 30; // I added this so you could see the label appear below the field (for testing only)
frame.origin.x += padding;
frame.size.width = width;
NSLog(#"%g, %g, %g, %g", frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
self.label1.frame = frame;
self.label1.text = self.field1.text;
self.label1.font = self.field1.font;
}
UITextField has a property adjustsFontSizeToFitWidth, see UITextField Class Reference.
You can set a big enough default font size and let the control reduce the text to fit the width. The actual font size will be between minimumFontSize and the size setting of font.
Similar to UILable, UITextField has a property
"adjustsFontSizeToFitWidth"
You can try to set this to YES

image has too big height to display

Please, help me study objective-c!
My program takes a screenshot of whole UIWebView content, saves it, and supposed to display it.
It works fine, until it meets a very long page. Seems like the height of a page is an issue, since it displays 5 Mb screenshots just fine, as long as they are not too long (don't have to much height), however 1Mb but extremely long screenshots do not display in the UIImageView at all. It displays the UIImageView's background and that's it.
My code, attempts to resize the page to be maximum 2000 in height, and minimum 75% of the whole screen size. Aspect ratio is secondary. However, the image is still missing:
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat divider = 2;
CGFloat imageDisplayLimit = 2000;
CGFloat width = _image.size.width;
CGFloat height = _image.size.height;
//determine the leading parameter (just in case of a fat-S image)
if (width > imageDisplayLimit || height > imageDisplayLimit) {
if (width > height) {
divider = width / imageDisplayLimit;
} else {
divider = height / imageDisplayLimit;
}
}
//don't let it get too fat
CGFloat minimumWidth = self.view.frame.size.width / 1.5;
if (width / divider < minimumWidth) {
width = minimumWidth;
} else {
width /= divider;
}
//don't let it get too long
CGFloat minimumHeight = self.view.frame.size.height / 1.5;
if (height / divider < minimumHeight) {
height = minimumHeight;
} else {
height /= divider;
}
_imageView = [[UIImageView alloc] initWithImage:_image];
_imageView.frame = CGRectMake(0, 0, width, height);
//now just to make it obvious - red background
_imageView.backgroundColor = [UIColor redColor];
_imageView.frame = CGRectMake(0, 0, _image.size.width / divider, _image.size.height / divider);
_imageView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin);
_imageView.contentMode = UIViewContentModeScaleAspectFill;
[_scrollView addSubview:_imageView];
_scrollView.contentSize = _imageView.bounds.size;
_scrollView.delegate = self;
//just to make scroll visible during debug
_scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
...
At this point nothing shows, but the red background on a scrollable view.
I'm studying objective-c and don't know A LOT, but I was trying to find a solution for 2 days now. Please, save me!
My guess is aspect fill or fit doesn't do anything just because they don't actually change the image - just a display. What I really should be using (IMHO) is the UIGraphicsBeginImageContext. But I simply don't know how to make it shrink to max 2000 px. I am able to cut it by using
UIGraphicsBeginImageContext(someSizeWith2000Height)
[originalImage drawInRect:CGRectMake(resized_x, resized_y, resized_width, resized_height)];
UIImage* resized_image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
or something like that, but I don't wanna cut it - just shrink (or stretch if too short).
Any ideas? I've run out of those.
Well, since stackoverflow's system is so great, it drops questions between the desks and none can find them, I had to give up on this problem, and the only solution I could come up with is replace UIImageView with UIWebView as an image-displaying view. It makes the image displayed with TERRIBLE quality, but at least it is displayed.
Please, if anyone finds this question by chance and can help.... help! :)

how to set ballon image to the right of the View?

Context:
I am building a chat app, I used code from apple sample.
It looks exactly like the native message app. My issue is on the iPad version I am implementing.
Here's an image:
As you can see in the image, I need it the righ ballon to be on the right edge of the screen
I track down the code, and I narrow down the block of code that needs tweaking.
// Comput the X,Y origin offsets
CGFloat xOffsetLabel;
CGFloat xOffsetBalloon;
CGFloat yOffset;
if (TRANSCRIPT_DIRECTION_SEND == transcript.direction) {//
// Sent messages appear or right of view
xOffsetLabel = 320 - labelSize.width - (BALLOON_WIDTH_PADDING / 2) - 3;
xOffsetBalloon = 320 - balloonSize.width;
yOffset = BUFFER_WHITE_SPACE / 2;
_nameLabel.text = #"";
// Set text color
_messageLabel.textColor = [UIColor whiteColor];
// Set resizeable image
_balloonView.image = [self.balloonImageRight resizableImageWithCapInsets:_balloonInsetsRight];
}
else {
// Received messages appear on left of view with additional display name label
xOffsetBalloon = 0;
xOffsetLabel = (BALLOON_WIDTH_PADDING / 2) + 3;
yOffset = (BUFFER_WHITE_SPACE / 2) + nameSize.height - NAME_OFFSET_ADJUST;
if (TRANSCRIPT_DIRECTION_LOCAL == transcript.direction) {
_nameLabel.text = #"user";
}
else {
_nameLabel.text = #"Admin"; //nameText;
}
// Set text color
_messageLabel.textColor = [UIColor darkTextColor];
// Set resizeable image
_balloonView.image = [self.balloonImageLeft resizableImageWithCapInsets:_balloonInsetsLeft];
}
// Set the dynamic frames
_messageLabel.frame = CGRectMake(xOffsetLabel, yOffset + 5, labelSize.width, labelSize.height);
_balloonView.frame = CGRectMake(xOffsetBalloon, yOffset, balloonSize.width, balloonSize.height);
_nameLabel.frame = CGRectMake(xOffsetLabel - 2, 1, nameSize.width, nameSize.height);
Unfortunately my attempts to place green ballon to the right were unsuccessful(I can only more the content of the text to the right not the ballon itself). any idea ?
Here:
xOffsetLabel = 320 - labelSize.width - (BALLOON_WIDTH_PADDING / 2) - 3;
xOffsetBalloon = 320 - balloonSize.width;
320 is the width of the iPhone screen. That needs to be changed to the width of the iPad (either 1024 or 768 depending on the orientation).
Of course your view also needs to be as wide as the iPad screen, so make sure that that's resized too.
Tim

UIScrollview Dynamic content size is very off based on number of items

I have a vertical scrollview with thumbnail images to act as a "side panel" for specific items on an ipad app.
Here's my code to set the content size:
- (void)setScrollViewContentSize:(UIScrollView*)scrollView{
NSInteger viewCount = [scrollView.subviews count];
NSLog(#"viewCount: %d", viewCount);
NSLog(#"height: %f", (viewCount * 190.0f));
scrollView.contentSize = CGSizeMake( scrollView.superview.frame.size.width, (viewCount * 190.0f));
}
When I run my app, there's one menu that has 57 items, so the viewCount log shows up as 57 and the height shows up as 10830. On another menu, I have 13 items and thus, the height is 2470.
Everything seems fine here, but when I scroll to the end of the view, the menu with 57 icons has way too much white space left over whereas the menu with 13 items ends perfectly on the last item with a little margin (each thumbnail is 183px). I'm trying to find out what the cause is, but it seems like the more menu items I have, the bigger the scroll view's spacing at the last item gets.
I tried calling scrollView sizeToFit and even trying to create a CGRect of a visible region to apple to my frame, but none of those worked. Any ideas?
thank you.
from https://stackoverflow.com/a/14852596/1363779
float sizeOfContent = 0;
UIView *lLast = [scrollView.subviews lastObject];
NSInteger wd = lLast.frame.origin.y;
NSInteger ht = lLast.frame.size.height;
sizeOfContent = wd+ht;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent);
This is a nice and easy way to do it.
Swift 2.0 version
var sizeOfContent: CGFloat = 0
let lLast: UIView = scrollView.subviews.last!
let wd: CGFloat = lLast.frame.origin.y
let ht: CGFloat = lLast.frame.size.height
sizeOfContent = wd + ht
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, sizeOfContent)

Resources