iOS - Add Badge to UITableViewCell - ios

How do I add a badge to UITableViewCell, like this:
alt text http://img17.imageshack.us/img17/9974/img0001ac9.png
Should I simply add a subview with a text and label on it?

Here's a swift enhancement to #POF's answer. We don't need as many subviews and we can use math to support N digits, not just 1-3:
func setDiscountBadge(count: Int) {
let size: CGFloat = 26
let digits = CGFloat( count("\(number)") ) // digits in the label
let width = max(size, 0.7 * size * digits) // perfect circle is smallest allowed
let badge = UILabel(frame: CGRectMake(0, 0, width, size))
badge.text = "\(number)"
badge.layer.cornerRadius = size / 2
badge.layer.masksToBounds = true
badge.textAlignment = .Center
badge.textColor = UIColor.whiteColor()
badge.backgroundColor = cfg.UIColors.brand
YOURCELL.accessoryView = badge // !! change this line
}
And the result (I use a brand color, but yours can be any color):

TDBadgedCell is a pretty good choice. Highly customizable for your needs.

As for me the simplest way is to use cell.accessoryView. Please look into my code how I did it:
UIImageView * commentsViewBG = [[UIImageView alloc] initWithImage: [UIImage imageNamed: #"counter1.png"]];
commentsViewBG.frame = CGRectMake(
commentsViewBG.frame.origin.x,
commentsViewBG.frame.origin.y, 30, 20);
UILabel *commentsCount;
if (commentsArray.totalCount < 10)
commentsCount = [[UILabel alloc]initWithFrame:CGRectMake(10, -10, 40, 40)];
else if (commentsArray.totalCount < 100)
commentsCount = [[UILabel alloc]initWithFrame:CGRectMake(5, -10, 40, 40)];
else if (commentsArray.totalCount < 1000)
{
commentsViewBG.frame = CGRectMake(
commentsViewBG.frame.origin.x,
commentsViewBG.frame.origin.y, 40, 20);
commentsCount = [[UILabel alloc]initWithFrame:CGRectMake(5, -10, 40, 40)];
}
commentsCount.text = [NSString stringWithFormat:#"%ld",(long)commentsArray.totalCount];
commentsCount.textColor = [UIColor whiteColor];
commentsCount.backgroundColor = [UIColor clearColor];
[commentsViewBG addSubview:commentsCount];
cell.accessoryView = commentsViewBG;
And my result:
Hope it helps.

Yes, there is currently no supported way of adding a badge to a UITableView Cell. In this example, it is most likely a custom subview which contains an image and UILabel.

I'd like to add another alternative to create customized Badges. CustomBadge is a little bit more powerful. It's open and for free.

Related

How to draw a 1px line in storyBoard?

As we know, the table view separator is so thin and beautiful. Sometimes we have to build some separator line in storyboard or nib, the min number is 1, but actually the line appears much thicker than we expected.
My question is how to draw a 1px line in storyboard?
Xcode 9 Swift: You can add a thin seperator with 1px line in the Storyboard using UIView.
Under Size Inspector, Just set the height to 1, width example to 360.
Apple documentation on UIView.
I got your point too, finally I find way out.
As we know, if we draw a line and set the height by code, we can set the height equal to (1.0 / [UIScreen mainScreen].scale).
But here, you wanna to draw in storyboard.
My way is subclass UIView or UIImageView, based on your demand as OnePXLine. In OnePXLine class, override layoutSubviews like below:
- (void)layoutSubviews {
[super layoutSubviews];
CGRect rect = self.frame;
rect.size.height = (1 / [UIScreen mainScreen].scale);
self.frame = rect;
}
And you can draw 1 px line in storyboard by use this class.
Goodluck!
This would help you if you're coding in Swift:
func lineDraw(viewLi:UIView)
{
let border = CALayer()
let width = CGFloat(1.0)
border.borderColor = UIColor(red: 197/255, green: 197/255, blue: 197/255, alpha: 1.0).CGColor
border.frame = CGRect(x: 0, y: viewLi.frame.size.height - width, width: viewLi.frame.size.width, height: viewLi.frame.size.height)
border.borderWidth = width
viewLi.layer.addSublayer(border)
viewLi.layer.masksToBounds = true
}
You can do like in any UIControl/UIElement for this and change the height as 1
If you want to 1 Point use this - 1
If you want to 1pixel Use this - 1.0 / UIScreen.mainScreen().scale
Objective-C
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, 1)]; // customize the frame what u need
[lineView setBackgroundColor:[UIColor yellowColor]]; //customize the color
[self.view addSubview:lineView];
Swift
var lineView = UIView(frame: CGRect(x: 0, y: 50, width: self.view.frame.size.width, height: 1))
lineView.backgroundColor = UIColor.yellow
self.view.addSubview(lineView)
If you want a more information see this once
you can assign float value for view frame . so what you can do is take any view (lable,textview,view,textfield) and assign height as 0.4f or something programatically and width to match self width.
lable.frame = CGRectMake(0,0,width of self.view,0.4f);
Try it in cellForRowAtIndex
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 1)];
separatorLineView.backgroundColor = [UIColor colorWithRed:242/255.0f green:222/255.0f blue:52/255.0f alpha:1.0];
[cell.contentView addSubview:separatorLineView];
Swift 5 code base on what #childrenOurFuture answered:
class OnePXLine: UIView {
override func layoutSubviews() {
super.layoutSubviews()
var rect = self.frame;
rect.size.height = (1 / UIScreen.main.scale);
self.frame = rect;
}
}

