UILabel Over UISlider Thumb - objective-c

How can i put an UILabel over the thumb of UISlider...so that when i move the thumb....UILabel will also move....as it is on the thumb...
Any idea??

Try this
yourLabel = [[UILabel alloc]initWithFrame:....];
//Call this method on Slider value change event
-(void)sliderValueChanged{
CGRect trackRect = [self.slider trackRectForBounds:self.slider.bounds];
CGRect thumbRect = [self.slider thumbRectForBounds:self.slider.bounds
trackRect:trackRect
value:self.slider.value];
yourLabel.center = CGPointMake(thumbRect.origin.x + self.slider.frame.origin.x, self.slider.frame.origin.y - 20);
}
I could get most accurate value by using this snippet.

The "knob" isn't available per public API, so bad chances for hooking it up - if it is a subview at all and not just drawn directly.
So you should add you label to the same view as the slider (make sure you add it later so that appears over it). You can then listen for the value change events and place your label accordingly. It is linear scaling between the endpoints that you need to figure out at first, but it shouldn't be too difficult.
Edit with code:
yourLabel = [[UILabel alloc]initWithFrame:....];
// .. configure label
[[yourSlider superview] addSubview:yourLabel];
[yourSlider addTarget:self action:#selector(adjustLabelForSlider:) forControlEvents:UIControlEventValueChanged];
-(void)adjustLabelForSlider:(id)slider
{
float value = slider.value;
float min = slider.minimumValue;
float max = slider.maximumValue;
CGFloat newX = ...; // Calculate based on yourSlider.frame and value, min, and max
CGFloat newY = ...;
[yourLabel setCenter:CGPointMake(newX,newY)];
}
Note: untested code ;-)

Same answer with swift3:
let trackRect: CGRect = slider.trackRect(forBounds: slider.bounds)
let thumbRect: CGRect = slider.thumbRect(forBounds: slider.bounds , trackRect: trackRect, value: slider.value)
let x = thumbRect.origin.x + slider.frame.origin.x
let y = slider.frame.origin.y - 20
sliderLabel.center = CGPoint(x: x, y: y)

extension UIImage {
class func imageWithLabel(_ label: UILabel) -> UIImage {
UIGraphicsBeginImageContextWithOptions(label.bounds.size, false, 0)
defer { UIGraphicsEndImageContext() }
label.layer.render(in: UIGraphicsGetCurrentContext()!)
return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
}
}
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITextFieldDelegate, UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDataSource, UIScrollViewDelegate
{
func maskRoundedImage(image: UIImage, radius: CGFloat) -> UIImage {
let imageView: UIImageView = UIImageView(image: image)
let layer = imageView.layer
layer.masksToBounds = true
layer.cornerRadius = radius
UIGraphicsBeginImageContext(imageView.bounds.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return roundedImage!
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 28, height: 28))
label.backgroundColor = .black
label.textAlignment = .center
label.font = label.font.withSize(12)
label.text = String(Int(round( backlightSlider.value * 100 )))
label.textColor = .white
var image = UIImage.imageWithLabel(label)
image = maskRoundedImage(image: image, radius: 14.0)
backlightSlider.setThumbImage(image, for: .normal)
}

