How to remove top padding for text in UITextView Swift - ios

I have a unusual problem. First i have Nav Controller and as a one page i have view controller with top panel for back button. I added uiview and uitextview on it. Then i make all needed constraints and after run and see top padding for text in textview about ~60 px . And i dont really know how to remove it.
I tried:
textViewUserInput.contentInset = UIEdgeInsetsMake(-50, 5, 5, 5);
it works but value -50 for top inset is not good for different devices and orientation
I also tried:
textViewUserInput.textContainerInset = UIEdgeInsetsZero;
textViewUserInput.textContainer.lineFragmentPadding = 0;
doesn't change anything

In Main.storyboard, select your view controller the one that has the UITextView in and underneath your attributes inspector tab uncheck "Adjust scroll view insets". I had the same problem and that worked for me.

Or you can add [textView setTextContainerInset:UIEdgeInsetsZero]; or textView.textContainerInset = .zero in your code.

Related

Center a scrollable InputAccessoryView

All,
I have a scrollable InputAccessoryView attached to my UITextView.
This was created as follows:
create a UIScrollView
add a horizontal UIStackView.
Attach top, bottom, trailing, leading of stack view to scroll view.
Set equal heights between stack and scroll.
Insert lots of buttons into stack view.
set TextView.inputaccessoryview = scrollview.
Voila! (Note - only the last line was programmatic).
So this works fine and correctly scrolls when the content (stack view) is wider than keyboard, BUT when you rotate to landscape (or run on an iPad), it is left aligned.
I'd like the buttons to be centred when the keyboard is wider than the set of buttons.
I've tried embedding the Scrollview into a UIView with Center X, but that doesn't seem to work.
Can anyone give me some pointers?
Thx
Found it!
The answer is to use ContentInset on the scrollbar (which is the InputAccessoryView above). The specific code is:
public void CentreToolbar()
{
var offsetX = Math.Max((scrollView.Bounds.Width - scrollView.ContentSize.Width) / 2, 0);
scrollView.ContentInset = new UIEdgeInsets(0, (nfloat)offsetX, 0, 0);
}
This code should be called anytime the layout of the screen changes - such as during rotation.

How to remove UITableView top inset when embedded in ContainerView?

I am currently working on an iPhone App. I now have a problem with the top spacing inset of a UITableView. See this screenshot:
There should be no space between the table view cells and the buttons.
I do not know how to fix this. The UITableView is embedded in a ContainerView like this:
I think I got the container view constraints right. Top Space to Chapter Button is set to 0.
I tried to change some settings of the table view controller in storyboard. For example the Adjust Scroll View Insets. However it does not change anything when I disable that.
I also tried to set the TableView insets directly in the code in viewDidLoad():
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
However this also did not fix it.
Can anyone help? I have no idea where to look.
This can be solved by disabling auto adjustment of scroll view insets. However this setting has to be applied to the ViewController which contains the ContainerView (with the UITableView inside of it). It does not work when applied to the UITableView itself.
This can be done via Storyboard:
Or via code in viewDidLoad(): self.automaticallyAdjustsScrollViewInsets = false
Since iOS 15 there's a new parameter which can introduce a top gap when using a section header. This can be removed with the following:
if #available(iOS 15, *) {
tableView.sectionHeaderTopPadding = 0
}
Try this Hope this work.
hide View which contains the ContainerView.
self.automaticallyAdjustsScrollViewInsets = NO

UICollectionVIew: How can I remove the space on top first cell's row?

