Disable UITableView horizontal scroll - ios

I created a UITableView with a small frame, like (0,0,50,50). I want to disable the horizontal scrolling but keep the vertical scrolling.
I set self.table.bounces = NO, but the tableview can't be vertically scrolled, either. As a result, the animation is not so perfect.
So anyone has tips?
thanks!

Check if the content inset property of the table view is nonzero. If so reset it to zero.

change the content size of the tableView, make sure the width of the content size is not greater than the frame size
self.tableView.contentSize = CGSizeMake(self.tableView.frame.size.width, self.tableView.contentSize.height);

You can set AlwaysBounceHorizontal property of UITableView to false as follows:
Swift:
self.tableView.alwaysBounceHorizontal = false
Objective-C:
[self.tableView setAlwaysBounceHorizontal:NO];

self.tblViewProfile.alwaysBounceHorizontal = false // using coding
Or by storyboard/xib
Un tick horizontal bounce option in storyboard or xib

If you've applied tableView.contentInsetAdjustmentBehavior = , try selecting the value .scrollableAxes instead of .automatic or .always

If you created the table view in the interface builder then there is an option check the scroll vertically and uncheck the horizontal scroll.
If you didn't then you should try create it in the interface builder and assign it to your IBOutlet
Hope it helps !

Related

UITableViewCell contentView inset on iPhone X

Any UITableViewCell created on iPhone X has a 44 points inset for content view. This means width of contentView of UITableViewCell is by default 44pts less than the cell width. I do not need to have this behavior. How do I get contentView width same as cell width (or like it is there on other iPhone models)?
Update: I solved the problem by setting tableView.insetsContentViewsToSafeArea = NO. Now working on same issue for other elements such as UINavigationBar items. Unable to find an equivalent was for UIBarButtonItem for navigation bar. Any insight is appreciated.
Maybe you could use additionalSafeAreaInsets on your view controller, it's there to reduce the actual usable space but with negative Insets it should do the opposite.
https://developer.apple.com/documentation/uikit/uiviewcontroller/2902284-additionalsafeareainsets
In your table view set insetsContentViewsToSafeArea to false.
tableview.insetsContentViewsToSafeArea = false

Collection View overlaps above when scrolling vertically

So I have collectionView but above that a UIView as well. When I scroll my collectionView vertically and go up, it scrolls and overlaps the UIView.
What could be the solution to make the UIView come on top of collectionView?
What did work was turning off clips to bounds in the collection View from storyboard.
Set the property "Clip to Bounds" to true. It can be done programatically or in the auto layout.
Programatically: colelctionView.clipToBounds = true
Auto Layout:
Your constraints should be like,
View - top,leading,trailing and fixed height
collection view - top,leading,trailing,bottom
and after that setup, you got issue then once try to set below in viewDidload,
self.automaticallyAdjustsScrollViewInsets = false
Try keeping View Below the Collection View in the View Hierarchy.
This looks sneaky, what let us know the effect.
Just play with the Section Inset

Hide subviews when superview height change while using auto layout constraints

I have one UIView, it's having few subview controls like label's and textbox. it is also having one switch control.
I want to hide/display (like collapsible) the portion on the superview based on the switch change. However when I try to do it with constant of superview, it just changes the superview height but all subview does not getting hides.
could you please help me to figure out this.
Thanks,
Set UIView's property clipsToBounds = true.
This prevents the subviews from being drawn when their frame lies outside the bounds of the superview
e.g.
superView.clipsToBounds = true
Note that for layers you can use:
superView.layer.masksToBounds = true
There are a number of methods of UIView that allow you to modify the view hierarchy.
bringSubviewToFront:
sendSubviewToBack:
insertSubview:atIndex:
insertSubview:aboveSubview:
insertSubview:belowSubview:
exchangeSubviewAtIndex:withSubviewAtIndex:
You can use any of this as per your requirement.

runtime expansion of uitableview footerview using autolayout

