customizing UISearchBarIconClear for UIControlStat

2019-04-26 12:34发布

问题:

I have a UISearchBar for which I have set a custom UISearchBarIconClear for UiControlStateNormal.

[mySearchBar setImage:myImage forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];

This part works as it should but unfortunately when tapping the clear button, it changes from the image I set, to the original default gray one.

I have tried setting the image for UIControlStateHighlighted, but apparently that does not work.

The documentation actually states

Valid states are UIControlStateNormal and UIControlStateDisabled.

What's the point of setting a custom button for the default state if you can't set it for the highlighted state? Am I missing something? Any thoughts or workarounds appreciated, thanks!

回答1:

Came across the same issue a little bit earlier today, here is my really ugly workaround that I probably wouldn't use myself.

for(UIView *subView in searchBar.subviews) {
    if([subView isKindOfClass: [UITextField class]]){
        UITextField *searchField = (UITextField *)subView;
        CGFloat myWidth = 26.0f;
        CGFloat myHeight = 30.0f;
        UIButton *myButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, myWidth, myHeight)];
        [myButton setImage:[UIImage imageNamed:@"searchbariconclear"] forState:UIControlStateNormal];
        [myButton setImage:[UIImage imageNamed:@"searchbariconclear"] forState:UIControlStateHighlighted];

        [myButton addTarget:self action:@selector(clearsearchbar) forControlEvents:UIControlEventTouchUpInside];

        searchField.rightView = myButton;
        searchField.rightViewMode = UITextFieldViewModeAlways;
        searchField.clearButtonMode = UITextFieldViewModeNever;
    }
}

And then..

- (void)clearsearchbar {
    for(UIView *subView in searchBar.subviews) {
        if([subView isKindOfClass: [UITextField class]]){
            UITextField *searchField = (UITextField *)subView;
            searchField.text = nil;
        }
    }
}

Three problems with this approach..

  1. Since we're digging around inside the subviews of the searchbar it could break some day with an OS update.

  2. This doesn't behave exactly like UISearchBarIconClear, in that the clear icon will always be visible.. You could potentially try testing with other UITextFieldViewModes using this approach, I didn't mainly because, from what I know none of the others would be ideal here, for some reason or the other.

  3. Maybe it's just me, but I don't really think that something that introduces two problems when trying to solve one, is a solution. :-)

If anyone has a better way of tackling this problem, I'd love to hear it too.



回答2:

I had the same problem, and adjusting the order of the statements solved it:

So instead of doing UIControlStateNormal first then UIControlStateHighlighted, set the image for Highlighted state first

[searchBar setImage:clearIcon forSearchBarIcon:UISearchBarIconClear state:UIControlStateHighlighted];
[searchBar setImage:clearIcon forSearchBarIcon:UISearchBarIconClear state:UIControlStateNormal];


回答3:

How about using appearance proxy?

[[UIButton appearanceWhenContainedIn:[UITextField class], [UISearchBar class], nil] setImage:myImage forState:UIControlStateHighlighted];


回答4:

I just had the same problem as you described with the clear icon reseting to the default icon upon being pressed.

This seems to be due to me trying to use the same UIImage for both the normal and highlighted state, switching to a different image for the highlighted state fixed the problem.