I have this arrangement in Interface Builder, all properties are set to zero.
However, when I run it on both device and simulator it appears like this
Where is the space above the cells come from?
So I try to set these properties for UICollectionViewFlowLayout in code like this
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.headerReferenceSize = CGSizeZero;
layout.footerReferenceSize = CGSizeZero;
layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 0;
layout.itemSize = CGSizeMake(103, 119);
self.calendarView.collectionViewLayout = layout;
but I have no luck.
How can I get rid of that space?
UICollectionView is descendant of UIScrollView class which has contentInset property, setting -20 top inset fixes the problem
[self.calendarView setContentInset:UIEdgeInsetsMake(-20, 0, 0, 0)];
However, the problem comes from UIViewController's automaticallyAdjustsScrollViewInsets property.
By documentation:
Default value is YES, which allows the view controller to adjust its scroll view insets in response to the screen areas consumed by the status bar, navigation bar, and toolbar or tab bar. Set to NO if you want to manage scroll view inset adjustments yourself.
That's why we get adjusted content insets for status bar. It's better to disable automatically adjusting than manually set value which doesn't match in result picture.
[self setAutomaticallyAdjustsScrollViewInsets:NO];
Another way is to select your ViewController and uncheck the checkbox Adjust Scroll View Insets in your interface builder:
It is essentially the same as the following line of code. But you got to see your changes right away in the interface builder.
automaticallyAdjustsScrollViewInsets = false
iOS 11 deprecated the use of automaticallyAdjustsScrollViewInsets, so the use of collectionView.contentInsetAdjustmentBehavior = .never is advised.
Here is the answer in swift with a few adjustments:
I have a collection view that takes up a small portion of the view. I used:
self.automaticallyAdjustsScrollViewInsets = false
to remove the top spacing that was messing up my layout. This piece of code didn't work for me:
self.paperCollectionView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
And neither did this one:
self.paperCollectionView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0)
But that might be because I'm not using a UICollectionViewController, I'm just using a UICollectionView.
Here's a bigger portion of the code to give more context:
You can also go with
[self.calendarView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[self setAutomaticallyAdjustsScrollViewInsets:NO];
There is by default collection view header scrolling space added on the collection view and you do not need to add -20 from top because it may reflect on device issue
You can do this in Interface Builder by going to the Scroll View section and changing the Content insets dropdown to "Never".
Swift 3:
self.automaticallyAdjustsScrollViewInsets = false
This answer is weird, but it works if you are working in Interface Builder and have a Collection View embedded in a View Controller that is under the control of a Tab Bar Controller that is the root view controller of a Navigation Controller.
Add a Toolbar to the View Controller that has the Collection View
Move the Toolbar in the hierarchy such that it is above the Collection View
If the Toolbar is above the Collection View, there will be no space from the top of the prototype Collection View Cell to the Collection View. If there is no Toolbar or the Toolbar is below the Collection View, then there will be space between the top of the Collection View and the Collection View Cell. This is true both in the Storyboard preview and while running the app. The same type of thing occurs for Table Views.
This was most recently tested with Xcode Version 8.3.3

UITableView is starting with an offset in iOS 7

I have dragged a plain jane UITableView onto a UIViewController in iOS 7.
Now there is an vertical offset of space before the first cell starts. How do I get rid of it? I want the first line to be much closer to the top edge of where the UITableView actually starts. I did not ask for the large offset did I?
Any ideas?
The new iOS 7 implementation of UIViewController has a new set of options that allows the developer to choose if the system will automatically add insets for UIScrollView, UITableView and derivations.
To disable this behaviour uncheck these boxes for all your wanted UIViewControllers in InterfaceBuilder, on UIViewController selected object inspector:
For more details:
Submit your iOS 7 apps today.
iOS 7 UI Transition Guide > Appearance and Behavior
By default table view controllers will pad the content down under the nav bar so you could scroll the content under it and see it, in a blurred state, underneath the navbar/toolbar.
Looks like you're positioning it at 44 (maybe 64)px to move it out from under the nav bar, but it already compensates for this so you get a big gap.
Go to the storyboard/xib in IB and untick the show content under nav bar stuff.
From iOS7 transition guide:
If you don’t want a scroll view’s content insets to be automatically
adjusted, set automaticallyAdjustsScrollViewInsets to NO. (The default
value of automaticallyAdjustsScrollViewInsets is YES.)
self.automaticallyAdjustsScrollViewInsets = NO;
i had a similar problem, after dismissing a viewController, the contentOffset from my tableView was changed to (0, -64).
my solution was a little weird, i tried all the other answers but had no success, the only thing that fixed my problem was to switch the tableView position in the controls tree of the .xib
it was the first control in the parent View like this:
I moved the tableView right after the ImageView and it worked:
it seems that putting the table view in the first position was causing the trouble, and moving the table view to another position fixed the problem.
P.D. I'm not using autoLayout neither storyboards
hope this can help someone!
it resolve my similar problem:
if ([[UIDevice currentDevice].systemVersion floatValue] >= 7){
tableView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0);
}
Try using this
tableView.separatorInset = UIEdgeInsetsZero;
Obviously, if you're supporting anything less than iOS7 you will need to ensure that the object responds to this selector before calling it.
Seriously, changing contentOffset is not the solution. You're just patching a problem and not fixing the cause. I've been facing the same problem and it turns out that grouped tableViews have a padding on the top. In my case setting the type to plain has done the trick.
Hopefully it saves someone a few minutes.
Z.
With iOS 9, none of the other answers from this page worked for me (i.e. unchecking boxes in Storyboard, setting automaticallyAdjustsScrollViewInsets to NO).
My workaround I am really dissatisfied about was this:
- (void)viewDidAppear:(BOOL)animated {
self.tableView.contentOffset = CGPointMake(0.0, 0.0);
self.tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0);
}
The same lines in viewWillAppear or viewDidLoad were ineffective.
Sometimes, I get a 64 height gap at the top of my Table View when the UIViewController is embedded inside a Navigation Controller.
In the past, I would just re-create everything, hoping that the constraints turn out correct after a clean slate.
TIL: If you don't want to make a vertical constraint to the Top Layout Guide, you can hold down the Option key to access the Container Margin.
Then make sure the Top Space to Superview constant is set to 0. This worked for me at least.
THis works for me:
- (void)loadView
{
[super loadView];
[self setAutomaticallyAdjustsScrollViewInsets:YES];
self.edgesForExtendedLayout = UIRectEdgeNone;
self.view.frame = CGRectZero;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
If you add an empty UIView before UITableView (or any view is scrollable such as ScrollView and TextView), you can have a luck.
I had a UITableViewController embedded in a container view. To get rid of the unwanted 64 points of vertical space, I needed to uncheck the 'Adjust Scroll View Insets' in Interface Builder and set the UITableView's contentInset in my UITableViewController's viewWillAppear as below.
The size of the vertical space appears to match the navigation bar's frame height and y offset. The problem only occurred on iOS 7.
- (void)viewWillAppear:(BOOL)animated;
{
[super viewWillAppear:animated];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
const CGRect navBarFrame = self.navigationController.navigationBar.frame;
const CGFloat blankVerticalSpace = navBarFrame.origin.y + navBarFrame.size.height;
self.tableView.contentInset = UIEdgeInsetsMake(-blankVerticalSpace, 0, 0, 0);
}
}
In Xamarin iOS, I had this issue occuring on a backgrounded UITableViewController just after the foreground modal dialog was being dismissed. In the process of moving into the foreground, the UITableViewController had insets set (somewhere by iOS):
This class solved it
public class UITableViewControllerWithBugFix : UITableViewController {
public UITableViewControllerWithBugFix(UITableViewStyle withStyle) : base(withStyle) {
}
public override void ViewWillLayoutSubviews() {
if (TableView.ContentInset.Top != 0.0f)
TableView.ContentInset = UIEdgeInsets.Zero;
if (TableView.ScrollIndicatorInsets.Top != 0.0f)
TableView.ScrollIndicatorInsets = UIEdgeInsets.Zero;
base.ViewWillLayoutSubviews();
}
}
From time to time I get back to this awful situation, and I notice that it's still quite unknown. So, for future memory...
Lately, I'm fixing with this workaround.
Add a subview at the top of the UITableView, with zero pixel height. Works with Autolayout or without.
If I feel confident :-) I remove this fake view, fix the constraints on the top, and magically it works.
Don't ask me why, I still think it's a bug deep in UIKit.
If you go to storyboard, you can change the offset by selecting the table and under the Table View section in the Attributes inspector you just change the Separator Insets on the left to 0.
I think the real solution is to set up your top and bottom constraints on the tableview be equal to the topMargin and bottomMargin. Not the top layout guide and bottom layout guide. This allows you to keep automaticallyAdjustsScrollViewInsets to be true.
Swift 3 solution:
class PaddingLessTableView : UITableView
{
override func headerView(forSection section: Int) -> UITableViewHeaderFooterView?
{
return nil
}
override func footerView(forSection section: Int) -> UITableViewHeaderFooterView?
{
return nil
}
}
If you embedded your TableViewController in a NavigationController or a ContainerView, You have to constraint to margins instead of top Layout guide in Storyboard. Check constraint to margins when you are doing the constraints No other way worked for me. I couldn't comment so I'm just reiterating on Robert Chens answer.
I tried several of the answers. Changing the settings in storyboard caused ripple problems with an overlay menu that pops in from the left.
I only have a blank UIViewController in storyboard, otherwise everything is programmatically generated.
I have same problem with a UITableView inside a UIView inside a UIViewController. Namely, the section headers start too far down when the UIViewController is embedded in a Navigation Controller. W/o the navigation controller everything works fine.
To fix the problem I created a UILabel and with constraints placed the UILabel bottom constraint = the top constraint of the UIView (so it does not show on the screen. Now with that additional control (the new Label) the TableView behaves properly.
inputsContainerView.addSubview(titleLabel)
inputsContainerView.addSubview(tableView)
// inputsContainerView
///////////////////////////////////////
inputsContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
inputsContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
inputsContainerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
inputsContainerView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.7).isActive = true
// tableView
///////////////////////////////////////
tableView.centerXAnchor.constraint(equalTo: inputsContainerView.centerXAnchor).isActive = true
tableView.topAnchor.constraint(equalTo: inputsContainerView.topAnchor).isActive = true
tableView.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
tableView.heightAnchor.constraint(equalTo: inputsContainerView.heightAnchor).isActive = true
// titleLabel - inserted to stop bad section header behavior
///////////////////////////////////////
titleLabel.centerXAnchor.constraint(equalTo: inputsContainerView.centerXAnchor).isActive = true
titleLabel.bottomAnchor.constraint(equalTo: inputsContainerView.topAnchor).isActive = true
titleLabel.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
titleLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true
I had a same problem in iOS 11 and xib, UITableviewController and I solved it as below
[self.tableView setContentInset:UIEdgeInsetsMake(-44,0,0,0)];
If none of the above answers work, try changing the table view style to plain from grouped