Duplicated UITextView doesn't show all text from the original

I'm trying to make a duplicate UITextView based on another UITextView for sharing purposes. This text view is added as a subview to viewToShare. There is an issue however, the duplicated text view doesn't show all of the original text from the text view I'm copying from. I'm using attributed text as well on the original text view, so I'm not sure if this is the issue. Setting the background color to black on textViewCopy showed me that the frame size is correct. For some reason it seems like new line \n characters from the original text view are causing havoc and preventing the text to be fully shown in the textViewCopy. I wonder if it's related to this question: NSAttributedString '\n' ignored
Screenshots:
Code:
- (UIView *)shareView
{
CGSize size = self.containerView.bounds.size;
UIView *viewToShare = [[UIView alloc]init];
viewToShare.backgroundColor = self.containerView.backgroundColor;
viewToShare.layer.cornerRadius = 6.0;
viewToShare.layer.masksToBounds = YES;
UITextView *textViewCopy = [[UITextView alloc]init];
textViewCopy.backgroundColor = [UIColor clearColor];
textViewCopy.tag = 1;
UIEdgeInsets textContainerInsets = self.textView.textContainerInset;
viewToShare.frame = CGRectMake(0, 0, size.width, size.height);
textViewCopy.frame = CGRectMake(0, 0, size.width, size.height);
textViewCopy.textContainerInset = textContainerInsets;
NSAttributedString *attributedStringCopy = [[NSAttributedString alloc]
initWithAttributedString:self.textView.attributedText];
textViewCopy.attributedText = attributedStringCopy;
[viewToShare addSubview:textViewCopy];
return viewToShare;
}
I figured out how to solve the issue based on this SO: Large Text Being Cut Off in UITextView That is Inside UIScrollView
- (UIView *)shareView
{
CGSize size = self.containerView.bounds.size;
UIView *viewToShare = [[UIView alloc]init];
viewToShare.backgroundColor = self.containerView.backgroundColor;
viewToShare.layer.cornerRadius = 6.0;
viewToShare.layer.masksToBounds = YES;
UITextView *textViewCopy = [[UITextView alloc]init];
textViewCopy.backgroundColor = [UIColor clearColor];
textViewCopy.tag = 1;
UIEdgeInsets textContainerInsets = self.textView.textContainerInset;
viewToShare.frame = CGRectMake(0, 0, size.width, size.height);
textViewCopy.frame = CGRectMake(0, 0, size.width, size.height);
// These two lines are needed to fix bug!
textViewCopy.scrollEnabled = NO;
textViewCopy.scrollEnabled = YES;
textViewCopy.textContainerInset = textContainerInsets;
NSAttributedString *attributedStringCopy = [[NSAttributedString alloc]
initWithAttributedString:self.textView.attributedText];
textViewCopy.attributedText = attributedStringCopy;
[viewToShare addSubview:textViewCopy];
return viewToShare;
}