I have a UIView that is a footerview of a uitableview. At run time, the user enters text into a uitextview within the footerview that should adjust to the size of the text content with a height constraint in autolayout.
All other objects in the view (labels, imageviews) have appropriate constraints to accommodate the expansion of the textview.
HOWEVER the height of the overall footerview will not change size, and it is impossible to use autolayout on the tableview footerview height.
Does anyone have a solution? Thanks
Haven't found an actual, elegant, solution yet, but I've postponed fixing this by using a workaround:
Setting the frame of the view used as a footer to be as large as you might possible need. In my case this meant giving it about 60px of spare vertical room. Since it's the footer and there's nothing below it to reposition the user won't be affected by the workaround.
The contents of the footer view are pinned to the top and have enough space to expand when needed.
For the record: my view is loaded from a nib file.
Although in theory the size one gives to the top level view in interface builder is just for design-time and the runtime size should be calculated based on constraints and the resulting intrinsic size, for this specific case I found the height stays the same as it was in IB.
We can change the height of the footer view run time by the following code:
func methodToChangeTableViewFooterHeight()
{
var footerView:UIView = self._tableView.tableFooterView! as UIView
var frame:CGRect = footerView.frame
frame.size.height = self.heightCollectionCS.constant + 10
footerView.frame = frame
self._tableView.tableFooterView! = footerView
}
Here , self.heightCollectionCS.constant is the height constraint for our Collection View.
We can use text content height on that place.
You may try to set again the footer view each time you footer height changes, to inform the table it should change the footer height. Or use inset. From within the footer view:
SetNeedsLayout()
LayoutIfNeeded()
ownertable.TableFooterView = this
Sorry about that, misread that question long ago. You can access the footer directly through the tableview's property tableFooterView.
What you could do is create your default footer in a xib or in your viewDidLoad:. Once you need to increase the size of the footer, you can pull out the UIView from that property and edit its frame if necessary to make it larger.
So make sure the tableFooterView gets assigned a UIView because it is nil by default. To just make the height taller, you can use self.tableView.tableFooterView.frame = CGRectMake(whatever rect you need);

UIScrollView not scrolling

