UIPickerView - multi-line rows - need layout advice - ios

I want to make picker with 2 lines, I tried it like a link , but I can not understand what I need to do: create a view and 2 label on it, when I add labels coordinates to code, but selection field still like it as default. How can I change selection field size? And text in selection field have bigger size when other lines. Sorry for my english.
- (UIView*)pickerView:(UIPickerView *)thePickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UIView* v;
if (view)
v = view;
else
{
v = [[UIView alloc] init] ;
UILabel* l1 = [[UILabel alloc] init];
l1.tag = 11;
[v addSubview: l1];
UILabel* l2 = [[UILabel alloc] init];
l2.tag = 12;
l2.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
[v addSubview: l2];
}
UILabel* l1 = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 110, 35)];
l1.font = [UIFont systemFontOfSize:22]; // choose desired size
l1.text = [NSString stringWithFormat: #"row %d line 1", row];
l1.tag = 11;
[v addSubview: l1];
UILabel* l2 = [[UILabel alloc] initWithFrame:CGRectMake(10, 34 , 110, 35)];
l2.font = [UIFont systemFontOfSize:14]; // choose desired size
l2.text = [NSString stringWithFormat: #"row %d line 2", row];
l2.tag = 12;
[v addSubview: l2];
return v;
}
UPDATE
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
return yourViewHeight;
}
- (UIView*)pickerView:(UIPickerView *)thePickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UIView* v;
if (view)
v = view;
else
{
v = [[UIView alloc] initWithFrame:CGRectMake(0, 34, 110, 35)] ;
UILabel* l1 = [[UILabel alloc] init];
l1.tag = 11;
[v addSubview: l1];
UILabel* l2 = [[UILabel alloc] init];
l2.tag = 12;
l2.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
[v addSubview: l2];
}
UILabel* l1 = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 110, 35)];
l1.font = [UIFont systemFontOfSize:22]; // choose desired size
l1.text = [NSString stringWithFormat: #"row %d line 1", row];
l1.tag = 11;
[v addSubview: l1];
UILabel* l2 = [[UILabel alloc] initWithFrame:CGRectMake(0, 34 , 110, 35)];
l2.font = [UIFont systemFontOfSize:14]; // choose desired size
l2.text = [NSString stringWithFormat: #"row %d line 2", row];
l2.tag = 12;
[v addSubview: l2];
return v;
}
http://i.picresize.com/images/2013/12/11/IiYqd.png

Hope It would work...
Implement this delegate method and return your view's height
(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
return yourViewHeight;
}
Set frame for your label and your view..Frame of your label does not exceed the view's frame
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
//1. Create your view and set frame for the view
//2. Create your label 1 and label 2 set the frame for your labels
//3. Add and return your view
}

You should implement the pickerView:rowHeightForComponent: picker view delegate method and return a height tall enough for your custom view.
You should also set the height of v in your pickerView:viewForRow:forComponent:reusingView: method.
And lastly, if you are reusing a view, don't keep adding more labels. They will already be there from the reused view.

Try this code
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 50;
}
than after
- (UIView *)pickerView:(UIPickerView *)thePickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 310, 50)];
lblTitle.numberOfLines=2;
lblTitle.textColor=[UIColor blackColor];
lblTitle.font=[UIFont systemFontOfSize:14];
lblTitle.text=[selectionList objectAtIndex:row];
}
return lblTitle;
}

Related

Unable to create section border in tableview and i want to represent the ui as per the attached image?

how to create section border in tableview and i want to represent the ui as per the attached image ? i displayed spaces between sections but cannot set the border line for section.
For this you need to add and import
#import <QuartzCore/QuartzCore.h>
After that follow below steps
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *section = [[UIView alloc]init];
section.frame = CGRectMake(0, 0, tableview.frame.size.width, height);
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithName:#"imageName"]];
imageView.frame = CGRectMake(0, 0, YOUR_WIDTH, YOUR_HEIGHT); //set your frame
[section addSubview:imageView];
labelSection = [[UILabel alloc]init];
labelSection.textAlignment = NSTextAlignmentLeft;
labelSection.frame = CGRectMake(10, 5, tableview.frame.size.width, 20);
[labelSection setBackgroundColor:[UIColor clearColor]];
[labelSection setFont:[UIFont boldSystemFontOfSize:15]];
NSString *name = #"section title";
labelSection.text = name;
[labelSection setTextColor:[UIColor blackColor]];
[section addSubview:labelSection];
section.layer.borderWidth = 2.0f;
section.layer.cornerRadius = 1.0f;
section.layer.masksToBounds = YES;
section.layer.borderColor=[UIColor lightGrayColor].CGColor;
return section;
}
If you want to set row height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44; //It default size.If you want to change to other size you can change.
//OR
// return 90; //Set to your needed size
}

