Adjust insets of UISearchController's searchBar - ios

I'm trying out some designs and I'd like to have an equal 25px margin for all my subviews. UISearchController's searchBar has a 16px padding on either sides out of the box. Do I have to write the search bar textfield from scratch, or is there ANY way, undocumented, swizzling, or otherwise, to accomplish offsetting the native bar to my taste?

If you are using a UISearchController you can set the margins of the searchBar like this (assuming searchBar is the UISearchController instance):
let directionalMargins = NSDirectionalEdgeInsets(top: 0, leading: 25, bottom: 0, trailing: 25)
searchController.searchBar.directionalLayoutMargins = directionalMargins

For UISearchBar text position use:
searchBar.searchTextPositionAdjustment = .init(horizontal: 25, vertical: 0)

Related

TableView ReparatorInset Width - Swift 4 Without Storyboard

I'm trying to design an app with the width of the separatorInset being short. I can achieve that but the label in the cell gets short also.
tableView.separatorInset = UIEdgeInsets(top: 0, left: 205, bottom: 0, right: 10)
Is it possble to target the actual separatorInset only and not to width of the row? The label should not be affected. I only need to shorten the separator.
Result expected:
Your best bet is to use custom cells and to have a UIView with 1px height as separator.

CollectionView header content under status bar

Here's a collection view constrained to top, left, right, and bottom of the superview with safe area layout guide enabled:
I want my collection view header to be shown under the status bar. I've achieved this for iPhone 4 - 8+ screen dimensions by unchecking Safe Area Layout Guide in the size inspector for the controller's main view, and adding the following code:
collectionView.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0)
This looks great for non iPhone X view sizes:
However, for the iPhone X, this leads to the following output:
The iPhone X has its own dimensions for the status bar. Adjusting the top inset further does work, but will over-offset the other device sizes. I am wondering if there's an more elegant way to achieve this behaviour.
Found a solution:
collectionView.contentInset.top = -UIApplication.shared.statusBarFrame.height
The previous solutions work, but this might be the easiest one:
collectionView.contentInsetAdjustmentBehavior = .never
This will do
collectionView.contentInsetAdjustmentBehavior = .never
You should use safeAreaInsets for iphone X
if #available(iOS 11.0, *) {
if let top = UIApplication.shared.keyWindow?.safeAreaInsets.top {
collectionView.contentInset = UIEdgeInsets(top: -top, left: 0, bottom: 0, right: 0)
}
} else {
// Fallback on earlier versions
collectionView.contentInset.top = -UIApplication.shared.statusBarFrame.height
}
Add 2 constraints:
1) view - superview
2) view - safeArea

How do I best create a button with a left aligned icon and the text centered in the remaining area

I need to have a button that looks like this:
Right now I went for a view with two buttons inside it. But the problem with that is that I can either hook up the two individual buttons to the same outlet, or add a UITapGestureRecognizer to the container view.
I went with the second option because I thought it would be cleaner, but that only works when I disable the buttons (and therefore disable the press-down animation).
Am I on the right track, and should I just find a way to trigger the button's animation when the UITapGestureRecognizer calls my method? Or is there a better way to do this?
You want to use a single UIButton and adjust the imageEdgeInsets & titleEdgeInsets.
For a Swift example:
extension UIButton {
func centerTextAndImage(spacing: CGFloat) {
let insetAmount = spacing / 2
imageEdgeInsets = UIEdgeInsets(top: 0, left: -insetAmount, bottom: 0, right: insetAmount)
titleEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: -insetAmount)
contentEdgeInsets = UIEdgeInsets(top: 0, left: insetAmount, bottom: 0, right: insetAmount)
}
}
The size inspector tab for UIButton has an Insets section at the top. Play around with the insets values of title insets and image insets to achieve the desired result.
And you don't need to use multiple buttons in a view or tap gesture to achieve this. Just 1 single button would suffice.

iOS: Table view, allow scrolling "further down" than the end

