UIPickerView interactive area for tapping cut off in iOS 7 - iphone

When I make a long picker with multiple components, only the components near the center react to the tap-to-select feature.
For example, if you want to pick the very next row under a selected row, you should be able to just tap it to make it animate up into the selection area. This feature still exists with iOS 7, but the area with in the UIPicker that will actually accept the tap is a very small window, no larger than 200px.
Is there any way to expand this tap-able area to include the entire UIPickerView, so any time you tap a row it becomes the selection?
EDIT here is the code, it's pretty standard...
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
NSLog(#"picked %i %i" , component , row);
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 4;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return 15;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return #"";
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *pickersLabel;
pickersLabel =[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, view.frame.size.width , view.frame.size.height )];
pickersLabel.text = [NSString stringWithFormat:#"thing %i" , row ];
pickersLabel.backgroundColor = [UIColor clearColor];
pickersLabel.backgroundColor = [UIColor colorWithRed:1/255.0 green:1/255.0 blue:2/255.0 alpha:0.05];
pickersLabel.opaque = NO;
[view addSubview:pickersLabel];
return pickersLabel;
}

I've had massive problems with UIPickerViews that were in .xibs instead of Storyboards in iOS 7. I'm not sure if there's some optimization going on behind the scenes in the Storyboard or if this is a straight-up bug, but it's worth a shot - I'm using a picker view that's coming from a Storyboard right now and I am able to tap on non-selected rows and they scroll up and become selected.

Related

Custom iOS UIDatepicker using UIAppearance