How to get a title to scroll above an iOS text view

I want to have a text title scroll above a text view, but can't find information on how to do it. I've been looking for days, but can't even figure out how to look for the info. I want the function to work like the Apple Notes app where the date text is positioned above the text entry location and scrolls off the screen with the text but is not editable.
I've tried placing labels above UITextView, but the label does not scroll with the textView. I have a sample Xcode project I'm work with, but not sure if it can be uploaded for others to see what I'm doing. I almost had success with the project, but the labels only scroll with the text in the landscape view, not the portrait view for some reason.
I've read Apple developer docs on TextViews and several other sources without finding any discussion on how to do this or examples to follow.
Can anyone point me in the right direction?
I'm sure there must be a better way to do this, but this is the only approach I've found to work after more than a week of trying to find a solution. If I can figure out how to upload the entire Xcode example project I will do that.
This is the explanation of the approach I found to work under iOS 6.1 and Xcode 4.5. I have only tired this on the iPhone 6.1 simulator.
After creating a full screen text view and placing a label at the top of the text view,
To get the label to scroll off screen with the editable text view you need to:
turn off autolayout in interface builder (uncheck Use Autolayout). (there appears to be a problem with autoLayout and scrollViews in iOS 6.x)
turn off the text view scrolling in interface builder (uncheck Scrolling Enabled)
set the text view content insets height (Top) to the label height
embed the text view and label in a scroll view.
set properties for the scroll view and text view to be able to access their properties
in viewDidAppear:animated:
a. set the scroll view content size height to 20 plus the greater of the screen view height or the text view content height plus the label height
b. set the text view delegate to self
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
float screenHeight = self.view.bounds.size.height;
// set the scroll view content height to 20 plus the greater of the view height or the text view content size height plus the label height
screenHeight = MAX(screenHeight, self.textView.contentSize.height + 20);
self.scrollView.contentSize = CGSizeMake(self.view.bounds.size.width, 20 + screenHeight);
// set the text view delegate
self.textView.delegate = self;
}
set the text view height dynamically in textView delegate method textViewDidChange:
a. if the text view content height is greater than the view bounds height less the label height:
1. set the text view frame to the view bounds width and the text view content height plus the lable height
2. set the scroll view content height to the view bounds width and the text view bounds height plus the label height
// dynamically set the text view content size height
-(void) textViewDidChange:(UITextView *)textView {
if (self.textView.contentSize.height > self.view.bounds.size.height - 20) {
self.textView.frame = CGRectMake(0.0, 0.0, self.view.bounds.size.width, self.textView.contentSize.height + 20);
self.scrollView.contentSize = CGSizeMake(self.view.bounds.size.width, self.textView.bounds.size.height + 20);
}
}
set the struts and springs in interface builder
1. set the scroll view and text view struts for left, right and bottom
2. set the scroll view and text view springs for width and height
3. set the label struts for left, right and top
4. set the label spring for width
The same settings need to be made every time the view changes orientations.
There might be a way to do this by setting constraints in code under autolayout, but I barely understand constraints, much less setting them successfully in code.
Hope this helps someone else.
What you are looking for is called UIScrollView. Take a look at the Apple documentation here.
A good tutorial on UIScrollView can be found on the Ray Wenderlich site.

Resources