Sorry the question sounds a bit confusing. I have two buttons overlapping my table view at the bottom, so if the table view scrolls "normal" the last row is partially hidden by these buttons. That's why I want to allow scrolling the table like the height of one row further down, so the last row is on top of these two buttons. How can I achieve this?
Adjust the content insets of the table view.
For instance, if your buttons are 50 points in height and your table's frame is the full window, you could set your table to snap to the top of your buttons like this:
tableView.contentInset = UIEdgeInsetsMake(0, 0, 50, 0);
Note: In iOS 7+ view controllers have a property automaticallyAdjustsScrollViewInsets that is set to YES by default. When this property is set to YES, the contentInsets you set manually may be overridden. Assuming you have a nav bar of some kind that you want to scroll under, you can set your top edge inset to the length of the topLayoutGuide.
Your final solution (put this in viewDidLoad):
self.automaticallyAdjustsScrollViewInsets = NO;
tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 50, 0);
As pointed out by others, deprecations have made this solution impossible, and if we use a section footer, this will display at the inset all the time. A much simpler solution would be to add a tableFooterView to allow the bottom cells to scroll past the buttons. Like so:
let bottomView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 83))
bottomView.backgroundColor = .clear
tableView.tableFooterView = bottomView
This will make it so the contents shift up.
If you want them to shift down you can change the insets accordingly.
func shiftScrollingUp() {
yourScrollView.contentInsetAdjustmentBehavior = .never
yourScrollView.contentInset = UIEdgeInsetsMake(0, 0, 150, 0)
}
AutomaticallyAdjustsScrollViewInsets is deprecated in ios 11.

UITextView content inset

I have encountered something a bit strange with contentInsets
I have a UITextView in my storyboard with a contentInset of 50 left, as I'm trying to add some padding to my uitextview
However, a scrollbar appears on the bottom of the uitextview, as shown below in this test:
I was under the impression that contentInset squashes the uitextview without causing this horizontal scroll bar, so how can I remove the need for the horizontal scrollbar and make everything--the inset AND all the text in the uitextview--visible without the need for this scrollbar.
N.B: I'm not asking about preventing the scrolling horizontally or not displaying the scrollbar(thus cutting of the text)
Thanks a lot!
For atomk(UITextView is called ss)
NSLog(#"Content Size Before %f",self.ss.contentSize.width); Logs: 280
CGSize size=self.ss.contentSize; size.width=size.width-50;
[self.ss setContentSize:size];
NSLog(#"Content Size After %f",self.ss.contentSize.width); Logs: 230
There is no visible difference between the view with the code added than before it was added, so something's going wrong!
(Thanks)
In iOS 7 UITextView is based on TextKit and has a new property textContainerInset. It behaves just as you would expect:
UITextView *textView = ...;
// Left inset of 50 points
textView.textContainerInset = UIEdgeInsetsMake(0.0, 50.0, 0.0, 0.0);
Swift 4.2
textView.textContainerInset = UIEdgeInsets(top: 0, left: 50, bottom: 0, right: 0)
UPDATE: This solution is out of date as of iOS 7.
See this answer below. In iOS 7.0, the textContainerInset property on UITextView was introduced.
Objective-C:
textView.textContainerInset = UIEdgeInsetsMake(0, 50, 0, 0);
Swift:
textView.textContainerInset = UIEdgeInsets(top: 0, left: 50, bottom: 0, right: 0)
Or as Zeev Vax suggested, in Swift 5.0:
textView.textContainerInset.left = 50
Pre-iOS 7 solution:
I was under the impression that contentInset squashes the uitextview without causing this horizontal scroll bar...
I'm afraid this is not how contentInset works with a UITextView. See Apple's documentation for contentInset where it states:
The distance that the content view is inset from the enclosing scroll view... Use this property to add to the scrolling area around the content.
The contentInset is added around the content.
You can change the contentSize in viewDidLayoutSubviews using the code you have included above:
- (void)viewDidLayoutSubviews
{
self.textView.contentInset = UIEdgeInsetsMake(0, 50, 0, 0);
NSLog(#"Content Size Before %f",self.textView.contentSize.width); //Logs: 280
CGSize size=self.textView.contentSize;
size.width=size.width-50;
[self.textView setContentSize:size];
NSLog(#"Content Size After %f",self.textView.contentSize.width); //Logs: 230
}
However, this causes the text to be cut off on the right side:
The best way I have been able to achieve the appearance of horizontal padding in a UITextView is to position it inside a container UIView. In your case, simply create a UIView the same size as your current text view, and add a text view that is 50px narrower inside the container view.
This workaround can cause problems if you have a background for your text view, but from your screenshot above it doesn't look like that's an issue for you.
UITextView (frame in red) inside UIView container:
If your UITextView does have a background, see:
How to set UITextView's content inset like Notes App
Stuff you learn from reverse-engineering Notes.app (see "iPadding" section)

Resources