1

I am creating a UI component that should display a UILabel and a UISearchBar below.

However, I am not able to align them, the UISearchBar always has extra space on both left and right side (highlighted RED).

I was trying to set the dimensions of searchBarTextField by layout anchors directly, but it didn't work.

I would prefer to do it using layout anchors when possible.

SearchBar.m:

-(id) init {        
    self.titleLabel = [UILabel new];
    self.searchBar = self.searchController.searchBar;
    UIView *searchBarWrapper = [UIView new];

    [self.view addSubview:self.titleLabel];
    [self.view addSubview:searchBarWrapper];
    [searchBarWrapper addSubview:self.searchBar];

    [self.titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
    [searchBarWrapper setTranslatesAutoresizingMaskIntoConstraints:NO];
    [self.searchBar setTranslatesAutoresizingMaskIntoConstraints:NO];

    //[self.titleLabel.widthAnchor constraintEqualToAnchor:self.view.widthAnchor multiplier:1.0].active = YES;
    [self.titleLabel.heightAnchor constraintEqualToConstant:14.0].active = YES;
    [self.titleLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
    [self.titleLabel.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
    [self.titleLabel.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES;
    //[self.titleLabel.bottomAnchor constraintEqualToAnchor:searchBarTextField.topAnchor].active = YES;

    [searchBarWrapper.widthAnchor constraintEqualToAnchor:self.view.widthAnchor multiplier:1.0].active = YES;
    //[self.searchBar.heightAnchor constraintEqualToConstant:36.0].active = YES;
    [searchBarWrapper.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor].active = YES;
    [searchBarWrapper.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
    [searchBarWrapper.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
    [searchBarWrapper.rightAnchor constraintEqualToAnchor:self.view.rightAnchor].active = YES;

    [self.searchBar.topAnchor constraintEqualToAnchor:searchBarWrapper.topAnchor].active = YES;
    [self.searchBar.bottomAnchor constraintEqualToAnchor:searchBarWrapper.bottomAnchor].active = YES;
    [self.searchBar.leftAnchor constraintEqualToAnchor:searchBarWrapper.leftAnchor].active = YES;
    [self.searchBar.rightAnchor constraintEqualToAnchor:searchBarWrapper.rightAnchor constant:16.0].active = YES;

    return self;
}

Left and right spaces highlishted

The UISearchBarTextField is embedded in a UIView to which I don't have access to.

The constraints:

The constraints and view hierarchy

The approach by @BenOng - works fine, but breaks after tapping for the first time:

Tapping

Peter G.
  • 7,816
  • 20
  • 80
  • 154

1 Answers1

0

UISearchBar have this property searchFieldBackgroundPositionAdjustment:UIOffset which you can set to UIOffsetMake(-8,0) to make the left side of the text field align with the left edge of the search bar.

Create a UIView right where the full search bar should be and make the search bar it's subview. Set the right edge of the search bar beyond it's super view till the right edge aligns with the superview, it should be about 16 points extra. Make sure the superview's property clipsToBoundsis set to true, the extra 16 points of search bar background will be clipped.

Ben Ong
  • 913
  • 1
  • 10
  • 25
  • Setting `UIOffsetMake(-8,0)` helped to solve the problem with the left offset. But setting a UIView as superview doesn't really work for me. It works at the beginning, but then after tapping the search bar its layout gets recomputed with the extra 16 points blank. Also, you suggested `clipsToBounds`, will make the edges on the right side not round. – Peter G. Jul 19 '18 at 09:15
  • 1
    Did you set the constraints correctly? The UISearchBar's original constraint should be applied to the UIView and the search bar made into it's subview with constraint align trailing -16. That should put the trailing edge of the textField along the superview's trailing. – Ben Ong Jul 19 '18 at 09:38
  • 1
    clipsToBound should only clip the extra space which we push out of the superview away. If part of the textField gets clipped maybe try a larger value instead of -16 as trailing. -16 is only a guess based on the spacing, might be lesser. – Ben Ong Jul 19 '18 at 09:39
  • I did all the steps as you described, the search bar looks alright when it gets rendered. But after tapping the search bar for the first time (only the first time), the search field gets displaced (around 8px down, the 16px are missing on the right). Then I rotate the device to rerender the search field after that can tap as many times as I want it works fine. I receive no layout constraint warnings in the console. – Peter G. Jul 19 '18 at 09:55
  • You can check the updated code and added screenshot. – Peter G. Jul 19 '18 at 10:09
  • Shouldn't there be a view below the searchBarWrapper? why is it anchored to self.view? I can't be sure if that is the cause but try setting the bottom constraint of searchBarWrapper to the view below it instead of self.view. – Ben Ong Jul 19 '18 at 10:15
  • You mean a wrapper around the wrapper? "Create a UIView right where the full search bar should be and make the search bar it's subview" => that's why `searchBarWrapper` was created there "Shouldn't there be a view below the searchBarWrapper?" => there is `[searchBarWrapper addSubview:self.searchBar];` – Peter G. Jul 19 '18 at 11:58
  • No, I mean there should be since your search bar is at the top of the screen there should be other views between thee search bar and the bottom of the screen no? I think it might help to set constraints to those views instead of the super view – Ben Ong Jul 20 '18 at 00:47
  • I'm already doing that, " there should be other views between thee search bar and the bottom of the screen" => the parent view of the search bar including the title view (`SearchBar.m`) is set to fixed dimensions 250x50. That view is set as the `titleView` of the `navigationItem`. – Peter G. Jul 20 '18 at 07:16