Add REPickerItem, reference #78

This commit is contained in:
Roman Efimov
2013-10-02 12:15:27 -05:00
parent 82523522c5
commit 6a2441fbb8
10 changed files with 336 additions and 0 deletions

View File

@@ -147,6 +147,7 @@
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[self setSelected:NO animated:NO];
[self.item deselectRowAnimated:NO];
self.item.value = self.datePicker.date;
self.dateLabel.text = [self.dateFormatter stringFromDate:self.item.value];

View File

@@ -0,0 +1,37 @@
//
// RETableViewPickerCell.h
// RETableViewManager
//
// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "RETableViewCell.h"
#import "REPickerItem.h"
@interface RETableViewPickerCell : RETableViewCell <UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate>
@property (strong, readonly, nonatomic) UITextField *textField;
@property (strong, readonly, nonatomic) UILabel *valueLabel;
@property (strong, readonly, nonatomic) UILabel *placeholderLabel;
@property (strong, readonly, nonatomic) UIPickerView *pickerView;
@property (strong, readwrite, nonatomic) REPickerItem *item;
@end

View File

@@ -0,0 +1,191 @@
//
// RETableViewPickerCell.m
// RETableViewManager
//
// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "RETableViewPickerCell.h"
#import "RETableViewManager.h"
#import "NSString+RETableViewManagerAdditions.h"
@interface RETableViewPickerCell ()
@property (strong, readwrite, nonatomic) UITextField *textField;
@property (strong, readwrite, nonatomic) UILabel *valueLabel;
@property (strong, readwrite, nonatomic) UILabel *placeholderLabel;
@property (strong, readwrite, nonatomic) UIPickerView *pickerView;
@end
@implementation RETableViewPickerCell
+ (BOOL)canFocusWithItem:(RETableViewItem *)item
{
return YES;
}
#pragma mark -
#pragma mark Lifecycle
- (void)cellDidLoad
{
[super cellDidLoad];
self.textLabel.backgroundColor = [UIColor clearColor];
self.textField = [[UITextField alloc] initWithFrame:CGRectNull];
self.textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.textField.inputAccessoryView = self.actionBar;
self.textField.delegate = self;
[self addSubview:self.textField];
self.valueLabel = [[UILabel alloc] initWithFrame:CGRectNull];
self.valueLabel.font = [UIFont systemFontOfSize:17];
self.valueLabel.backgroundColor = [UIColor clearColor];
self.valueLabel.textColor = self.detailTextLabel.textColor;
self.valueLabel.highlightedTextColor = [UIColor whiteColor];
self.valueLabel.textAlignment = NSTextAlignmentRight;
self.valueLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.contentView addSubview:self.valueLabel];
self.placeholderLabel = [[UILabel alloc] initWithFrame:CGRectNull];
self.placeholderLabel.font = [UIFont systemFontOfSize:17];
self.placeholderLabel.backgroundColor = [UIColor clearColor];
self.placeholderLabel.textColor = [UIColor lightGrayColor];
self.placeholderLabel.highlightedTextColor = [UIColor whiteColor];
[self.contentView addSubview:self.placeholderLabel];
self.pickerView = [[UIPickerView alloc] init];
self.pickerView.delegate = self;
self.pickerView.dataSource = self;
}
- (void)cellWillAppear
{
self.textLabel.text = self.item.title.length == 0 ? @" " : self.item.title;
self.textField.inputView = self.pickerView;
self.valueLabel.text = self.item.value ? [self.item.value componentsJoinedByString:@", "] : @"";
self.placeholderLabel.text = self.item.placeholder;
self.placeholderLabel.hidden = self.valueLabel.text.length > 0;
if (!self.item.title) {
self.valueLabel.textAlignment = NSTextAlignmentLeft;
}
}
- (void)layoutSubviews
{
[super layoutSubviews];
self.textField.frame = CGRectNull;
self.textField.alpha = 0;
[self layoutDetailView:self.valueLabel minimumWidth:[self.valueLabel.text re_sizeWithFont:self.valueLabel.font].width];
[self layoutDetailView:self.placeholderLabel minimumWidth:[self.placeholderLabel.text re_sizeWithFont:self.placeholderLabel.font].width];
if ([self.tableViewManager.delegate respondsToSelector:@selector(tableView:willLayoutCellSubviews:forRowAtIndexPath:)])
[self.tableViewManager.delegate tableView:self.tableViewManager.tableView willLayoutCellSubviews:self forRowAtIndexPath:[self.tableViewManager.tableView indexPathForCell:self]];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if (selected) {
[self.textField becomeFirstResponder];
[self.item.options enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self.pickerView selectRow:[[self.item.options objectAtIndex:idx] indexOfObject:[self.item.value objectAtIndex:idx]] inComponent:idx animated:NO];
}];
}
}
- (UIResponder *)responder
{
return self.textField;
}
- (void)shouldUpdateItemValue
{
NSMutableArray *value = [NSMutableArray array];
[self.item.options enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSArray *options = [self.item.options objectAtIndex:idx];
NSString *valueText = [options objectAtIndex:[self.pickerView selectedRowInComponent:idx]];
[value addObject:valueText];
}];
self.item.value = [value copy];
self.valueLabel.text = self.item.value ? [self.item.value componentsJoinedByString:@", "] : @"";
}
#pragma mark -
#pragma mark UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if (!self.selected)
[self setSelected:YES animated:NO];
NSIndexPath *indexPath = [self indexPathForNextResponder];
if (indexPath) {
textField.returnKeyType = UIReturnKeyNext;
} else {
textField.returnKeyType = UIReturnKeyDefault;
}
[self updateActionBarNavigationControl];
[self.parentTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.rowIndex inSection:self.sectionIndex] atScrollPosition:UITableViewScrollPositionTop animated:YES];
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
[self setSelected:NO animated:NO];
[self.item deselectRowAnimated:NO];
[self shouldUpdateItemValue];
self.placeholderLabel.hidden = self.valueLabel.text.length > 0;
return YES;
}
#pragma mark -
#pragma mark UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return self.item.options.count;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [[self.item.options objectAtIndex:component] count];
}
#pragma mark -
#pragma mark UIPickerViewDelegate
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSArray *items = [self.item.options objectAtIndex:component];
return [items objectAtIndex:row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
[self shouldUpdateItemValue];
}
@end