Just add an imageview on the thumb of slider add a label on imageview
- (IBAction)valueChangedSlider:(id)sender {
handleView = [_slider.subviews lastObject];
label = [[UILabel alloc] initWithFrame:handleView.bounds];
label = (UILabel*)[handleView viewWithTag:1000];
if (label==nil) {
label = [[UILabel alloc] initWithFrame:handleView.bounds];
label.tag = 1000;
[label setFont:[UIFont systemFontOfSize:12]];
label.textColor = [UIColor redColor];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
[handleView addSubview:label];
}
label.text = [NSString stringWithFormat:#"%0.2f", self.slider.value];
}

If anybody is looking for answer in Swift, please take a look of my answer here:- Put Label over UISlider Thumb
It'll work like a charm :)

This could be very helpful...
How to get the center of the thumb image of UISlider

Related

Objective c label.numberOflines is not working [duplicate]

Consider I have the following text in a UILabel (a long line of dynamic text):
Since the alien army vastly outnumbers the team, players must use the post-apocalyptic world to their advantage, such as seeking cover behind dumpsters, pillars, cars, rubble, and other objects.
I want to resize the UILabel's height so that the text can fit in. I'm using following properties of UILabel to make the text within to wrap.
myUILabel.lineBreakMode = UILineBreakModeWordWrap;
myUILabel.numberOfLines = 0;
Please let me know if I'm not heading in the right direction. Thanks.
sizeWithFont constrainedToSize:lineBreakMode: is the method to use. An example of how to use it is below:
//Calculate the expected size based on the font and linebreak mode of your label
// FLT_MAX here simply means no constraint in height
CGSize maximumLabelSize = CGSizeMake(296, FLT_MAX);
CGSize expectedLabelSize = [yourString sizeWithFont:yourLabel.font constrainedToSize:maximumLabelSize lineBreakMode:yourLabel.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = yourLabel.frame;
newFrame.size.height = expectedLabelSize.height;
yourLabel.frame = newFrame;
You were going in the right direction. All you need to do is:
myUILabel.numberOfLines = 0;
myUILabel.text = #"Enter large amount of text here";
[myUILabel sizeToFit];
In iOS 6 Apple has added a property to UILabel that greatly simplifies dynamic vertical resizing of labels: preferredMaxLayoutWidth.
Using this property in combination with lineBreakMode = NSLineBreakByWordWrapping and sizeToFit method allows easily resize a UILabel instance to the height that accommodates the entire text.
A quote from iOS documentation:
preferredMaxLayoutWidth
The preferred maximum width (in points) for a multiline label.
Discussion
This property affects the size of the label when layout constraints are applied to it. During layout, if the text extends beyond the width specified by this property, the additional text is flowed to one or more new lines, thereby increasing the height of the label.
A sample:
...
UILabel *status = [[UILabel alloc] init];
status.lineBreakMode = NSLineBreakByWordWrapping;
status.numberOfLines = 5; // limits to 5 lines; use 0 for unlimited.
[self addSubview:status]; // self here is the parent view
status.preferredMaxLayoutWidth = self.frame.size.width; // assumes the parent view has its frame already set.
status.text = #"Some quite lengthy message may go hereā€¦";
[status sizeToFit];
[status setNeedsDisplay];
...
Check this work perfectly without adding Single line of code. (Using Autolayout)
I made a demo for you according to your requirement. Download it from below link,
Autoresize UIView and UILabel
Step by Step Guide :-
Step 1 :- Set constrain to UIView
1) Leading 2) Top 3) Trailing (From mainview)
Step 2 :- Set constrain to Label 1
1) Leading 2) Top 3) Trailing (From it's superview)
Step 3 :- Set constrain to Label 2
1) Leading 2) Trailing (From it's superview)
Step 4 :- Most tricky give botton to UILabel from UIView .
Step 5 :- (Optional) Set constrain to UIButton
1) Leading 2) Bottom 3) Trailing 4) Fixed Height (From mainview)
Output :-
Note :- Make sure you have set Number of lines =0 in Label property.
I hope this info enough to understand Autoresize UIView according to UILabel's height and Autoresize UILabel According to text.
Instead doing this programmatically, you can do this in Storyboard/XIB while designing.
Set UIlabel's number of lines property to 0 in attribute inspector.
Then set width constraint/(or) leading and trailing constraint as per the requirement.
Then set height constraint with minimum value. Finally select the height constraint you added and in the size inspector the one next to attribute inspector, change the height constraint's relation from equal to - greater than.
Thanks guys for help, here is the code I tried which is working for me
UILabel *instructions = [[UILabel alloc]initWithFrame:CGRectMake(10, 225, 300, 180)];
NSString *text = #"First take clear picture and then try to zoom in to fit the ";
instructions.text = text;
instructions.textAlignment = UITextAlignmentCenter;
instructions.lineBreakMode = NSLineBreakByWordWrapping;
[instructions setTextColor:[UIColor grayColor]];
CGSize expectedLabelSize = [text sizeWithFont:instructions.font
constrainedToSize:instructions.frame.size
lineBreakMode:UILineBreakModeWordWrap];
CGRect newFrame = instructions.frame;
newFrame.size.height = expectedLabelSize.height;
instructions.frame = newFrame;
instructions.numberOfLines = 0;
[instructions sizeToFit];
[self addSubview:instructions];
Solution to iOS7 prior and iOS7 above
//
// UILabel+DynamicHeight.m
// For StackOverFlow
//
// Created by Vijay on 24/02/14.
// Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//
#import <UIKit/UIKit.h>
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define iOS7_0 #"7.0"
#interface UILabel (DynamicHeight)
/*====================================================================*/
/* Calculate the size,bounds,frame of the Multi line Label */
/*====================================================================*/
/**
* Returns the size of the Label
*
* #param aLabel To be used to calculte the height
*
* #return size of the Label
*/
-(CGSize)sizeOfMultiLineLabel;
#end
//
// UILabel+DynamicHeight.m
// For StackOverFlow
//
// Created by Vijay on 24/02/14.
// Copyright (c) 2014 http://Vijay-Apple-Dev.blogspot.com. All rights reserved.
//
#import "UILabel+DynamicHeight.h"
#implementation UILabel (DynamicHeight)
/*====================================================================*/
/* Calculate the size,bounds,frame of the Multi line Label */
/*====================================================================*/
/**
* Returns the size of the Label
*
* #param aLabel To be used to calculte the height
*
* #return size of the Label
*/
-(CGSize)sizeOfMultiLineLabel{
NSAssert(self, #"UILabel was nil");
//Label text
NSString *aLabelTextString = [self text];
//Label font
UIFont *aLabelFont = [self font];
//Width of the Label
CGFloat aLabelSizeWidth = self.frame.size.width;
if (SYSTEM_VERSION_LESS_THAN(iOS7_0)) {
//version < 7.0
return [aLabelTextString sizeWithFont:aLabelFont
constrainedToSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
lineBreakMode:NSLineBreakByWordWrapping];
}
else if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(iOS7_0)) {
//version >= 7.0
//Return the calculated size of the Label
return [aLabelTextString boundingRectWithSize:CGSizeMake(aLabelSizeWidth, MAXFLOAT)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{
NSFontAttributeName : aLabelFont
}
context:nil].size;
}
return [self bounds].size;
}
#end
Since sizeWithFont is deprecated I use this one instead.
this one get label specific attributes.
-(CGFloat)heightForLabel:(UILabel *)label withText:(NSString *)text{
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:#{NSFontAttributeName:label.font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){label.frame.size.width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
return ceil(rect.size.height);
}
UILabel extension based on this answer for Swift 4 and above
extension UILabel {
func retrieveTextHeight () -> CGFloat {
let attributedText = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName:self.font])
let rect = attributedText.boundingRect(with: CGSize(width: self.frame.size.width, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
return ceil(rect.size.height)
}
}
Can be used like:
self.labelHeightConstraint.constant = self.label.retrieveTextHeight()
Here is a category version:
UILabel+AutoSize.h
#import
#interface UILabel (AutoSize)
- (void) autosizeForWidth: (int) width;
#end
UILabel+AutoSize.m
#import "UILabel+AutoSize.h"
#implementation UILabel (AutoSize)
- (void) autosizeForWidth: (int) width {
self.lineBreakMode = UILineBreakModeWordWrap;
self.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(width, FLT_MAX);
CGSize expectedLabelSize = [self.text sizeWithFont:self.font constrainedToSize:maximumLabelSize lineBreakMode:self.lineBreakMode];
CGRect newFrame = self.frame;
newFrame.size.height = expectedLabelSize.height;
self.frame = newFrame;
}
#end
You can implement TableViewController's (UITableViewCell *)tableView:cellForRowAtIndexPath method in the following way (for example) :
#define CELL_LABEL_TAG 1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *text = #"my long text";
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier] autorelease];
}
CGFloat width = [UIScreen mainScreen].bounds.size.width - 50;
CGFloat height = [self textHeight:text] + 10;
CGRect frame = CGRectMake(10.0f, 10.0f, width, height);
UILabel *cellLabel = [[UILabel alloc] initWithFrame:frame];
cellLabel.tag = CELL_LABEL_TAG;
cellLabel.textColor = [UIColor blackColor];
cellLabel.backgroundColor = [UIColor clearColor];
cellLabel.textAlignment = UITextAlignmentLeft;
cellLabel.font = [UIFont systemFontOfSize:12.0f];
[cell.contentView addSubview:cellLabel];
[cellLabel release];
return cell;
}
UILabel *label = (UILabel *)[cell viewWithTag:CELL_LABEL_TAG];
label.text = text;
label.numberOfLines = 0;
[label sizeToFit];
return cell;
Also use NSString's sizeWithFont:constrainedToSize:lineBreakMode: method to compute the text's height.
My approach to compute the dynamic height of UILabel.
let width = ... //< width of this label
let text = ... //< display content
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.preferredMaxLayoutWidth = width
// Font of this label.
//label.font = UIFont.systemFont(ofSize: 17.0)
// Compute intrinsicContentSize based on font, and preferredMaxLayoutWidth
label.invalidateIntrinsicContentSize()
// Destination height
let height = label.intrinsicContentSize.height
Wrap to function:
func computeHeight(text: String, width: CGFloat) -> CGFloat {
// A dummy label in order to compute dynamic height.
let label = UILabel()
label.numberOfLines = 0
label.lineBreakMode = .byWordWrapping
label.font = UIFont.systemFont(ofSize: 17.0)
label.preferredMaxLayoutWidth = width
label.text = text
label.invalidateIntrinsicContentSize()
let height = label.intrinsicContentSize.height
return height
}
And for those that are migrating to iOS 8, here is a class extension for Swift:
extension UILabel {
func autoresize() {
if let textNSString: NSString = self.text {
let rect = textNSString.boundingRectWithSize(CGSizeMake(self.frame.size.width, CGFloat.max),
options: NSStringDrawingOptions.UsesLineFragmentOrigin,
attributes: [NSFontAttributeName: self.font],
context: nil)
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, rect.height)
}
}
}
The easiest and better way that worked for me was to apply height constraint to label and set the priority to low, i.e., (250) in storyboard.
So you need not worry about calculating the height and width programmatically, thanks to storyboard.
Updated Method
+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {
CGSize constraint = CGSizeMake(width, 20000.0f);
CGSize size;
CGSize boundingBox = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
return size.height;
}
This is one line of code to get the UILabel Height using Objective-c:
labelObj.numberOfLines = 0;
CGSize neededSize = [labelObj sizeThatFits:CGSizeMake(screenWidth, CGFLOAT_MAX)];
and using .height you will get the height of label as follows:
neededSize.height
You can get height using below code
You have to pass
text 2. font 3. label width
func heightForLabel(text: String, font: UIFont, width: CGFloat) -> CGFloat {
let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.height
}
Thanks for this post. It helped me a great deal. In my case I am also editing the text in a separate view controller. I noticed that when I use:
[cell.contentView addSubview:cellLabel];
in the tableView:cellForRowAtIndexPath: method that the label view was continually rendered over the top of the previous view each time I edited the cell. The text became pixelated, and when something was deleted or changed, the previous version was visible under the new version. Here's how I solved the problem:
if ([[cell.contentView subviews] count] > 0) {
UIView *test = [[cell.contentView subviews] objectAtIndex:0];
[test removeFromSuperview];
}
[cell.contentView insertSubview:cellLabel atIndex:0];
No more weird layering. If there is a better way to handle this, Please let me know.
UILabel *itemTitle = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 10,100, 200.0f)];
itemTitle.text = #"aseruy56uiytitfesh";
itemTitle.adjustsFontSizeToFitWidth = NO;
itemTitle.autoresizingMask = UIViewAutoresizingFlexibleWidth;
itemTitle.font = [UIFont boldSystemFontOfSize:18.0];
itemTitle.textColor = [UIColor blackColor];
itemTitle.shadowColor = [UIColor whiteColor];
itemTitle.shadowOffset = CGSizeMake(0, 1);
itemTitle.backgroundColor = [UIColor blueColor];
itemTitle.lineBreakMode = UILineBreakModeWordWrap;
itemTitle.numberOfLines = 0;
[itemTitle sizeToFit];
[self.view addSubview:itemTitle];
use this here all the properties are used on the label and test it by increasing the text in the itemTitle.text as
itemTitle.text = #"diofgorigjveghnhkvjteinughntivugenvitugnvkejrfgnvkhv";
it will show the perfetc answer as you need
You may use it as a method, as well. #Pyjamasam is very much true so i am just making its method. It may be helpfull for some one else
-(CGRect)setDynamicHeightForLabel:(UILabel*)_lbl andMaxWidth:(float)_width{
CGSize maximumLabelSize = CGSizeMake(_width, FLT_MAX);
CGSize expectedLabelSize = [_lbl.text sizeWithFont:_lbl.font constrainedToSize:maximumLabelSize lineBreakMode:_lbl.lineBreakMode];
//adjust the label the the new height.
CGRect newFrame = _lbl.frame;
newFrame.size.height = expectedLabelSize.height;
return newFrame;
}
and just set it like this
label.frame = [self setDynamicHeightForLabel:label andMaxWidth:300.0];
To do this in Swift3 following is the code:
let labelSizeWithFixedWith = CGSize(width: 300, height: CGFloat.greatestFiniteMagnitude)
let exactLabelsize = self.label.sizeThatFits(labelSizeWithFixedWith)
self.label.frame = CGRect(origin: CGPoint(x: 20, y: 20), size: exactLabelsize)
Adding to the above answers:
This can be easily achieved via storyboard.
Set constraint for UILabel.(In my case I did top, left and fixed width)
Set Number of line to 0 in Attribute Inspector
Set Line Break to WordWrap in Attribute Inspector.
One line is Chris's answer is wrong.
newFrame.size.height = maximumLabelSize.height;
should be
newFrame.size.height = expectedLabelSize.height;
Other than that, it's the correct solution.
Finally, it worked. Thank you guys.
I was not getting it to work because i was trying to resize the label in heightForRowAtIndexPath method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
and (yeah silly me), i was resizing the label to default in cellForRowAtIndexPath method - i was overlooking the code i had written earlier:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cellIdentifier = #"myCell";
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell.myUILabel.lineBreakMode = UILineBreakModeWordWrap;
cell.myUILabel.numberOfLines = 0;
cell.myUILabel.text = #"Some very very very very long text....."
[cell.myUILabel.criterionDescriptionLabel sizeToFit];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat rowHeight = cell.myUILabel.frame.size.height + 10;
return rowHeight;
}
NSString *str = #"Please enter your text......";
CGSize lblSize = [str sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize: CGSizeMake(200.0f, 600.0f) lineBreakMode: NSLineBreakByWordWrapping];
UILabel *label = [[UILabel alloc]init];
label.frame = CGRectMake(60, 20, 200, lblSize.height);
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.font = [UIFont systemFontOfSize:15];
label.text = str;
label.backgroundColor = [UIColor clearColor];
[label sizeToFit];
[self.view addSubview:label];
My code:
UILabel *label = [[UILabel alloc] init];
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
label.text = text;
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont fontWithName:_bodyTextFontFamily size:_bodyFontSize];
CGSize size = [label sizeThatFits:CGSizeMake(width, MAXFLOAT)];
float height = size.height;
label.frame = CGRectMake(x, y, width, height);
This method will give perfect height
-(float) getHeightForText:(NSString*) text withFont:(UIFont*) font andWidth:(float) width{
CGSize constraint = CGSizeMake(width , 20000.0f);
CGSize title_size;
float totalHeight;
title_size = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{ NSFontAttributeName : font }
context:nil].size;
totalHeight = ceil(title_size.height);
CGFloat height = MAX(totalHeight, 40.0f);
return height;
}
Swift 2:
yourLabel.text = "your very long text"
yourLabel.numberOfLines = 0
yourLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
yourLabel.frame.size.width = 200
yourLabel.frame.size.height = CGFloat(MAXFLOAT)
yourLabel.sizeToFit()
The interesting lines are sizeToFit() in conjunction with setting a frame.size.height to the max float, this will give room for long text, but sizeToFit() will force it to only use the necessary, but ALWAYS call it after setting the .frame.size.height .
I recommend setting a .backgroundColor for debug purposes, this way you can see the frame being rendered for each case.
myLabel.text = "your very long text"
myLabel.numberOfLines = 0
myLabel.lineBreakMode = NSLineBreakMode.ByWordWrapping
Please set constraints for UILable in storyboard including top left bottom right

