我有一个 UIWebview 包含一个 html“选择”标签,它在屏幕上显示为一个。
当我点击下拉菜单时,UIWebview 会自动弹出一个 UIWebSelectSinglePicker 视图,显示为.
我想更改选择器视图背景颜色和文本颜色。我怎样才能实现这个目标?
我尝试监听 UIKeyboardWillShowNotification 事件,但此时尚未创建此视图。
提前感谢您的帮助。
我设法自己解决了这个问题。
如果有人还想即时更改 UIPickView,请查看:
首先,在 UIKeyboardWillShowNotification 事件上添加一个监听器。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_pickerViewWillBeShown:) name:UIKeyboardWillShowNotification object:nil];
其次,当通知触发时,延迟后调用更改背景颜色方法。<-- 这点很重要,如果不延迟调用方法,此时pickview不存在。
- (void)_pickerViewWillBeShown:(NSNotification*)aNotification {
[self performSelector:@selector(_resetPickerViewBackgroundAfterDelay) withObject:nil afterDelay:0];
}
第三,浏览 UIApplication 窗口并找出 pickerView。你可以改变任何你想要的pickerView。
-(void)_resetPickerViewBackgroundAfterDelay
{
UIPickerView *pickerView = nil;
for (UIWindow *uiWindow in [[UIApplication sharedApplication] windows]) {
for (UIView *uiView in [uiWindow subviews]) {
pickerView = [self _findPickerView:uiView];
}
}
if (pickerView){
[pickerView setBackgroundColor:UIColorFromRGB(0x00FF00)];
}
}
(UIPickerView *) _findPickerView:(UIView *)uiView {
if ([uiView isKindOfClass:[UIPickerView class]] ){
return (UIPickerView*) uiView;
}
if ([uiView subviews].count > 0) {
for (UIView *subview in [uiView subviews]){
UIPickerView* view = [self _findPickerView:subview];
if (view)
return view;
}
}
return nil;
}
希望它会有所帮助。
我相信我已经想出了解决这个问题的替代方案。在某些情况下,建议的其他解决方案标签颜色显示不正确(使用系统默认值而不是覆盖的颜色)。滚动项目列表时会发生这种情况。
为了防止这种情况发生,我们可以使用方法 swizzling 在它们的源处修复标签颜色(而不是在它们已经创建后修补它们)。
显示的UIWebSelectSinglePicker
(如您所说)实现了 UIPickerViewDelegate 协议。该协议负责提供 NSAttributedString 实例,这些实例通过该- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component
方法显示在选择器视图中。通过使用我们自己的方法来调整实现,我们可以覆盖标签的外观。
为此,我在 UIPickerView 上定义了一个类别:
@implementation UIPickerView (LabelColourOverride)
- (NSAttributedString *)overridePickerView:(UIPickerView *)pickerView
attributedTitleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
// Get the original title
NSMutableAttributedString* title =
(NSMutableAttributedString*)[self overridePickerView:pickerView
attributedTitleForRow:row
forComponent:component];
// Modify any attributes you like. The following changes the text colour.
[title setAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]}
range:NSMakeRange(0, title.length)];
// You can also conveniently change the background of the picker as well.
// Multiple calls to set backgroundColor doesn't seem to slow the use of
// the picker, but you could just as easily do a check before setting the
// colour to see if it's needed.
pickerView.backgroundColor = [UIColor yellowColor];
return title;
}
@end
然后使用方法 swizzling(请参阅此答案以供参考)我们交换实现:
[Swizzle swizzleClass:NSClassFromString(@"UIWebSelectSinglePicker")
method:@selector(pickerView:attributedTitleForRow:forComponent:)
forClass:[UIPickerView class]
method:@selector(overridePickerView:attributedTitleForRow:forComponent:)];
这是我根据上面的链接开发的 Swizzle 实现。
@implementation Swizzle
+ (void)swizzleClass:(Class)originalClass
method:(SEL)originalSelector
forClass:(Class)overrideClass
method:(SEL)overrideSelector
{
Method originalMethod = class_getInstanceMethod(originalClass, originalSelector);
Method overrideMethod = class_getInstanceMethod(overrideClass, overrideSelector);
if (class_addMethod(originalClass,
originalSelector,
method_getImplementation(overrideMethod),
method_getTypeEncoding(overrideMethod))) {
class_replaceMethod(originalClass,
overrideSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
}
else {
method_exchangeImplementations(originalMethod, overrideMethod);
}
}
@end
这样做的结果是,当请求一个标签时,我们的覆盖函数被调用,它调用原始函数,它方便地返回给我们一个可变的 NSAttributedString,我们可以随意修改它。如果我们愿意,我们可以完全替换返回值并保留文本。在此处找到您可以更改的属性列表。
此解决方案允许您通过一次调用全局更改应用程序中的所有 Picker 视图,从而无需为需要此代码的每个视图控制器注册通知(或定义一个基类来执行相同操作)。