How to get Custom UIPickerView?

I want to achieve the following functionality in Custom UIPiker as shown in below picture.
I want to change the text colour of selected area only like above.
Add lable in your pickerview in your viewDidLoad method as below.
Define label and myPickerView both in ViewController.h file
- (void)viewDidLoad
{
myPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 200, 320, 200)];
myPickerView.delegate = self;
myPickerView.showsSelectionIndicator = YES;
[self.view addSubview:myPickerView];
label = [[UILabel alloc] initWithFrame:CGRectMake(145, 76, 36, 36)];
//label.text = #"Label";
label.font = [UIFont boldSystemFontOfSize:20];
label.layer.cornerRadius = 18;
[label setTextColor:[UIColor whiteColor]];
label.backgroundColor = [UIColor blueColor];
label.textAlignment = NSTextAlignmentCenter;
label.shadowColor = [UIColor whiteColor];
label.shadowOffset = CGSizeMake (0,1);
[myPickerView addSubview:label];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
in pickerview delegate set label title.
#pragma mark - PickerView delegate
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component {
// Handle the selection
[label setText:[NSString stringWithFormat:#"%d",row]];
NSLog(#"%#",[NSString stringWithFormat:#"%d",row]);
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSLog(#"%#",[NSString stringWithFormat:#"%d",row]);
[label setText:[NSString stringWithFormat:#"%d",row]];
return [NSString stringWithFormat:#"%d",row];
}
Your OuytPut is :

UIPicker single component to display multiple arrays

first comment so I hope Im doing this right.
I'm having a fight with a UIPicker. I am trying to display 2 columns of data in a single picker component. The reason I have chosen to do this within 1 component is that I want the arrays to scroll together, which I can't get multiple components to do.
The trouble is, I can't get this way to work either, as titleForRow and viewForRow will only return one value (as per the rules of C). I tried making them output arrays and dicts but that caused data type errors.
I can get it to work just fine using 1 component, 1 array with viewForRow but that only allows justification the whole field, not parts of the string.
The below code works great and gives a correct answer with return label2; and if changed to return label1 is correct also , How do I get both to display?
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label1;
{
label1 = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 150.0f, 130.0f, 60.0f)];
label1.textAlignment = NSTextAlignmentLeft;
label1.text = [_firstList objectAtIndex:row];
}
UILabel *label2;
{
label2 = [[UILabel alloc] initWithFrame:CGRectMake(100.0f, 10.0f, 175.0f, 100.0f)];
label2.textAlignment = NSTextAlignmentCenter;
label2.text = [_secondList objectAtIndex:row];
}
return label2;
}
Setup your UIPickerView to have one component.
Now assuming that your two array _firstList and _secondList have the same number of objects in them, you have two options:
Use the simple pickerView:titleForRow:forComponent: method to return a single string build from the two values:
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [NSString stringWithFormat:#"%# - %#", _firstList[row], _secondList[row]];
}
Of course you can format the two strings as needed. This is one example.
Use pickerView:viewForRow:forComponent:reusingView: like you tried but return a single view that has two labels added to it.
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *label1;
UILabel *label2;
if (view) {
label1 = (UILabel *)[view viewWithTag:1];
label1 = (UILabel *)[view viewWithTag:2];
} else {
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 0.0f, 130.0f, 40.0f)];
label1.tag = 1;
label1.textAlignment = NSTextAlignmentLeft;
UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(100.0f, 0.0f, 175.0f, 40.0f)];
label2.tag = 2;
label2.textAlignment = NSTextAlignmentCenter;
[view addSubview:label1];
[view addSubview:label2];
}
label1.text = _firstList[row];
label2.text = _secondList[row];
return view;
}
Note how this properly makes use of the reused view.

2 lines (multiline) picker for long text

why can i set the Row hight or multi lines for a picker,
the problem i have long texts for my picker, or gives an line break in picker... xcode 5 ...
i get the values for the picker from an array.
my code for my custom Picker is:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel *label = [[UILabel alloc] init];
CGRect frame = CGRectMake(0,0,265,40);
label.backgroundColor = PickColor;
label.textColor = [UIColor whiteColor];
label.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:18 ];
label.textAlignment = NSTextAlignmentCenter;
if(component == 0)
{
label.text = [_vergehen objectAtIndex:row];
}
return label;
}
thanks for help
Try this code
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
return 50;
}
then
- (UIView *)pickerView:(UIPickerView *)thePickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *lblTitle = [[UILabel alloc] initWithFrame:CGRectMake(5, 0, 310, 50)];
lblTitle.numberOfLines=2;
lblTitle.textColor=[UIColor blackColor];
lblTitle.font=[UIFont systemFontOfSize:14];
lblTitle.text=[selectionList objectAtIndex:row];
return lblTitle;
}
Because you're creating a label, you might try this property of UILabel:
// UILabel wraps text across multiple lines
label.lineBreakMode = UILineBreakModeWordWrap;
If you set label.numberOfLines = 0, you should be able to get any number of lines placed within the label.
UILineBreakModeWordWrap is deprecated deprecated in iOS 6.0
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;