View File

@@ -0,0 +1,37 @@
//
// REPickerItem.h
// RETableViewManager
//
// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "RETableViewItem.h"
@interface REPickerItem : RETableViewItem
@property (strong, readwrite, nonatomic) NSArray *options;
@property (strong, readwrite, nonatomic) NSArray *value;
@property (copy, readwrite, nonatomic) NSString *placeholder;
+ (instancetype)itemWithTitle:(NSString *)title value:(NSArray *)value placeholder:(NSString *)placeholder options:(NSArray *)options;
- (id)initWithTitle:(NSString *)title value:(NSArray *)value placeholder:(NSString *)placeholder options:(NSArray *)options;
@end

View File

@@ -0,0 +1,51 @@
//
// REPickerItem.m
// RETableViewManager
//
// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "REPickerItem.h"
@implementation REPickerItem
+ (instancetype)itemWithTitle:(NSString *)title value:(NSArray *)value placeholder:(NSString *)placeholder options:(NSArray *)options
{
return [[self alloc] initWithTitle:title value:value placeholder:placeholder options:options];
}
- (id)initWithTitle:(NSString *)title value:(NSArray *)value placeholder:(NSString *)placeholder options:(NSArray *)options
{
self = [super init];
if (!self)
return nil;
self.title = title;
self.value = value;
self.style = UITableViewCellStyleValue1;
self.placeholder = placeholder;
self.value = value;
self.options = options;
return self;
}
@end

View File

@@ -284,6 +284,7 @@
if (!cell)
[self.parentTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
cell = (RETableViewCell *)[self.parentTableView cellForRowAtIndexPath:indexPath];
[self.responder resignFirstResponder];
[cell.responder becomeFirstResponder];
}
}

View File

@@ -37,6 +37,7 @@
#import "RETableViewDateTimeCell.h"
#import "RETableViewLongTextCell.h"
#import "RETableViewOptionCell.h"
#import "RETableViewPickerCell.h"
#import "REBoolItem.h"
#import "RERadioItem.h"
#import "RETextItem.h"
@@ -46,6 +47,7 @@
#import "REFloatItem.h"
#import "REDateTimeItem.h"
#import "REMultipleChoiceItem.h"
#import "REPickerItem.h"
@protocol RETableViewManagerDelegate;

View File

@@ -96,6 +96,7 @@
self[@"REDateTimeItem"] = @"RETableViewDateTimeCell";
self[@"RECreditCardItem"] = @"RETableViewCreditCardCell";
self[@"REMultipleChoiceItem"] = @"RETableViewOptionCell";
self[@"REPickerItem"] = @"RETableViewPickerCell";
}
- (void)registerClass:(NSString *)objectClass forCellWithReuseIdentifier:(NSString *)identifier

View File