UNIQLO's new alarm app has a custom UIDatePicker:
And I want to create my own custom UIDatePicker.
I tried to change the appearance of the DatePicker, but looking for UI_APPEARANCE_SELECTOR in the UIDatePicker returns nothing.
Meaning that its not possible to change any values, as per the docs:
To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR.
How can change my UIDatePicker's appearance?
The API does not provide a way to do this.
You can make a pretty convincing replica yourself using a UIPickerView rather than using UIDatePicker.
As the UIDatePicker or UIPickerView don't have the UI_APPEARANCE_SELECTOR and even you can't change UIDatePicker contents' appearance as its UIControl and not having any delegate so it has its native appearance whereas in case of UIPickerView you can change its contents' appearance similar as in UITableView.
#pragma mark -
#pragma mark UIPicker Delegate & DataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return 100;
}
//- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent: (NSInteger)component {
// return [NSString stringWithFormat:#"%d",row];
//}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UILabel *label= [[[UILabel alloc] initWithFrame:CGRectMake(30.0, 0.0, 50.0, 50.0)] autorelease];
[label setBackgroundColor:[UIColor clearColor]];
[label setTextColor:[UIColor blueColor]];
[label setFont:[UIFont boldSystemFontOfSize:40.0]];
[label setText:[NSString stringWithFormat:#"%d",row]];
return label;
}
Check this out.
add this method in your implementation file
-(UIView *)pickerViews{
return ([datePicker.subviews objectAtIndex:0]);
}
-(void)viewDidLoad{
[super viewDidLoad];
[[self pickerViews].subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"%# --- > %i",obj, idx);
}];
}
when you run your app it will display all the subviews of the datePicker on your console, just choose any index and modify them one by one
modify the viewDidLoad and insert this code
UIView *background = (UIView *)[[self pickerViews].subviews objectAtIndex:0];
background.backgroundColor = [UIColor clearColor];
UIView *wheel2 = (UIView *)[[self pickerViews].subviews objectAtIndex:4];
wheel2.backgroundColor = [UIColor redColor];
UIView *wheel3 = (UIView *)[[self pickerViews].subviews objectAtIndex:11];
wheel3.backgroundColor = [UIColor redColor];
In this case i change the background color of index "0", "4", "11"
With iOS 5 the UIAppearance protocol was introduced, which lets you customize several UI elements. UIDatePicker happens to conform this protocol, so that is probably the easiest way to do this. That is, if you're willing to support only iOS 5 users. Matthew's option would probably the next best thing, which should also work with older iOS versions.
It appears to be quite difficult to change the way a UIDatePicker appears.
The example you provided, in my opinion, is a sophisticated customization of a simple UIPickerView with two columns and probably a simulated infinite scroll (as Apple does in the date picker, and it's quite simple to realize).
You can change little of the UIDatePicker through the UIAppearance proxy, as seen in this example:
UIDatePicker *picker = [UIDatePicker appearance];
picker.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.3];
UIView *view;
view = [UIView appearanceWhenContainedIn:[UITableView class], [UIDatePicker class], nil];
view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
UILabel *label = [UILabel appearanceWhenContainedIn:[UITableView class], [UIDatePicker class], nil];
label.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
label.textColor = [UIColor blueColor];
Using this piece of code at the start of the application (just try it) you can change the aspect of only a couple of the main components of the date picker.
Labels are impossible to customize (and this test code proves it); apparently they are changed in aspect every time you rotate a column, since they are put inside a custom UITableView controller.
To fully change these appearances you should probably work with private APIs from Apple, that will eventually result in your app being rejected.
If you just need a custom hour-minute picker (as shown in your screenshot), the full customization of appearance is reachable only extending the UIPickerView class or assigning an appropriate delegate to a UIPickerView instance.
Through the
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
method on the delegate you can make the single element of the picker view appear the way you want. Then you will have to appropriately handle the data source to make the two components of the picker virtually infinite.
You can implement one yourself using two UIScrollViews, one for hours and one for minutes. You would just need to figure out the contentOffset of each scrollview when it has stopped moving, which off the top of my head would look like this:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
// get the offset here
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
// also get the offset here
}
Take the value of the content offset and translate it into the hour value and minute value, probably by dividing the y position of the content offset by the 24 or 60 respectively. You will need to make the custom artwork yourself.
To change date picker color:
[datePickerView setValue:self.pickerLabelColor forKey:#"textColor"];
And to change font the only way I know is:
Create category UIFont+System and place this code inside
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+ (UIFont *)systemFontOfSize:(CGFloat)fontSize
{
return [UIFont fontWithName:fontName size:fontSize];
}
#pragma clang diagnostic pop
This will set as well fonts in another places in your app (replacing system font by your font).
You should go through the UICatalog by Apple. It has all the methods in which a UIDatePicker can be used including the custom date picker method . Study this link developer.apple.com/library/ios/samplecode/UICatalog/ . Also they have implemented a standard switch and the navigation bar which is given in the latter.
A combination of 2 UITableViews is the way to go.
UITableView is a subview of UIScrollView, so it handles the following event
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
}
and on getting the position, just scroll the table to the center using the following method
[myTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
Hope this helps.

Custom Look & Feel of UIPickerView;

I want a UIPickerView in following design;
http://dl.dropbox.com/u/53051470/Screen%20shot%202012-04-18%20at%2012.02.36%20PM.png
(sorry as a new user, can't paste image here)
I read other questions on same topic too, and try to implement
pickerView:viewForRow:forComponent:reusingView:
method as well, but din't get the actual results;
Requirements are like selected value should display in green bar with checkmark image, and in white color; Moreover when user will start scrolling the picker, any value that enters inside green bar should turns into green color, and any value that leaves the green bar ares should turns into black;
Any suggestion?
Kind regards;
you should use the method
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
and decide which row is highlight
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
// i use a UILabel instead of your **custom UIView** , you may add a tick in you custom view
UILabel *testRow = view?(UILabel *)view:[[[UILabel alloc] initWithFrame:CGRectMake(0,0, 140, 40)] autorelease];
testRow.font = [UIFont fontWithName:[testArray objectAtIndex:row] size:16];
testRow.text = [fontsArray objectAtIndex:row];
testRow.backgroundColor = [UIColor clearColor];
if ( row == selectedRow )
{
testRow.backgroundColor = [UIColor greenColor];
}
return testRow;
}
don't forget set the showsSelectionIndicator to NO
pickView.showsSelectionIndicator = NO;
UIPickerView multiple-selection-behavior without adding other views in front of the pickerview,using: https://github.com/alexleutgoeb/ALPickerView
Improvements are highly appreciated!

How to change the font size in a UIPickerView? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
UIPickerView Font…
I'm really stuck on this one problem in my application. I searched everywhere to no avail. How can I change the font size in a UIPickerView?
Implement viewForRow:forComponent: method in picker's data delegate, create UILabel instance in it with the font (and all other properties) you need, e.g.:
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel* tView = (UILabel*)view;
if (!tView){
tView = [[UILabel alloc] init];
// Setup label properties - frame, font, colors etc
...
}
// Fill the label text here
...
return tView;
}
PickerView.transform = CGAffineTransformMakeScale(0.4, 0.4);

Bottom part of UISwitch is cut off on the device but displays normal on the Simulator