iOS: adding images to a UIButton, then putting button in a scrollview, but only seeing one image?

I'm working on an iPad app and part of the UI is a scrollview that has buttons for its contents. I'm working on adding images to these buttons, but when I do so, I only ever get the image in one spot, when I should be seeing it on all the buttons. This is what I'm doing:
float scrollCurrTop = 0;
CGRect currProcedureButtonFrame = CGRectMake(0,
scrollCurrTop,
self.fProceduresView.frame.size.width,
self.fLabelAndButtonHeight);
PatientIDButton* currProcedureButton = [PatientIDButton buttonWithType:UIButtonTypeCustom];
[currProcedureButton setFrame:currProcedureButtonFrame];
[currProcedureButton.layer setBorderColor: [self.fPanelViewBorderColor CGColor]];
[currProcedureButton.layer setBorderWidth: self.fBorderWidth];
currProcedureButton.titleLabel.font = self.fLabelFont;
NSString* displayName = [grabbing name];
if (displayName == nil)
{
displayName = currPlanName;
}
[currProcedureButton setTitle:displayName
forState:UIControlStateNormal];
[currProcedureButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
currProcedureButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
currProcedureButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
// is the plan approved?
if ([self isPlanApproved:currPlanName])
{
// add the checkmark to this plan button
CGRect currPlanButtonFrame = currProcedureButton.frame;
float originX = currPlanButtonFrame.size.width - (currPlanButtonFrame.size.width/3.0f);
float originY = currPlanButtonFrame.origin.y;
float width = currPlanButtonFrame.size.width - originX;
float height = currPlanButtonFrame.size.height;
CGRect currPlanApprovalImageFrame = CGRectMake(originX, originY, width, height);
UIImageView* currPlanApprovalImage = [[UIImageView alloc] initWithFrame:currPlanApprovalImageFrame];
[currPlanApprovalImage setBackgroundColor:[UIColor colorWithRed:(63.0f/255.0f)
green:(179.0f/255.0f)
blue:(79.0f/255.0f)
alpha:1.0f]];
[currPlanApprovalImage setImage:self.fCheckMarkIcon];
[currProcedureButton addSubview:currPlanApprovalImage];
}
[self.fProceduresView addSubview:currProcedureButton];
scrollCurrTop += self.fLabelAndButtonHeight;
Where 'fProceduresView' is the scrollview that houses the buttons. What am I doing wrong?
It seems that you're misunderstanding the logic behing setting the frame of the imageview's those you're trying to add
CGRect currPlanButtonFrame = currProcedureButton.frame;
float originX = currPlanButtonFrame.size.width - (currPlanButtonFrame.size.width/3.0f);
float originY = currPlanButtonFrame.origin.y;
float width = currPlanButtonFrame.size.width - originX;
float height = currPlanButtonFrame.size.height;
CGRect currPlanApprovalImageFrame = CGRectMake(originX, originY, width, height);
UIImageView* currPlanApprovalImage = [[UIImageView alloc] initWithFrame:currPlanApprovalImageFrame];
You don't need to set originY to currPlanButtonFrame.origin.y;
All subviews have relative coordinates to their's superviews.
So in your case originY should be 0
For example:
// Image is visible
Button frame [0, 0, 100, 100]
image in button [0, 0, 100, 100]
// Button is visible, but image is not because it will be clipped by bounds of the button.
Button frame [100, 100, 100, 100]
image in button [100, 100, 100, 100]
Also you will be able to "see" your images, if you set
currProcedureButton.clipsToBounds = NO

Add header to UIPickerView

I created the UIPickerView with 4 components.
Can I add the header title for each component in that UIPickerView?
Thanks for any advice
Swift version, based on #greentor's answer with some improvements:
var labelTexts = ["Months", "Weeks", "Days", "Hours", "Minutes"]
override func viewDidAppear(animated: Bool) {
let labelWidth = itemPicker.frame.width / CGFloat(itemPicker.numberOfComponents)
for index in 0..<labelTexts.count {
let label: UILabel = UILabel.init(frame: CGRectMake(itemPicker.frame.origin.x + labelWidth * CGFloat(index), 0, labelWidth, 20))
label.text = labelTexts[index]
label.textAlignment = .Center
itemPicker.addSubview(label)
}
Note that this might work incorrectly if called in ViewWillAppear or earlier because the UIPickerView won't know its frame dimensions at that point yet.
One other technique I use from time to time is the make the header the first row in each column:
You need to increment the number of rows of course..
I show 3 components and then use a UIView to show a title (UILabel) centred above each component (you can easily amend this for more or fewer components):
-(void)labelForDays
{
NSString *strDay = #"Days";
float lblWidth = self.pickerDayHourMin.frame.size.width / self.pickerDayHourMin.numberOfComponents;
float lblXposition = self.pickerDayHourMin.frame.origin.x;
float lblYposition = (self.pickerDayHourMin.frame.origin.y);
UILabel *lblDay = [[UILabel alloc] initWithFrame:CGRectMake(lblXposition,
lblYposition,
lblWidth,
20)];
[lblDay setText:strDay];
[lblDay setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:lblDay];
}
Then a label for 2nd component
-(void)labelForHours
{
NSString *strHours = #"Hours";
float lblWidth = self.pickerDayHourMin.frame.size.width / self.pickerDayHourMin.numberOfComponents;
float lblXposition = self.pickerDayHourMin.frame.origin.x;
float lblYposition = (self.pickerDayHourMin.frame.origin.y);
UILabel *lblHours;
if (self.pickerDayHourMin.numberOfComponents ==3)
{
lblHours = [[UILabel alloc] initWithFrame:CGRectMake((lblXposition + lblWidth),
lblYposition,
lblWidth,
20)];
}
[lblHours setText:strHours];
[lblHours setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:lblHours];
}
and finally a label centred above the 3rd component
-(void)labelForMinutes
{
NSString *strMinute = #"Minutes";
float lblWidth = self.pickerDayHourMin.frame.size.width / self.pickerDayHourMin.numberOfComponents;
float lblXposition = self.pickerDayHourMin.frame.origin.x;
float lblYposition = (self.pickerDayHourMin.frame.origin.y);
UILabel *lblMinute;
if (self.pickerDayHourMin.numberOfComponents ==3)
{
lblMinute = [[UILabel alloc] initWithFrame:CGRectMake((lblXposition + lblWidth + lblWidth),
lblYposition,
lblWidth,
20)];
}
[lblMinute setText:strMinute];
[lblMinute setTextAlignment:NSTextAlignmentCenter];
[self.view addSubview:lblMinute];
}
You can use UIlabel above the UIPicker view,that works well

iOS, how to draw the dynamic length of text?

The picture is: http://www.flickr.com/photos/71607441#N07/6641626163/
The background is a UIImageView, and the blue part I want to show as "title" of the image.
I used UILabel, but the length of the text is dynamic. It can be one line or two line, at most two line. If the text is longer than two lines, it will be truncated.
The blue part looks like "highlight in Microsoft Word", but it is not "highlight in iOS UILabel.text"
Is there anyone can help me?
Try this code :----
CGSize maximumSize = CGSizeMake(320, 30);
UILabel *newsLabel = [[UILabel alloc] init];
newsLabel.textColor = [UIColor whiteColor];
newsLabel.font = [UIFont boldSystemFontOfSize:11];
newsLabel.backgroundColor = [UIColor clearColor];
newsLabel.lineBreakMode = UILineBreakModeWordWrap;
newsLabel.numberOfLines = 0;
lineBreakMode:newsLabel.lineBreakMode];
CGSize dateStringSize = [#"Text Input" sizeWithFont:newsLabel.font
constrainedToSize:maximumSize
lineBreakMode:newsLabel.lineBreakMode];
CGRect dateFrame = CGRectMake(5, 5, 320, dateStringSize.height); //breath can be any desired float value
newsLabel.text = #"Text Input";
newsLabel.textAlignment = UITextAlignmentCenter;
newsLabel.frame = dateFrame;
You can find the size in pixels required for your title using:
CGSize size = [UILabel.text sizeWithFont:yourFont];
there's also:
CGSize size = [UILabel.text sizeWithFont:yourFont lineBreakMode: yourLineBreakMode];
You could then use these dimensions (size.width, size.height) to set the frame of your UILabel.
Hope this helps. :)

Resources