我已经对这个问题进行了很多研究,但是我还不清楚它是否可能。基本上我想做的是创建一个连续的UIPickerView
,你可以永久地旋转它,你将永远不会到达它的末尾(因为最后一个值后跟第一个值)。 / p>
我在网上看过,似乎有各种各样的黑客可以达到预期的效果。然而,很多这些解决方案似乎增加了UIPickerView
中的行数以诱使用户认为UIPickerView
是连续的(但是,实际上如果他们继续滚动它们最终会到达终点)
我所追求的是一种创建UIPickerView的方法,如果你继续滚动数天,数周,数月或数年,你将永远无法达到目的。如果解决方案是黑客攻击,我不介意太多,因为我知道Apple还没有提供实现这种效果的方法。
请有人建议这样做(或至少指出我正确的方向)?
答案 0 :(得分:4)
我真的认为,你可以用本机UIPickerView做的唯一的黑客在这里描述:
How do you make an UIPickerView component wrap around?
另一种方法是使真正的循环选择器是自己实现它。
我看到使用cocos2d实现的选择器,即基于OpenGL的选择器。我想,如果你真的需要,可以尝试使用UIKit。
或者只是忘记它并使用具有可重复内容的NSIntegerMax行创建一个选择器。我想没有人会把它旋转到最后。
答案 1 :(得分:3)
找到自定义UIPickerView
类,该类工作得非常好并且非常容易实现
here
答案 2 :(得分:2)
这是可能的。这是你如何做到的。首先设置一个计时器。我们假设int maxNumber
是一个设置为某个任意值的实例变量。
- ( void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(timerFireMethod:) userInfo:nil repeats:YES];
}
- (void) viewWillDisappear:(BOOL)animated{
[self.timer invalidate];
[super viewWillDisappear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.infinitePickerView selectRow:(int)maxNumber*5 inComponent:0 animated:YES];
}
在计时器点火方法中,检查uipickerview的任何“边缘”视图是否正在显示。
- (void)timerFireMethod:(NSTimer*)theTimer{
int rowSelected = [self.infinitePickerView selectedRowInComponent:0];
for (int i=0; i<= 20; i++) {
UIView * viewBelow = [self.infinitePickerView viewForRow:i forComponent:0];
UIView * viewAbove = [self.infinitePickerView viewForRow:maxNumber*10-20+i forComponent:0];
if(viewBelow!=nil || viewAbove!=nil){
int middlePosition = maxNumber * 5 + (rowSelected % maxNumber);
[self.infinitePickerView selectRow:middlePosition inComponent:0 animated:NO];
break;
}
}
}
请注意这是有效的,因为[self.infinitePickerView viewForRow:i forComponent:0];
只有在可见时才会返回UIView。
当然,您的UIPickerViewDelegate
必须使用类似
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return maxNumber * 10; //returning a large number
}
//You cannot use this method
/*
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{}
You have to use the method below in lieu of it
*/
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view{
UILabel * label;
if (!view) {
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.infinitePickerView.bounds.size.width, 30)];
}else {
label = (UILabel *) view;
}
[label setText:[NSString stringWithFormat:@" %d", row % maxNumber]];
return label;
}
希望这个有效!!祝你好运!
答案 3 :(得分:2)
没有包装的原生选择器(不管是iOS7.1还是如此。)你可以通过以下方式来伪装:
NSArray *picks = @[ @"zero", @"one", @"two", @"three" ]; // 4 entries
// ...
- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component
{
return (3 * [picks count]); // we're very tricky, displaying only
// ...the SECOND set of entries, to
// ... give the impression of wrap-around
}
// ...
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
// All "3" sets of entries have the same values;
// this is what gives the appearance of wrap-around.
int titleRow = row % [picks count];
return [picks objectAtIndex: titleRow];
}
// ...
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
// If the wheel turns to outside our 2nd-set range,
// ...set it to the matching item in the 2nd set.
// In this way, we always display what looks like a wrap-around.
int count = [picks count];
if ((row < count)
|| (row > (count * 2) )
{
[pickerView selectRow: (row % count) inComponent: component animated: NO];
}
}
当然,您必须进行调整和调整以满足您的需求,但这是它的基本要点。
祝你好运!答案 4 :(得分:0)
答案 5 :(得分:0)
在我看来,需要将大量数据填充到pickerView中的解决方案是浪费的。以下解决方案使用智能而不是内存。
需要填充的唯一行是视图中可见的行以及紧接在第一个之前的行和紧跟在最后一个之后的行。当用户滚动组件时,将为每个滚动的行调用pickerView:titleForRow:forComponent:。
所以解决方案是更新pickerView:titleForRow:forComponent:中的数据,然后调用适当的方法重新加载数据,以便当pickerview再滚动一次时它就在那里。
答案 6 :(得分:0)
我知道这是一个老问题,但我发现它只是在我自己的项目中实现它。
只需使用Morion的大量项目重复内容的方法,然后每次停止滚动,重置行。任何人都会弄清楚你被欺骗的唯一方法是,如果他们连续不断地滚动直到它停止,从不调用didSelectRow函数。需要一些奉献精神!
无论你怎么做,在我看来,它会感觉有点hacky,&amp;这一定是最简单的黑客...
答案 7 :(得分:0)
我基于UIScrollView
创建了一个循环表。基于此tableView,我重新实现了UIPickerView
。你可能对此感兴趣。此选择器视图具有UIPickerView
的所有功能,但也提供了许多新功能,并且自定义此选择器视图更容易。
https://github.com/danleechina/DLPickerView
请注意,此DLPickerView循环滚动实际上是循环滚动。所有的魔法都是因为另一个班级DLTableView
而发生的。
答案 8 :(得分:0)
我使用pickerView Selection来创建一个圆形的:
MAIL_ENCRYPTION=
答案 9 :(得分:0)
一个非常简单的解决方案,通过按比例放大数组并使模数从数组中选择相应的项目,你会认为拾取器视图没有结束
override func viewDidLoad(){
super.viewDidLoad()
self.yourArray.selectRow((yourArray.count*100)/2, inComponent: 0, animated: false)
}
func pickerView(_ pickerView: UIPickerView, numberOfRowaInComponent component: Int) -> Int{
return yourArray.count*100
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int)->String{
return yourArray[row % yourArray.count]
}