@@ -64,6 +64,8 @@
30DB067816E934AD006C9530 /* RETableViewManager.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 30DB066516E934AD006C9530 /* RETableViewManager.bundle */; };
30DB067916E934AD006C9530 /* RETableViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DB066716E934AD006C9530 /* RETableViewManager.m */; };
30DB067A16E934AD006C9530 /* RETableViewSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DB066916E934AD006C9530 /* RETableViewSection.m */; };
30DBFA9117FC827D0099ACA5 /* REPickerItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DBFA9017FC827D0099ACA5 /* REPickerItem.m */; };
30DBFA9417FC84380099ACA5 /* RETableViewPickerCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 30DBFA9317FC84380099ACA5 /* RETableViewPickerCell.m */; };
30E16A48171A103400F7C258 /* EditingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E16A47171A103300F7C258 /* EditingViewController.m */; };
30E5F50C17BBD163005CF1FE /* IndexedListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30E5F50B17BBD163005CF1FE /* IndexedListViewController.m */; };
30EF93B316E039B800B84981 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30EF93B216E039B800B84981 /* UIKit.framework */; };
@@ -185,6 +187,10 @@
30DB066716E934AD006C9530 /* RETableViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RETableViewManager.m; sourceTree = "<group>"; };
30DB066816E934AD006C9530 /* RETableViewSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RETableViewSection.h; sourceTree = "<group>"; };
30DB066916E934AD006C9530 /* RETableViewSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RETableViewSection.m; sourceTree = "<group>"; };
30DBFA8F17FC827D0099ACA5 /* REPickerItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REPickerItem.h; sourceTree = "<group>"; };
30DBFA9017FC827D0099ACA5 /* REPickerItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REPickerItem.m; sourceTree = "<group>"; };
30DBFA9217FC84380099ACA5 /* RETableViewPickerCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RETableViewPickerCell.h; sourceTree = "<group>"; };
30DBFA9317FC84380099ACA5 /* RETableViewPickerCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RETableViewPickerCell.m; sourceTree = "<group>"; };
30E16A46171A103300F7C258 /* EditingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingViewController.h; sourceTree = "<group>"; };
30E16A47171A103300F7C258 /* EditingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditingViewController.m; sourceTree = "<group>"; };
30E5F50A17BBD163005CF1FE /* IndexedListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexedListViewController.h; sourceTree = "<group>"; };
@@ -370,6 +376,8 @@
300E5B4117170B0100910013 /* RETableViewLongTextCell.m */,
30D74552174EB4C900D4C7C1 /* RETableViewOptionCell.h */,
30D74553174EB4C900D4C7C1 /* RETableViewOptionCell.m */,
30DBFA9217FC84380099ACA5 /* RETableViewPickerCell.h */,
30DBFA9317FC84380099ACA5 /* RETableViewPickerCell.m */,
);
path = Cells;
sourceTree = "<group>";
@@ -395,6 +403,8 @@
300E5B3E17170AE100910013 /* RELongTextItem.m */,
30D208621718FFDE00144E46 /* REMultipleChoiceItem.h */,
30D208631718FFDE00144E46 /* REMultipleChoiceItem.m */,
30DBFA8F17FC827D0099ACA5 /* REPickerItem.h */,
30DBFA9017FC827D0099ACA5 /* REPickerItem.m */,
);
path = Items;
sourceTree = "<group>";
@@ -629,6 +639,7 @@
300E5B3F17170AE100910013 /* RELongTextItem.m in Sources */,
300E5B4217170B0200910013 /* RETableViewLongTextCell.m in Sources */,
30B35CEF17E54B670082CE0E /* RECommonFunctions.m in Sources */,
30DBFA9417FC84380099ACA5 /* RETableViewPickerCell.m in Sources */,
30BB805E17E0D8E700AD0861 /* MultilineTextItem.m in Sources */,
30082D1A17170EDD008B0DB5 /* REPlaceholderTextView.m in Sources */,
30D208641718FFDE00144E46 /* REMultipleChoiceItem.m in Sources */,
@@ -642,6 +653,7 @@
30E5F50C17BBD163005CF1FE /* IndexedListViewController.m in Sources */,
30BB805B17E0D8C300AD0861 /* XIBTestItem.m in Sources */,
30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */,
30DBFA9117FC827D0099ACA5 /* REPickerItem.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -29,6 +29,7 @@
@property (strong, readwrite, nonatomic) REMultipleChoiceItem *multipleChoiceItem;
@property (strong, readwrite, nonatomic) RELongTextItem *longTextItem;
@property (strong, readwrite, nonatomic) RECreditCardItem *creditCardItem;
@property (strong, readwrite, nonatomic) REPickerItem *pickerItem;
@end
@@ -101,6 +102,7 @@
self.dateTimeItem.onChange = ^(REDateTimeItem *item){
NSLog(@"Value: %@", item.value.description);
};
self.pickerItem = [REPickerItem itemWithTitle:@"Picker" value:@[@"Item 12", @"Item 23"] placeholder:nil options:@[@[@"Item 11", @"Item 12", @"Item 13"], @[@"Item 21", @"Item 22", @"Item 23", @"Item 24"]]];
self.radioItem = [RERadioItem itemWithTitle:@"Radio" value:@"Option 4" selectionHandler:^(RERadioItem *item) {
[item deselectRowAnimated:YES]; // same as [weakSelf.tableView deselectRowAtIndexPath:item.indexPath animated:YES];
@@ -172,6 +174,7 @@
[section addItem:self.boolItem];
[section addItem:self.floatItem];
[section addItem:self.dateTimeItem];
[section addItem:self.pickerItem];
[section addItem:self.radioItem];
[section addItem:self.multipleChoiceItem];
[section addItem:self.longTextItem];