UITableViewCell with subviews is not working properly

I have UITableView in my iOS app and I want to add some subviews to cell. I do it by using
[cell.contentView addSubview:someView];
and it works well, but... When I scroll down, subviews are starting to hide from cells that are on top and when I scroll back to top, they wont appear again... What I'm doing wrong? Is there some solution please?
EDIT
Mainly, I'm talking about "detailtext" label, but I have those problems in more cases...
Here is whole code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
switch (indexPath.row) {
case 0:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
break;
default:
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
break;
}
UIView *separatorLine = [[UIView alloc] init];
separatorLine.frame = CGRectMake(15.0f, 60 - 0.5f, cell.frame.size.width-15.0f, 0.5f);
separatorLine.tag = 4;
separatorLine.backgroundColor = [UIColor lightGrayColor];
cell.layer.masksToBounds = NO;
tableView.backgroundColor = [UIColor colorWithRed:33.0 / 255.0 green:157.0 / 255.0 blue:147.0 / 255.0 alpha:1.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIView *row2 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];
UIView *profileBorder = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2-50, 50, 102, 102)];
profileBorder.layer.borderColor = [UIColor whiteColor].CGColor;
profileBorder.layer.borderWidth = 5; //2
profileBorder.layer.cornerRadius = 50;
NZCircularImageView *profileImage = [[NZCircularImageView alloc] initWithFrame:CGRectMake(1,1, 100, 100)];
profileImage.image = profilePhoto;
profileImage.contentMode = UIViewContentModeScaleAspectFill;
UITapGestureRecognizer *showBigProfilePhoto = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showImage:)];
profileImage.userInteractionEnabled = YES;
[profileImage addGestureRecognizer:showBigProfilePhoto];
[profileBorder addSubview:profileImage];
UILabel *numberFeelings = [[UILabel alloc] initWithFrame:CGRectMake(10, 100-25, 100, 50)];
numberFeelings.text = [NSString stringWithFormat:#"%#\nFeelings", feelings];
numberFeelings.font = [UIFont boldSystemFontOfSize:16];
numberFeelings.textAlignment = NSTextAlignmentCenter;
numberFeelings.textColor = [UIColor whiteColor];
numberFeelings.numberOfLines = 0;
UILabel *numberFriends = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2+60, 100-25, 100, 50)];
numberFriends.text = [NSString stringWithFormat:#"%#\nFollowers", friends];
numberFriends.font = [UIFont boldSystemFontOfSize:16];
numberFriends.textColor = [UIColor whiteColor];
numberFriends.numberOfLines = 0;
numberFriends.textAlignment = NSTextAlignmentCenter;
[row2 addSubview:profileBorder];
[row2 addSubview:numberFriends];
[row2 addSubview:numberFeelings];
int rectButtons = cell.frame.size.width-246;
UIImageView *graph = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2, -20, 82, 82)];
UIImageView *badgets = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+82, -20, 82, 82)];
UIImageView *photos = [[UIImageView alloc] initWithFrame:CGRectMake(rectButtons/2+164, -20, 82, 82)];
graph.image = [UIImage imageNamed:#"graph.jpg"];
badgets.image = [UIImage imageNamed:#"badgets.jpg"];
photos.image = [UIImage imageNamed:#"photos.jpg"];
graph.userInteractionEnabled = YES;
badgets.userInteractionEnabled = YES;
photos.userInteractionEnabled = YES;
UITapGestureRecognizer *graphTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showGraph:)];
[graph addGestureRecognizer:graphTap];
NSArray *jmenoCasti = [name componentsSeparatedByString:#" "];
krestni = [jmenoCasti objectAtIndex:0];
int indexOfPost = indexPath.row-3;
NSMutableAttributedString *str;
int countFeeling;
int countString;
int countBeforeFeeling;
if (indexPath.row >=3) {
str = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:#"%# was %#", krestni, [naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:#"_feel"] integerValue]]]];
countFeeling = [[naladyHim objectAtIndex:[[[posts objectAtIndex:indexOfPost] objectForKey:#"_feel"] integerValue]] length];
countString = krestni.length+5+countFeeling;
countBeforeFeeling = countString-countFeeling+1;
int rangeStart = countBeforeFeeling-1;
int rangeStop = str.length-rangeStart;
NSLog(#"%i ... %i", countBeforeFeeling-1, countString-1);
[str addAttribute:NSFontAttributeName value: [UIFont fontWithName:#"Helvetica-Bold" size:16.0f] range:NSMakeRange(rangeStart, rangeStop)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:32.0 / 255.0 green:147.0 / 255.0 blue:138.0 / 255.0 alpha:1.0] range:NSMakeRange(rangeStart, rangeStop)];
}
UILabel *mainText = [[UILabel alloc] initWithFrame:CGRectMake(15, 70, cell.frame.size.width-10, 20)];
mainText.attributedText = str;
UILabel *detailText;
if (!detailText) {
detailText = [[UILabel alloc] initWithFrame:CGRectMake(15, 90, cell.frame.size.width-10, 30)];
}
detailText.textColor = [UIColor grayColor];
detailText.font = [UIFont systemFontOfSize:13];
switch (indexPath.row) {
case 0:
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.textLabel.text = name;
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont systemFontOfSize:20];
cell.backgroundColor = [UIColor clearColor];
break;
case 1:
[cell.contentView addSubview:row2];
cell.backgroundColor = [UIColor clearColor];
break;
case 2:
cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
[cell.contentView addSubview:graph];
[cell.contentView addSubview:badgets];
[cell.contentView addSubview:photos];
break;
default:
detailText.text = [[posts objectAtIndex:indexPath.row-3] objectForKey:#"_text"];
[cell.contentView addSubview:detailText];
cell.textLabel.attributedText = str;
cell.backgroundColor = [UIColor colorWithRed:236.0 / 255.0 green:235.0 / 255.0 blue:210.0 / 255.0 alpha:1.0];
break;
}
return cell; }
This is an easy way thats works for me:
for(UIView *subview in cell.contentView.subviews)
{
if([subview isKindOfClass: [UIView class]])
{
[subview removeFromSuperview];
}
}
You can use it at the begin of
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
In your tableView:cellForRowAtIndexPath:, you hide the info when you don't want it to be shown, but you don't explicitly unhide it for cells where it should be shown.
Look at the first two lines in that method: What you are - correctly - doing is reusing your cells, so when cells are scrolled out of view, they are removed from the UITableView and put into the reuse queue. Then, when cells should become visible, the TableView gets cells from that queue - or creates new ones if none are available.
This all goes very well, but after a while, cells with hidden info buttons are put on the queue. And then, some time later, those cells are reused - and sometimes for rows in which there should be info visible.
There are two solutions to this: You could either explicitly unhide the information for those rows where you want it to be shown, or you could use two different kinds of cell, one with hidden info, and one with visible info. You then give each of those cells a different identifier, and based on what row the cells are in, set the identifier before dequeuing/creating cells.
You should create a subclass of UITableViewCell for each different cell and add all your view related code that doesn't change depending on the data into an initialization method. Then create a method in each cell called something like configureWithData and pass in the data relevant to the cell. The creation of your attributed string and modification of label frames can occur in this configuration method.
It will dramatically reduce the clutter in your UITableViewController and is much better design wise. There is no real need for your view controller to know what your table cells look like.
Here is an example of what I am talking about:
-(void)awakeFromNib
{
if( self.accessoryType == UITableViewCellAccessoryDisclosureIndicator )
{
DTCustomColoredAccessory *accessory = [DTCustomColoredAccessory accessoryWithColor:[UIColor whiteColor]];
accessory.highlightedColor = [UIColor blackColor];
self.accessoryView = accessory;
}
}
-(void)configureCellWithObject:(id)inObject
{
TableDataModel *dataObject = (TableDataModel *)inObject;
self.titleLabel.text = dataObject.titleString;
self.subtitleLabel.text = dataObject.subtitleString;
self.accessibilityIdentifier = dataObject.accessIdString;
if( dataObject.imageUrlString != nil )
{
UIImage *iconImage = [UIImage imageNamed:dataObject.imageUrlString];
if( iconImage != nil )
{
NSInteger yOffset = [StaticTools centerYOffset:self.frame.size objectFrameSize:iconImage.size];
self.iconImageView.image = iconImage;
CGRect frame = self.iconImageView.frame;
frame.origin.y = yOffset;
frame.size = iconImage.size;
[self.iconImageView setFrame:frame];
}
else
{
[self.iconImageView loadImageFromUrl:dataObject.imageUrlString];
}
}
}

Resources