Dynamic height for textview in ios?

I have added a UITextView inside a UIView. UIView has some height depending upon screen sizes. UITextView can have more or less text. So I want to make the height of UITextView dynamic so if text is more then it should have more height but it should be less than the height of main view . If text is less then it should have less height.
Size a UITextView to its content programmatically:
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[textView setDelegate:self];
[textView setText:#"your long text"];
[textView setScrollEnabled:NO];
[self.view addSubview:textView];
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
textView.frame = newFrame;
If you are using textview to display multilines of text with scrolling disabled, It is nothing more than a UILabel. I suggest you to use UILabel for the purpose.
In the storyboard, set the constraints as follows:
and set the line break as word wrap:
Same as the first answer, but in Swift 4:
let screenSize = UIScreen.main.bounds
let textView = UITextView.init(frame: CGRect(x: 1, y: 40, width: screenSize.width, height: screenSize.height))
textView.delegate = self as? UITextViewDelegate
textView.isScrollEnabled = false
view.addSubview(textView)
let fixedWidth = textView.frame.size.width
let newSize: CGSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat(MAXFLOAT)))
var newFrame = textView.frame
newFrame.size = CGSize(width: CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), height: newSize.height)
Try with this
-(void)dynamicTextSize{
UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(200, 300, 200, 30)];
textView.center = self.view.center;
[self.view addSubview:textView];
NSString *string = #"This is pour text.a hjajksdkja kajhdsjk akjdhs jakhd skjahs ajkdhsjkad hskja akjdhs ajkhdjskar";
textView.text = string;
//UIFont *font = [UIFont fontWithName:#"Arial" size:16.0f];
NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys:textView.font, NSFontAttributeName, nil];
textView.backgroundColor = [UIColor lightGrayColor];
CGRect frame = [textView.text boundingRectWithSize:CGSizeMake(textView.frame.size.width, 10000) options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin attributes:attrDict context:nil];
CGRect mFrame = textView.frame;
mFrame.size.width = frame.size.width;
mFrame.size.height = frame.size.height;
textView.frame = mFrame;
//NSLog(#"frame2:%#",NSStringFromCGRect(textView.frame));
}

