UIPicker single component to display multiple arrays - ios

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.

Related

changing font by scrolling UIPickerView

Is it possible to change the font of a text while scrolling down/up a UIPickerView which has all the correct names of the system fonts? So that the text changes its font to the one that is currently selected in the pickerView.
You can set a method, for UIPickerView changes the selection while scrolling up/down, in viewdidload, or method where UIPickerview get present, like
[uorPickerView addTarget:self action:#selector(ValueChanged:) forControlEvents: UIControlEventValueChanged];
You can set the font which has been selected from UIPickerview in ValueChanged Method like
-(void)ValueChanged :(UIPickerView *) sender {
//Lets say you have UILable or UITextfield or UITextview as textView, so u can set your text like,
// fontArray = Array you have provided for UIPickerView datasource
[textView setFont:[UIFont fontWithName:[fontArray objectAtIndex:[sender selectedRowInComponent:0]] size:16]]
// make sure that fontArray has proper value of font family.
}
Hope this help you,
HTH, Enjoy Coding !!
You can get all system fonts and use it as your datasource
for(NSString *familyName in [UIFont familyNames]) {
for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
NSLog(#"%#", fontName);
}
}
Implementing your delegate, you can create custom views for every row
- (UIView *)pickerView:(UIPickerView *)pickerView
viewForRow:(NSInteger)row
forComponent:(NSInteger)component
reusingView:(UIView *)view {
UILabel *pickerLabel = (UILabel *)view;
if (pickerLabel == nil) {
CGRect frame = CGRectMake(0.0, 0.0, 80, 32);
pickerLabel = [[[UILabel alloc] initWithFrame:frame] autorelease];
[pickerLabel setTextAlignment:UITextAlignmentLeft];
[pickerLabel setBackgroundColor:[UIColor clearColor]];
[pickerLabel setFont:/*font from datasource*/];
}
[pickerLabel setText:[pickerDataArray objectAtIndex:row]];
return pickerLabel;
}

Change Color of single, selected Row in UIPickerView [duplicate]

Ok, maybe I'm missing something really simple and I apologize if that's the case, however, I've googled every permutation of the title and have not found! So this is simply what I want to do: change the background color of the label I'm using as the row view in a 2 component pickerview when that row has been selected. So I thought this would work:
if (row == [pickerview selectedRowForComponent])
viewlabel.backgroundColor = redcolor;
but this doesn't work. It seems to arbitrarily choose which row to color and sometimes even give a bad access error. I've tried all different clauses to no effect! ANy suggestions would be greatly appreciated!!
Here's the full method:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
if (component == kNumberComponent) {
#define PICKER_LABEL_FONT_SIZE 24
#define PICKER_LABEL_ALPHA 1.0
// UIFont *font = [UIFont boldSystemFontOfSize:PICKER_LABEL_FONT_SIZE];
UIFont *font = [ UIFont fontWithName:#"AppleGothic" size:24];
UILabel *carsLabel =[ [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 75, 50) ]autorelease];
//[picker selectRow:row inComponent:component animated:YES];
NSString *pickerText = [self.numbers objectAtIndex:(int)row];
carsLabel.text = pickerText;
carsLabel.textAlignment = UITextAlignmentCenter;
NSLog(#"carsLabel = %#",carsLabel.text);
//carsLabel.text = #"maybe because the string isn't long enough";
carsLabel.textColor = [UIColor blackColor];
carsLabel.font = font;
carsLabel.opaque = YES;
[view addSubview:carsLabel];
return carsLabel;
} else {
UIFont *font = [ UIFont fontWithName:#"AppleGothic" size:18];
UILabel *carsLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 225, 50)] autorelease];
id fact = [self.facts objectAtIndex:(int)row];
NSString *pickerText = #"Dictionary Entry";
if ( [fact isKindOfClass:[NSString class]]) {
pickerText = [self.facts objectAtIndex:(int)row];
}
carsLabel.text = pickerText;
carsLabel.textAlignment = UITextAlignmentCenter;
NSLog(#"carsLabel = %#",carsLabel.text);
//carsLabel.text = #"maybe because the string isn't long enough";
carsLabel.textColor = [UIColor blackColor];
carsLabel.font = font;
if ( row == 0) {
carsLabel.backgroundColor = [UIColor redColor];
}
//carsLabel.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"blackboard.png"]];;
carsLabel.opaque = YES;
[view addSubview:carsLabel];
return carsLabel;
}
return nil;
}
Normally, I use this method:
I use the custom view for show the row item
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = (id)view;
if (!label)
{
label= [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, [pickerView rowSizeForComponent:component].width, [pickerView rowSizeForComponent:component].height)];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.text = _arrayStringPicker[row];
}
return label;
I change color of row selected with:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
UILabel *labelSelected = (UILabel*)[pickerView viewForRow:row forComponent:component];
[labelSelected setTextColor:[UIColor redColor]];
}
Swift implementation
extension PickerViewController: UIPickerViewDelegate {
func pickerView(pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
var color: UIColor!
if pickerView.selectedRowInComponent(component) == row {
color = UIColor.redColor()
} else {
color = UIColor.blackColor()
}
let attributes: [String: AnyObject] = [
NSForegroundColorAttributeName: color,
NSFontAttributeName: UIFont.systemFontOfSize(15)
]
return NSAttributedString(string: rows[row], attributes: attributes)
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
//this will trigger attributedTitleForRow-method to be called
pickerView.reloadAllComponents()
}
}
The correct format for viewForPicker is:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *label = (UILabel*) view;
if (label == nil)
{
label = [[UILabel alloc] init];
}
[label setText:#"Whatever"];
// This part just colorizes everything, since you asked about that.
[label setTextColor:[UIColor whiteColor]];
[label setBackgroundColor:[UIColor blackColor]];
CGSize rowSize = [pickerView rowSizeForComponent:component];
CGRect labelRect = CGRectMake (0, 0, rowSize.width, rowSize.height);
[label setFrame:labelRect];
return label;
}
The problem with the code above is: it colorizes the labels, but not the picker, itself. So, when you roll to one end or the other, there's a blank spot where you can see the white background. Setting [myPicker setBackgroundColor...] doesn't do what one might hope.
// CGRectMake values for the frame we’d like
UIPickerView *myPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height)];
// add the UIPickerView to your viewcontroller [mainView addSubview:myPickerView];
// set the selectionindicator to none myPickerView.showsSelectionIndicator = NO;
// define the image that we would like to use
UIImage *selectorImage = [UIImage imageNamed:#"selectionIndicator.png"];
UIView *customSelector = [[UIImageView alloc] initWithImage:selectorImage];
// set the x and y values to the point on the UIPickerView where you want to place the image
// set the width and height values to the width and height of your image
customSelector.frame = CGRectMake(10,(myPickerView.bounds.size.height / 2) + 16, self.view.bounds.size.width – 10, 47);
// add the custom selectionIndicator also to the same viewcontroller
[mainView addSubview:customSelector];
Solved! Declare 2 instance variables: selectedView, and oldView. Then the following code does the trick:
if (self.oldView != nil)
self.oldView.backgroundColor = [UIColor clearColor];
self.selectedView = [picker viewForRow:row forComponent:kNumberComponent];
self.selectedView.backgroundColor = [UIColor redColor];
[self.selectedView setNeedsDisplay];
self.oldView = self.selectedView;
Call the UIPickerView instance's -viewForRow:forComponent: method to get the UIView * object. Then set that view's background UIColor.
Swift version of #alessandro-pirovano answer
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let rowSize = pickerView.rowSize(forComponent: component)
let width = rowSize.width
let height = rowSize.height
let frame = CGRect(x: 0, y: 0, width: width, height: height)
let label = UILabel(frame: frame)
label.textAlignment = .center
label.text = rows[row]
return label
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
guard let label = pickerView.view(forRow: row, forComponent: component) as? UILabel else {
return
}
label.backgroundColor = .orange
}
It's unclear where you are putting the above code. Is it in -pickerView:viewForRow:forComponent:reusingView:? This is where it should be. Are you sure that you are maintaining a pointer to the label for that particular view? The fact that you are crashing suggests you probably are not. A larger block of code, including where you have put it, would be helpful.
Here's what worked for me:
Add a UIView as a subview to your UIPickerView
Constrain it to be Y entered with your UIPickerView and the has the same width
Give it height equal to the height of what returned in pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
Make it semi transparent and color it the way you want
*the rest of the solutions (with custom views for row or attributed stringsfor row) were buggy when scrolling fast.
UIPickerView has delegate to set NSAttributeString for title at row and component we can set attribute color like below:
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSDictionary *attrs = #{NSForegroundColorAttributeName : [UIColor redColor]};
NSString *title = #"title"
return [[NSAttributedString alloc] initWithString:title attributes:attrs];
}
Expanding on Alessandro Pirovano's answer;
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
UILabel *labelSelected = (UILabel*)[pickerView viewForRow:row forComponent:component];
[labelSelected setTextColor:[UIColor redColor]];
labelSelected.superview.backgroundColor = [UIColor yellowColor];
}

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 :

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;

UIPickerView - multi-line rows - need layout advice

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;
}

Resources