UIPickerView 不会立即重绘未选中的行
UIPickerView doesn't immediately redraw unselected rows
我有一个特殊的 UIPickerView
,其中行是通过点击手动 select 编辑的。当发生这种情况时,selected 行的样式会发生变化(文本颜色会发生变化,并显示带有复选标记的图像)。同样,如果另一行是 selected,则先前 selected 的行是 "deselected",即它的样式更改为正常。
现在,当我 select 一行时,它看起来是正确的:
但是,当我滚动到另一行并且 selected 行不再位于中间时,它的新样式未应用(Antarktis 应在此处 selected):
但是,如果我进一步向下滚动几行然后返回,它会将行更新为正确的样式:
我在 deselecting 时遇到了同样的问题。如果我 select 另一行旧行似乎没有 deselected 我明白了(Antarktis 现在应该 deselected):
但是如果我将 Antarktis 行向后滚动到中间,它确实被删除了select。
所以我的问题是 UIPickerView
不会立即重绘可见但不在中间的行(它们可能以某种方式缓存)。它们仅在特定行离开视图然后 returns 或显示全新行时才重绘。
那么我可以强制它重绘那些行吗?我尝试在 UIPickerView
和特定行(它们是 UITableViewCell
的子类)上调用 setNeedsDisplay
方法,但它什么也没做。
谢谢!
您是否尝试过在 UIPickerView
实例上调用 reloadComponent:
或 reloadAllComponents
?
我在这里发布我的答案是为了解释我在使用 reloadAllComponents
时作为副作用的解决方法,正如 fpg1503 在他的答案中所建议的那样。
基本上我记得选择,然后在 reloadAllComponents
完成后以编程方式再次设置它:
// We tell the picker to reload data in order to force it to redraw all rows.
// Otherwise it may look like multiple rows are selected as checkmarks from previously selected row remains visible.
// When reloading data the picker will automatically scroll to first row. That's why we will make it to go to the selected row afterwards.
NSInteger selectedIndex = [self.countryCodePicker selectedRowInComponent:0];
[self.countryCodePicker reloadAllComponents];
// We have to make the selection with a delay, otherwise it may perform it before reloading was finished.
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.countryCodePicker selectRow:selectedIndex inComponent:0 animated:NO];
});
@NobleK 感谢您的快速回复!我尝试了您的解决方案,但发现选择器来回移动的视觉效果令人分心-但是...这给了我一个好主意:问题实际上不是导致跳转的对 reloadAllComponents 的调用-这是gestureRecognizer 在重新加载后会把事情搞砸。所以...我所做的是将重新加载调用放入定时调度中,瞧!完美运行! :-D
// delay the reload slightly
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
{
[self.pickerView reloadAllComponents];
});
我有一个特殊的 UIPickerView
,其中行是通过点击手动 select 编辑的。当发生这种情况时,selected 行的样式会发生变化(文本颜色会发生变化,并显示带有复选标记的图像)。同样,如果另一行是 selected,则先前 selected 的行是 "deselected",即它的样式更改为正常。
现在,当我 select 一行时,它看起来是正确的:
但是,当我滚动到另一行并且 selected 行不再位于中间时,它的新样式未应用(Antarktis 应在此处 selected):
但是,如果我进一步向下滚动几行然后返回,它会将行更新为正确的样式:
我在 deselecting 时遇到了同样的问题。如果我 select 另一行旧行似乎没有 deselected 我明白了(Antarktis 现在应该 deselected):
但是如果我将 Antarktis 行向后滚动到中间,它确实被删除了select。
所以我的问题是 UIPickerView
不会立即重绘可见但不在中间的行(它们可能以某种方式缓存)。它们仅在特定行离开视图然后 returns 或显示全新行时才重绘。
那么我可以强制它重绘那些行吗?我尝试在 UIPickerView
和特定行(它们是 UITableViewCell
的子类)上调用 setNeedsDisplay
方法,但它什么也没做。
谢谢!
您是否尝试过在 UIPickerView
实例上调用 reloadComponent:
或 reloadAllComponents
?
我在这里发布我的答案是为了解释我在使用 reloadAllComponents
时作为副作用的解决方法,正如 fpg1503 在他的答案中所建议的那样。
基本上我记得选择,然后在 reloadAllComponents
完成后以编程方式再次设置它:
// We tell the picker to reload data in order to force it to redraw all rows.
// Otherwise it may look like multiple rows are selected as checkmarks from previously selected row remains visible.
// When reloading data the picker will automatically scroll to first row. That's why we will make it to go to the selected row afterwards.
NSInteger selectedIndex = [self.countryCodePicker selectedRowInComponent:0];
[self.countryCodePicker reloadAllComponents];
// We have to make the selection with a delay, otherwise it may perform it before reloading was finished.
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self.countryCodePicker selectRow:selectedIndex inComponent:0 animated:NO];
});
@NobleK 感谢您的快速回复!我尝试了您的解决方案,但发现选择器来回移动的视觉效果令人分心-但是...这给了我一个好主意:问题实际上不是导致跳转的对 reloadAllComponents 的调用-这是gestureRecognizer 在重新加载后会把事情搞砸。所以...我所做的是将重新加载调用放入定时调度中,瞧!完美运行! :-D
// delay the reload slightly
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
{
[self.pickerView reloadAllComponents];
});