UIBarButtonItem with custom view not properly aligned on iOS 7 when used as left or right navigation bar items

The following code works up through iOS 6:
UIButton *myButton = nil;
myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.bounds = CGRectMake(0,0,44,30);
// setup myButton's images, etc.
UIBarButtonItem *item = nil;
item = [[UIBarButtonItem alloc] initWithCustomView:customButton];
This is how the button is supposed to be aligned:
However, on iOS 7, the button appears to be offset from the right or left by too many pixels:
How can I get my custom bar button items to be aligned properly?
Works until iOS11!
You can use negative flexible spaces and rightBarButtonItems property instead of rightBarButtonItem:
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
spacer.width = -10; // for example shift right bar button to the right
self.navigationItem.rightBarButtonItems = #[spacer, yourBarButton];
In order to fix this bug, you must subclass UIButton so that you can override alignmentRectInsets. From my testing, you'll need to return a UIEdgeInsets with either a positive right offset or a positive left offset, depending on the button position. These numbers make no sense to me (at least one of them should be negative, according to common sense), but this is what actually works:
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (IF_ITS_A_LEFT_BUTTON) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF_ITS_A_RIGHT_BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}
Special thanks to #zev for suggesting I try adjusting alignmentRectInsets.
I have tried all of the answers above and nothing worked for me. And here is what works, if anyone would need this:
(No subclassing needed)
// Add your barButtonItem with custom image as the following
UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStyleBordered target:self action:#selector(categoryButtonPressed)];
// set your custom image
[barButton setImage:categoryImage];
// finally do the magic
barButton.imageInsets = UIEdgeInsetsMake(0.0, -20, 0, 0);
-Take a look at the result.
Notice the space to the left button and from the right button (the
right button has the default behavior)
Ok, I went the other "direction". I made everything line up properly via Storyboard with iOS 7 (assuming this is how it will continue to work). And then using the describe sub-class approach, I sub-class UIButton with the following implementation.
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (SYSTEM_VERSION_LESS_THAN(#"7.0")) {
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, -10, 0, 0);
} else {
insets = UIEdgeInsetsMake(0, 0, 0, -10);
}
} else {
insets = UIEdgeInsetsZero;
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.origin.x < (self.superview.frame.size.width / 2);
}
So this code only runs if the device is pre-iOS 7.
Thanks for the insight #jaredsinclair!
#jaredsinclair
Here is a look at my code.
// Create the tweetly button that will show settings
self.tweetlyDisplay = [NavButton buttonWithType:UIButtonTypeCustom];
[self.tweetlyDisplay setFrame:CGRectMake(0, 0, 90, 44)];
[self.tweetlyDisplay setBackgroundColor:[UIColor clearColor]];
[self.tweetlyDisplay setBackgroundImage:[UIImage imageNamed:#"settings.png"] forState:UIControlStateNormal];
[self.tweetlyDisplay setAdjustsImageWhenHighlighted:NO];
[self.tweetlyDisplay addTarget:self action:#selector(tweetlyPressed:) forControlEvents:UIControlEventTouchUpInside];
// Add the Tweetly button as the left bar button item
// This had a glitch that moves the image to the right somewhat
UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithCustomView:self.tweetlyDisplay];
self.navigationItem.leftBarButtonItem = leftBarButton;
See anything that isnt right?
Here is the result. The second image is not so visible because I had to time taking the screenshot and it is still in transition, but you can clearly see how it is improperly offset.
Good normal image:
Bad Offset Image:
After about a half second, the image then snaps back to the original image location.
Here is my code for the NavButton.h and .m:
/**********************************************
NavButton.h
**********************************************/
#import <UIKit/UIKit.h>
#interface NavButton : UIButton
#end
/**********************************************
NavButton.m
**********************************************/
#import "NavButton.h"
#implementation NavButton {
int imageHeight;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
imageHeight = 44;
}
return self;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF ITS A RIGHT BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.origin.x < (self.superview.frame.size.width / 2);
}
// THIS IS THE TRICK. We make the height of the background rect match the image.
-(CGRect)backgroundRectForBounds:(CGRect)bounds
{
CGRect bgRect = bounds;
bgRect.origin.y = (bounds.size.height - imageHeight)/2.0f;
bgRect.size.height = imageHeight;
return bgRect;
}
#end
A better solution without jumping buttons arround can be found here:
Custom UIBarButtonItem alignment off with iOS7
Not a huge fan of subclassing UIButton or method swizzling from Marius's answer: https://stackoverflow.com/a/19317105/287403
I just used a simple wrapper, and moved the button's frame's x in a negative direction until I found the correct positioning. Button tapping appears to be fine as well (although you could extend the width of the button to match the negative offset if you needed).
Here's the code I use to generate a new back button:
- (UIBarButtonItem *) newBackButton {
// a macro for the weak strong dance
#weakify(self);
UIButton *backButton = [[UIButton alloc] init];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
backButton.titleLabel.font = [UIFont systemFontOfSize:17];
CGFloat width = [#"Back" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading|NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:nil].size.width + 27;
backButton.frame = CGRectMake(-17.5, 0, width + 17.5, 44);
[backButton setImage:[UIImage imageNamed:#"UINavigationBarBackIndicatorDefault"] forState:UIControlStateNormal];
[backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 14, 0, 0)];
[backButton setTitleColor:mTCOrangeColor forState:UIControlStateNormal];
backButton.contentEdgeInsets = UIEdgeInsetsZero;
backButton.imageEdgeInsets = UIEdgeInsetsZero;
[backButton addEventHandler:^(id sender) {
// a macro for the weak strong dance
#strongify(self);
// do stuff here
} forControlEvents:UIControlEventTouchUpInside];
UIView *buttonWrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)];
[buttonWrapper addSubview:backButton];
return [[UIBarButtonItem alloc] initWithCustomView:buttonWrapper];
}
I would like to add to #jaredsinclair confirmed answer the below override methods to those who have text and/or image in their navigation button, otherwise the text and the image won't be aligned (only the background image):
- (UIEdgeInsets) titleEdgeInsets {
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
if (IF_ITS_A_LEFT_BUTTON) {
{
return UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
else
{ // IF_ITS_A_RIGHT_BUTTON
return UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
}
return [super titleEdgeInsets];
}
- (UIEdgeInsets)imageEdgeInsets {
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
if (IF_ITS_A_LEFT_BUTTON)
{
return UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
else
{ // IF_ITS_A_RIGHT_BUTTON
return UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
}
return [super imageEdgeInsets];
}
p.s. the macro is:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
*Solution found, read on the end of the answer.*
#jaredsinclair
I have similar case as Kyle Begeman
This is the button
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
}
return self;
}
- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")){
if ([self isLeftButton]) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
} else {
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
}else{
insets = UIEdgeInsetsZero;
}
return insets;
}
- (BOOL)isLeftButton {
return self.frame.origin.x < (self.superview.frame.size.width / 2);
}
and I use it in this case
PBNavigationBarButton *dashboardButton = [PBNavigationBarButton buttonWithType:UIButtonTypeCustom];
UIImage *dashboardImage = [UIImage imageNamed:#"btn_dashboard.png"];
UIImage *dashboardImageHighlighted = [UIImage imageNamed:#"btn_dashboard_pressed.png"];
NSInteger halfImageWidth = ceilf([dashboardImage size].width/2.0f);
[dashboardButton setBackgroundImage:[dashboardImage stretchableImageWithLeftCapWidth:halfImageWidth topCapHeight:0] forState:UIControlStateNormal];
[dashboardButton setBackgroundImage:[dashboardImageHighlighted stretchableImageWithLeftCapWidth:halfImageWidth topCapHeight:0] forState:UIControlStateHighlighted];
[dashboardButton addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[dashboardButton sizeToFit];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:dashboardButton];
Everything looks great except that, when I go back to the previous VC, the button repositions itself. Like a small jump.
For me it does jump right away not after a second. And it happens after I go do the popVC from NavigationViewController.
Edit: The answer below, the swizzling method from Marius helped me as well.
I came up with a shortened Version of jaredsinclair's approach:
- (UIEdgeInsets)alignmentRectInsets {
return [self isLeftButton] ? UIEdgeInsetsMake(0, 9.0f, 0, 0) : UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
- (BOOL)isLeftButton {
return self.frame.origin.x < (self.superview.frame.size.width / 2);
}
Works like a charm.
in ios7 you can just add a dummy barbuttonitem
for fixing left space you should add dummy as first, for right as last
example for left, you should add this after setting your original items or in viewdidload if you are setting buttons using storyboard.
NSMutableArray *buttons = [[NSMutableArray alloc] init];
UIBarButtonItem *spacerItem = [[UIBarButtonItem alloc] init];
[buttons addObject:spacerItem];
for(UIBarButtonItem *item in self.leftBarButtonItems){
[buttons addObject:item];
}
[self setLeftBarButtonItems:[NSArray arrayWithArray:buttons] animated:NO];
It just simply adjust imageEdgeInsets to fix this bug.
try this.
UIButton *actionBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
[actionBtn setImage:[UIImage imageNamed:#"arrow.png"] forState:UIControlStateNormal];
[actionBtn addTarget:self action:#selector(goToSetting) forControlEvents:UIControlEventTouchUpInside];
actionBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 9, 0, -9);
UIBarButtonItem *profileBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:actionBtn];
self.topViewController.navigationItem.rightBarButtonItems = #[profileBarButtonItem];
Tested in iOS 11
public lazy var navigationBackBarButton : UIBarButtonItem = {
let backBarButtonIcon = <Image Literal here>
let backBarButton = UIBarButtonItem(image: backBarButtonIcon, style: .plain, target: self, action: #selector(self.backBarButtonTouched(_:)))
backBarButton.imageInsets = UIEdgeInsets(top: 0.0, left: -9.0, bottom: 0.0, right: 0.0)
return backBarButton
}()
2018, iOS 11+, Swift 4.x, this worked for me.
Combining the top answers:
Property
internal lazy var button_Favorite: UIButton = {
let button = UIButton(type: .custom)
button.setImage(.favNormal, for: .normal)
button.contentHorizontalAlignment = .right
button.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -9.0)
return button
}()
In viewDidLoad:
let barButton = UIBarButtonItem(customView: self.button_Favorite)
self.button_Favorite.frame = CGRect(x: 0, y: 0, width: 40.0, height: 44.0)
let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
negativeSpacer.width = -10.0
self.navigationItem.rightBarButtonItems = [negativeSpacer, barButton]
Change the following for your UIButton
Control -> Alignment -> Horizontal to Align Right

UILabel how to get label to autosize a name to a maximum width and truncate?

So I've got this UILabel that I'd like to have it auto size to a maximum width, stop, then truncate. The reason for the autosize is that there is another label (date) that I'd like to be just to the right of this by a set amount of pixels (10px).
I've attempted to use a frame on the UILabel but that just statically sets the width,but that didn't work and I need this to auto size...
Screenshot below.
The basic idea is to use size to fit for whenever the label is not too long, then "cut" it off when it's too long. It's pretty much as simple as it sounds.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(32, 96, 90, 16)];
label.backgroundColor = [UIColor greenColor];
label.font = [UIFont fontWithName:#"Helvetica" size:label.frame.size.height];
label.text = #"Johnny Appleseed";
[label sizeToFit];
[self addSubview:label];
const int CUT_OFF_AT_X = 100;
float labelRight = label.frame.origin.x + label.frame.size.width;
if (labelRight > CUT_OFF_AT_X) {
label.frame = CGRectMake(label.frame.origin.x, label.frame.origin.y, CUT_OFF_AT_X - label.frame.origin.x, label.frame.size.height);
}
labelRight = label.frame.origin.x + label.frame.size.width;
UILabel *badge = [[UILabel alloc] initWithFrame:CGRectMake(labelRight, 96, 90, 16)];
badge.backgroundColor = [UIColor redColor];
badge.font = label.font;
badge.text = #"LEVEL 90";
[badge sizeToFit];
[self addSubview:badge];
Great answer! For swift 3:
if traitCollection.horizontalSizeClass == .compact && ((lbl_FacilityName.text?.length ?? 0) > 15) {
print("if traitCollection.horizontalSizeClass == .compact and label larger than 15 chars ")
//If label is too long cut the width off at the start of the segmented control -3 for padding
lbl_FacilityName.frame = CGRect(x: lbl_FacilityName.frame.origin.x, y: lbl_FacilityName.frame.origin.y, width: ((segPatientSortControl.frame.origin.x - 3) - lbl_FacilityName.frame.origin.x), height: lbl_FacilityName.frame.size.height)
}

IOS: create a UIImage or UIImageView with rounded corners

Is it possible create an UIImage or an UIImageView with rounded corners? Because I want take an UIImage and show it inside an UIImageView, but I don't know how to do it.
Yes, it is possible.
Import the QuartzCore (#import <QuartzCore/QuartzCore.h>) header and play with the layer property of the UIImageView.
yourImageView.layer.cornerRadius = yourRadius;
yourImageView.clipsToBounds = YES;
See the CALayer class reference for more info.
Try this Code For Round Image Import QuartzCore framework
simple way to create Round Image
imageView.layer.backgroundColor=[[UIColor clearColor] CGColor];
imageView.layer.cornerRadius=20;
imageView.layer.borderWidth=2.0;
imageView.layer.masksToBounds = YES;
imageView.layer.borderColor=[[UIColor redColor] CGColor];
Objective-C
-(UIImage *)makeRoundedImage:(UIImage *) image
radius: (float) radius;
{
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height);
imageLayer.contents = (id) image.CGImage;
imageLayer.masksToBounds = YES;
imageLayer.cornerRadius = radius;
UIGraphicsBeginImageContext(image.size);
[imageLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return roundedImage;
}
Swift 3
func makeRoundedImage(image: UIImage, radius: Float) -> UIImage {
var imageLayer = CALayer()
imageLayer.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
imageLayer.contents = image.cgImage
imageLayer.masksToBounds = true
imageLayer.cornerRadius = radius
UIGraphicsBeginImageContext(image.size)
imageLayer.render(in: UIGraphicsGetCurrentContext())
var roundedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return roundedImage
}
uiimageview.layer.cornerRadius = uiimageview.frame.size.height/2;
uiimageview.clipToBounds = YES;
#import <QuartzCore/QuartzCore.h>
// UIImageView+OSExt.h
#import <UIKit/UIKit.h>
#interface UIImageView (OSExt)
- (void)setBorder:(CGFloat)borderWidth color:(UIColor*)color;
#end
// UIImageView+OSExt.m
#import "UIImageView+OSExt.h"
#implementation UIImageView (OSExt)
- (void)layoutSublayersOfLayer:(CALayer *)layer
{
for ( CALayer *sub in layer.sublayers )
{
if ( YES == [sub.name isEqual:#"border-shape"])
{
CGFloat borderHalf = floor([(CAShapeLayer*)sub lineWidth] * .5);
sub.frame = layer.bounds;
[sub setBounds:CGRectInset(layer.bounds, borderHalf, borderHalf)];
[sub setPosition:CGPointMake(CGRectGetMidX(layer.bounds),
CGRectGetMidY(layer.bounds))];
}
}
}
- (void)setBorder:(CGFloat)borderWidth color:(UIColor*)color
{
assert(self.frame.size.width == self.frame.size.height);
for ( CALayer *sub in [NSArray arrayWithArray:self.layer.sublayers] )
{
if ( YES == [sub.name isEqual:#"border-shape"])
{
[sub removeFromSuperlayer];
break;
}
}
CGFloat borderHalf = floor(borderWidth * .5);
self.layer.cornerRadius = self.layer.bounds.size.width * .5;
CAShapeLayer *circleLayer = [CAShapeLayer layer];
self.layer.delegate = (id<CALayerDelegate>)self;
circleLayer.name = #"border-shape";
[circleLayer setBounds:CGRectInset(self.bounds, borderHalf, borderHalf)];
[circleLayer setPosition:CGPointMake(CGRectGetMidX(self.layer.bounds),
CGRectGetMidY(self.layer.bounds))];
[circleLayer setPath:[[UIBezierPath bezierPathWithOvalInRect:circleLayer.bounds] CGPath]];
[circleLayer setStrokeColor:color.CGColor];
[circleLayer setFillColor:[UIColor clearColor].CGColor];
[circleLayer setLineWidth:borderWidth];
{
circleLayer.shadowOffset = CGSizeZero;
circleLayer.shadowColor = [[UIColor whiteColor] CGColor];
circleLayer.shadowRadius = borderWidth;
circleLayer.shadowOpacity = .9f;
circleLayer.shadowOffset = CGSizeZero;
}
// Add the sublayer to the image view's layer tree
[self.layer addSublayer:circleLayer];
// old variant
//CALayer *layer = self.layer;
//layer.masksToBounds = YES;
//layer.cornerRadius = self.frame.size.width * 0.5;
//layer.borderWidth = borderWidth;
//layer.borderColor = color;
}
#end
Setting cornerRadius and clipsToBounds is the right way to do this. However if the view's size changes, the radius will not update. In order to get proper resizing and animation behavior, you need to create a UIImageView subclass.
class RoundImageView: UIImageView {
override var bounds: CGRect {
get {
return super.bounds
}
set {
super.bounds = newValue
setNeedsLayout()
}
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.width / 2.0
clipsToBounds = true
}
}
Try this to get rounded corners of the image View and also to colour the corners:
imageView.layer.cornerRadius = imageView.frame.size.height/2;
imageView.layer.masksToBounds = YES;
imageView.layer.borderColor = [UIColor colorWithRed:148/255. green:79/255. blue:216/255. alpha:1.0].CGColor;
imageView.layer.borderWidth=2;
Condition*: The height and the width of the imageView must be same to get rounded corners.
layer.cornerRadius = imageviewHeight/2
layer.masksToBounds = true
It is possible but I'll advice you to create transparent png image (mask) with round corners and place it over you image with UIImageView. It might be quicker solution (for example if you need animations or scrolling).
Here how i set my rounded avatar at the center of it contain view:
-(void)setRoundedAvatar:(UIImageView *)avatarView toDiameter:(float)newSize atView:(UIView *)containedView;
{
avatarView.layer.cornerRadius = newSize/2;
avatarView.clipsToBounds = YES;
avatarView.frame = CGRectMake(0, 0, newSize, newSize);
CGPoint centerValue = CGPointMake(containView.frame.size.width/2, containedView.frame.size.height/2);
avatarView.center = centerValue;
}
Circle with UIBeizerPath #Swift-3 && #imageExtension
class ViewController: UIViewController {
#IBOutlet weak var imageOutlet: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "IMG_0001.JPG")
if let image = image {
let renderimage = image.imageCroppingBezierPath(path: UIBezierPath(arcCenter: CGPoint(x:image.size.width/2,y:image.size.width/2 ) , radius: 200, startAngle: 0, endAngle: (2 * CGFloat(M_PI) ), clockwise: true) )
imageOutlet.image = renderimage
}
}
}
extension UIImage {
func imageCroppingBezierPath(path:UIBezierPath) ->UIImage {
let frame = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height)
//Defining a graphic context to paint on
UIGraphicsBeginImageContextWithOptions(self.size, false, 0.0)
//Get the current graphics context (if it exists)
let context = UIGraphicsGetCurrentContext()
//save the current graphic context
context?.saveGState()
// clipping area
path.addClip()
self.draw(in: frame)
//To extract an image from our canvas
let image = UIGraphicsGetImageFromCurrentImageContext()
//restore graphic context
context?.restoreGState()
//remove current context from stack
UIGraphicsEndImageContext()
return image!
}
}
# import QuartzCore framework
imageView.layer.cornerRadius=imgvwUser.frame.size.width/2;
imageView.layer.masksToBounds = YES;
The height and the width of the imageView must be same to get rounded corners.