I have a UIScrollView which contains many UIImageViews, UILabels, etc... the labels are much longer that the UIScrollView, but when I run the app, I cannot click and scroll down...
Why might this be?
Thanks
It's always good to show a complete working code snippet:
// in viewDidLoad (if using Autolayout check note below):
UIScrollView *myScrollView;
UIView *contentView;
// scrollview won't scroll unless content size explicitly set
[myScrollView addSubview:contentView];//if the contentView is not already inside your scrollview in your xib/StoryBoard doc
myScrollView.contentSize = contentView.frame.size; //sets ScrollView content size
Swift 4.0
let myScrollView
let contentView
// scrollview won't scroll unless content size explicitly set
myScrollView.addSubview(contentView)//if the contentView is not already inside your scrollview in your xib/StoryBoard doc
myScrollView.contentSize = contentView.frame.size //sets ScrollView content size
I have not found a way to set contentSize in IB (as of Xcode 5.0).
Note:
If you are using Autolayout the best place to put this code is inside the -(void)viewDidLayoutSubviews method .
If you cannot scroll the view even after you set contentSize correctly,
make sure you uncheck "Use AutoLayout" in Interface Builder -> File Inspector.
You need to set the contentSize property of the scroll view in order for it to scroll properly.
If you're using autolayout, you need to set contentSize in viewDidLayoutSubviews in order for it to be applied after the autolayout completes.
The code could look like this:
-(void)viewDidLayoutSubviews
{
// The scrollview needs to know the content size for it to work correctly
self.scrollView.contentSize = CGSizeMake(
self.scrollContent.frame.size.width,
self.scrollContent.frame.size.height + 300
);
}
The answer above is correct - to make scrolling happen, it's necessary to set the content size.
If you're using interface builder a neat way to do this is with user defined runtime attributes. Eg:
Try to resize the content size to huge numbers. I couldn't understand why my scroll view doesn't scroll even when its content size seems to be bigger than control size. I discovered that if the content size is smaller than needed, it doesn't work also.
self.scrollView.contentSize = CGSizeMake(2000, 2000);
Instead of 2000 you can put your own big numbers. And if it works, it means that your content size is not big enough when you resize.
The delegate is not necessary for scroll view to work.
Make sure you have the contentSize property of the scroll view set to the correct size (ie, one large enough to encompass all your content.)
Uncheck 'Use Autolayout' did the trick for me.
Environment:
xCode 5.0.2
Storyboards
ios7
In my case I had to set delaysContentTouches to true because the objects inside the scrollView were all capturing the touch events and handling themselves rather than letting the scrollView itself handle it.
Set contentSize property of UIScrollview in ViewDidLayoutSubviews method. Something like this
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height)
}
if you are getting a message (IOS8 / swift) that viewDidLayoutSubviews does not exist, use the following instead
override func viewDidAppear(animated: Bool)
This fixed it for me
The idea of why scroll view is not scrolling because you set the content size for scrolling less than the size of the scroll view, which is wrong.
You should set the content size bigger than the size of your scroll view to navigate through it while scrolling.
The same idea with zooming, you set the min and max value for zooming which will applied through zooming action.
welcome :)
One small addition, all above are the actual reasons why your scroll view might not be scrolling but sometimes mindlessly this could be the reason specially when scrollview is added through code and not IB, you might have added your subviews to the parent view and not to the scrollview this causes the subview to not scroll
and do keep the content size set and bigger than parent view frame (duhh!!)
I made it working at my first try. With auto layout and everything, no additional code. Then a collection view went banana, crashing at run time, I couldn't find what was wrong, so I deleted and recreated it (I am using Xcode 10 Beta 4. It felt like a bug) and then the scrolling was gone. The Collection view worked again, though!
Many hours later.. this is what fixed it for me. I had the following layout:
UIView
Safe Area
Scroll view
Content view
It's all in the constraints. Safe Area is automatically defined by the system. In the worst case remove all constraints for scroll and content views and do not have IB resetting/creating them for you. Make them manually, it works.
For Scroll view I did: Align Trailing/Top to Safe Area. Equal Width/Height to Safe area.
For Content view I did: Align Trailing/Leading/Top/Bottom to Superview (the scroll view)
basically the concept is to have Content view fitting Scrollview, which is fitting Safe Area.
But as such it didn't work. Content view missed the height. I tried all I could and the only one doing the trick has been a Content view height created control-dragging Content view.. to itself. That defined a fixed height, which value has been computed from the Size of the the view controller (defined as freeform, longer than the real display, to containing all my subviews) and finally it worked again!
Add the UIScrollViewDelegate and adding the following code to the viewDidAppear method fixed it for me.
#interface testScrollViewController () <UIScrollViewDelegate>
-(void)viewDidAppear:(BOOL)animated {
self.scrollView.delegate = self;
self.scrollView.scrollEnabled = YES;
self.scrollView.contentSize = CGSizeMake(375, 800);
}
My issue was resolved by:
setting the contentSize on the scrollView to a large height
BUT also I had to fix top and/or bottom constraints on views within the scrollView, which meant the scroll indicators showed on screen but the content did not scroll
Once I removed top and/or bottom constraints bound to the safe area and/or superview, the views inside the scrollView could scroll again and didn't stay fixed to the top of bottom of the screen!
Hope this stops someone else from hours of pain with this particular issue.
yet another fun case:
scrollview.superview.userInteractionEnabled must be true
I wasted 2+hrs chasing this just to figure out the parent
is UIImageView which, naturally, has userInteractionEnabled == false
Something that wasn't mentioned before!
Make sure your outlet was correctly connected to the scrollView! It should have a filled circle, but even if you have filled circle, scrollView may not been connected - so double check! Hover over the circle and see if the actual scrollview gets highlighted! (This was a case for me)
//Connect below well to the scrollView in the storyBoard
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
Alot of the time the code is correct if you have followed a tutorial but what many beginners do not know is that the scrollView is NOT going to scroll normally through the simulator. It is suppose to scroll only when you press down on the mousepad and simultaneously scroll. Many Experienced XCode/Swift/Obj-C users are so use to doing this and so they do not know how it could possibly be overlooked by beginners. Ciao :-)
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
// Do any additional setup after the view
}
override func viewWillLayoutSubviews(){
super.viewWillLayoutSubviews()
scrollView.contentSize = CGSize(width: 375, height: 800)
}
This code will work perfectly fine as long as you do what I said up above
If none of the other solutions work for you, double check that your scroll view actually is a UIScrollView in Interface Builder.
At some point in the last few days, my UIScrollView spontaneously changed type to a UIView, even though its class said UIScrollView in the inspector. I'm using Xcode 5.1 (5B130a).
You can either create a new scroll view and copy the measurements, settings and constraints from the old view, or you can manually change your view to a UIScrollView in the xib file. I did a compare and found the following differences:
Original:
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wsk-WB-LMH">
...
</scrollView>
After type spontaneously changed:
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" customClass="UIScrollView" id="qRn-TP-cXd">
...
</view>
So I replaced the <view> line with my original <scrollView> line.
I also replaced the view's close tag </view> with </scrollView>.
Be sure to keep the id the same as the current view, in this case: id="qRn-TP-cXd".
I also had to flush the xib from Xcode's cache by deleting the app's derived data:
Xcode->Window->Organizer->Projects, choose your project, on the Derived Data line, click Delete...
Or if using a device:
Xcode->Window->Organizer->Device, choose your device->Applications, choose your app, click (-)
Now clean the project, and remove the app from the simulator/device:
Xcode->Product->Clean
iOS Simulator/device->press and hold the app->click the (X) to remove it
You should then be able to build and run your app and have scrolling functionality again.
P.S. I didn't have to set the scroll view's content size in viewDidLayoutSubviews or turn off auto layout, but YMMV.
If your scrollView is a subview of a containerView of some type, then make sure that your scrollView is within the frame or bounds of the containerView. I had containerView.clipsToBounds = NO which still allowed me see the scrollView, but because scrollView wasn't within the bounds of containerView it wouldn't detect touch events.
For example:
containerView.frame = CGRectMake(0, 0, 200, 200);
scrollView.frame = CGRectMake(0, 200, 200, 200);
[containerView addSubview:scrollView];
scrollView.userInteractionEnabled = YES;
You will be able to see the scrollView but it won't receive user interactions.
adding the following code in viewDidLayoutSubviews worked for me with Autolayout. After trying all the answers:
- (void)viewDidLayoutSubviews
{
self.activationScrollView.contentSize = CGSizeMake(IPHONE_SCREEN_WIDTH, 620);
}
//set the height of content size as required
The straightforward programmatically way
To wrap it up
Create a UIScrollView
private lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
Use a Single Child View to Hold All of Your Content Subviews
private lazy var contentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
Add your views
contentView.addSubview(firstSubView)
contentView.addSubview(lastSubView)
scrollView.addSubview(contentView)
view.addSubview(scrollView)
Usually, you only want your content to scroll in one direction. In most cases to scroll vertically. Therefore set the width of the content view to be the width of the scroll view.
NSLayoutConstraint.activate([
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
Attach four constraints (top, bottom, left, right) from our single content view to the scroll view.
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
Make sure you have constraints attached to all four sides of the content view so that it will expand to the size of your content.
// After Adding your subviews to the contentView make sure you've those two constraints set:
firstSubView.topAnchor.constraint(equalTo: contentView.topAnchor),
.
.
.
lastSubView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
])
Reference: Using UIScrollView with Auto Layout in iOS
After failing with the provided answers in this thread, I stumbled upon this article with the solution.
There are two things not intuitive about setting up the scrollview with autolayout:
The constraints you set up as margin between the contentview and scrollview do not influence the size of the contentview. They really are margins. And to make it work, the contentview should have a fixed size.
The trick to the fixed size is that you can set the width of the contentview equal to that of the scrollview's parent. Just select both views in the tree on the left and add the equal widths constraint.
This is the gist of that article. For a complete explanation, including illustrations, check it out.
I found that with this AutoLayout issue... if I just make the ViewController use UIView instead of UIScrollView for the class... then just add a UIScrollView myself... that it works.
I had the same issue in IB.
After setting the leading, trailing, top and bottom of the scrollView to its superView. I made the following changes to make the containerView scrollable, which worked.
To make the scrollView only scroll on horizontal direction make the constraint with scrollView's centerY = ContainerView's centerY
and to make it vertically scrollable make the scrollView's centerX = ContainerView's centerX
You don’t have to set the content size of the scroll view.
Technical Note TN2154
In case someone made the same mistake like me, I'd like to share my case.
In my case, I mistakenly add a constraint to one of the subviews of scrollview which makes the subview's space to the topLayoutGuide fixed, thus it's location can't be changed, so the scrollview can't be scrolled.

Resources