The UISwitch on my device: Switch Image with the bottom pixels cut off http://gorgando.com/uiswitch.jpg
The UISwitch on the simulator: Good UISwitch http://gorgando.com/uiswitch-good.png
As you can see, the bottom pixels are cut off on the device, but not on the simulator. I have tried just about everything I can think of, but nothing has fixed the problem.
Some of the things I've tried:
Changing the UISwitch's frame's height
Changing the UICell's height
Changing the UICell's contentView's height
Adding the UISwitch to the UICell rather than the UICell's contentView
Here is the relevant code:
This is in the viewDidLoad of the uiTableViewController:
UISwitch *sw = [[UISwitch alloc] init];
self.contactedSwitch = sw;
[sw release];
self.contactedSwitch = [UISwitch switchWithLeftText:#"YES" andRight:#"NO"];
self.contactedSwitch.center = CGPointMake(230, 22);
self.contactedSwitch.on = [self.contact.contacted boolValue];
This is where the switchWithLeftText:andRight method comes from:
#import "UISwitch-Extended.h"
#define TAG_OFFSET 900
#implementation UISwitch (tagged)
- (void) spelunkAndTag: (UIView *) aView withCount:(int *) count
{
for (UIView *subview in [aView subviews])
{
if ([subview isKindOfClass:[UILabel class]])
{
*count += 1;
[subview setTag:(TAG_OFFSET + *count)];
}
else
[self spelunkAndTag:subview withCount:count];
}
}
- (UILabel *) label1
{
return (UILabel *) [self viewWithTag:TAG_OFFSET + 1];
}
- (UILabel *) label2
{
return (UILabel *) [self viewWithTag:TAG_OFFSET + 2];
}
+ (UISwitch *) switchWithLeftText: (NSString *) tag1 andRight: (NSString *) tag2
{
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 94, 27)];
int labelCount = 0;
[switchView spelunkAndTag:switchView withCount:&labelCount];
if (labelCount == 2)
{
[switchView.label1 setText:tag1];
[switchView.label2 setText:tag2];
}
return [switchView autorelease];
}
#end
This is where I add the UISwitch to my tableviewcell:
[[contactedCell contentView] addSubview:self.contactedSwitch];
Thanks so much!
[Update] I thought the tableviewcell's might be the problem, so I added these UISwitches to a regular UIView to see how they looked. I have the exact same problem where they look alright in the simulator and the bottom is chopped in the device. So bizarre!
I had the same problem when programatically creating a UISwitch and changing its frame's origin- it turned out to be a half-pixel issue.
A key to noticing half-pixel bugs is: do the unwanted artifacts appear differently on the simulator vs device?
Your solution of placing the UISwitch with Interface Builder fixes this- you can also make sure to floor() your new coordinates if you are setting the UISwitch's frame's origin x/y.
UISwitch *mySwitch = [[UISwitch alloc] initWithFrame(CGRectZero)];
CGRect switchFrame = mySwitch.frame;
// move frame up without pixel fractions
switchFrame.origin.y = floor((cell.contentView.frame.size.height - switchFrame.size.height) / 2);
mySwitch.frame = switchFrame;
[cell.contentView addSubview:mySwitch];
In the original poster's case, the height of a uiswitch is an odd number (27 pixels), so setting the center to 22 splits the height into 13.5. The UISwitch's origin's y coordinate becomes 22-13.5 = 8.5 pixels. Either don't move a UISwitch by setting its center, or floor the coordinate, or use a fraction in the call to CGPointMake(230,22.5).
Another way to track this type of bug is to grep through Interface Builder looking for ".5" coordinates. I have found that sometimes over-tweaking the placement of UI elements in Interface Builder introduces this bug.
This is caused of the UISwich's top.
You can use UISwich.origin.y = ceil((height - UISwich.size.height)/2)
to fix it.
Never figured out exactly what was wrong, but I ended up creating the UISwitches in IB and got it to work beautifully that way. Very weird that it works in IB and not programmatically when I am basically doing the exact same thing.

Changing style of UIPickerView

How can I change the style of a UIPickerview. I want to change its white background to green color and its black frame to red color.
Anyone please help. I am a beginner.
As far as I know you can't actually change the frame's color, but you can create an image with a transparent area in the middle and add that on top of the frame like so:
[picker addSubview:image];
As for the background color, you can create your own custom views for each row by implementing the UIPickerViewDelegate method:
- (UIView *)pickerView:(UIPickerView *)pickerView
viewForRow:(NSInteger)row
forComponent:(NSInteger)component
reusingView:(UIView *)aView;
You could then set the background color of the view you return via
[myView setBackgroundColor:[UIColor yellowColor]];
However this only affects the rows with data. I don't think you can currently set the background color of the component itself which is a shame.
I personally prefer this:
[self.picker setBackgroundColor:[UIColor greenColor]];
self.picker.layer.borderColor = [UIColor whiteColor].CGColor;
self.picker.layer.borderWidth = 4;