UICollectionViewCell contentView padding - ios

I want to set padding for contentView from inside of custom UICollectionViewCell so that it is smaller than the cell itself.
I tried doing that by setting anchors for contentView but this view seems to always be equal size of the cell.
This is what I tried.
self.contentView.translatesAutoresizingMaskIntoConstraints = false;
[self.contentView.topAnchor constraintEqualToAnchor:self.topAnchor constant:5].active = true;
[self.contentView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:5].active = true;
[self.contentView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-5].active = true;
[self.contentView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-5].active = true;
For a quick solution I created another view inside contentView that I can anchor the way shown above but I hope for a cleaner solution.

You might want to try setting edge insets for the contentView, but if you take that approach you should be pinning the subviews to the layout margins guides and not anchors directly.
I come from Swift, but I think you'll understand me:
contentView.layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
someSubview.topAnchor.constraintEqualToAnchor(contentView.layoutMarginsGuide.topAnchor).isActive = true

Related

UITableView Cell should not scroll horizontally swift iOS

I have a table view which has card kind of cells as shown in picture.
I have set the content Inset so that I can get the cells with 20px spacing in left,right and top.
tableVw.contentInset = UIEdgeInsets(top: 20, left: 20, bottom: 0, right: 20)
Its displaying as I expected but the problem is, cells can be moved in all direction. But when I move it to right/top, it automatically comes back to original position. But when I move to left it just goes inside and don't scroll back to original position as shown in picture.
I don't want the cells to move at all or I want the cells to come back to centre if its dragged anywhere also. Please help!
Dont provide uiedgeinsets to tableview instead add a view in uitableview cell that cover up the whole cell and add another uiview inside that view and give constraint from top bottom leading trailing equals to 8 or whatever you want then the cell wont move anyways and u tableview cells will look like it has edgeinsets.
you need to set the clipsToBounds property true
tableview.clipsToBounds = true
If you're using AutoLayout, by setting this only should work for you:
In code:
tableView.alwaysBounceVertical = false
or In Interface Builder:
Just find this option and untick "Bounce Vertically" option.
Here's the reference:
If you're not using AutoLayout:
override func viewDidLayoutSubviews() {
// Enable scrolling based on content height
tableView.isScrollEnabled = tableView.contentSize.height > tableView.frame.size.height
}
and also try clipToBounds
tableview.clipsToBounds = true
I achieved what I wanted by below code.
postsTable.contentInset = UIEdgeInsets(top: 20, left: 20, bottom: 0, right: -20)
And in UITableViewCell class :
override var frame: CGRect{
get {
return super.frame
}
set(newFrame){
var frame = newFrame
frame.size.width = kScreenWidth - 40
super.frame = frame
}
}
Now if I drag the cell left or right also its coming back to original position.

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 to remove UITableViewCell left space?

I have searched everywhere but cannot find answer to this question.
In my UITableView's cells, there is empty space on the left side. How do I get rid of it?
I'm using swift-4 IOS-11, xCode- Version 9.0 beta 6
As shown in this picture, I can not remove the left margin.
I tried these but not:
1-> cell.imageView?.contentMode = .scaleToFill
2-> tableView.layoutMargins = UIEdgeInsets.zero
tableView.separatorInset = UIEdgeInsets.zero
3->cell.layoutMargins = UIEdgeInsets.zero
4->self.tableView.contentInset = UIEdgeInsetsMake(0, -15, 0, 0);
Please Help me :/
Create a subclass of UITableViewCell.
Inside it set the method:
- (void)setFrame:(CGRect)frame
{
frame.origin.x = 0;
//More frame stuff if you want
[super setFrame:frame];
}
Then use that subclass for cells in your UITableView.

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)

UICollectionView cell subviews do not resize

In a CollectionView, some cells should have an additional subview or layer. The CollectionView can be told to resize it's cells, thus all content needs to resize appropriately.
Currently, the cell is initialized from a nib containing a cell with imageview; the cell nib is linked to a custom UICollectionViewCell subclass, that only does the init. Autoresize subviews is checked.
The CollectionView is told to resize the cell by a value derived and returned in sizeForItemAtIndexPath:. I have subclassed a FlowLayout but it only specifies ScrollDirection and Insets.
All of that is working fine. Problem: How do I add subview/layer to the cell so it also resizes correctly? I tried adding subviews and layers with translatesAutoresizingMaskIntoConstraints off, but these do not automatically change size at all. Also tried to use code frame/view instead of nib.
The best I got now is a cell.contentView.layer sublayer which I add in cellForItemAtIndexPath:; that is "manually" resized by storing the cell's frame.size from sizeForItemAtIndexPath:, which is not only ugly but also ends up with the sublayer having various sizes for different cells.
Any help appreciated!
I ran into the same issue just now.
When using the UICollectionViewFlowLayoutDelegate method to set the cell size depending on device and device-orientation, the size would be calculated properly but subviews would not resize to fill the newly size cell. The effect was a large blank cell with small subviews that don't fill the cell's bounds / remain the size equal to their current value in the xib file.
I solved this by doing the following in awakeFromNib:
- (void)awakeFromNib
{
[super awakeFromNib];
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.contentView.translatesAutoresizingMaskIntoConstraints = YES;
}
Prior to doing this, the contentView mask was nil.
*override func awakeFromNib() {
super.awakeFromNib()
self.contentView.autoresizingMask.insert(.FlexibleHeight)
self.contentView.autoresizingMask.insert(.FlexibleWidth)
}
This worked for me.. This code goes inside of your subclassed UICollectionViewCell.swift file (where your code involving the custom cell is located)
Swift solution*
As an alternative to enabling AutoResizingMask, for custom UICollectionViewLayouts that have variable height for example where you are setting some constraints manually and need translatesAutoresizingMaskIntoConstraints to remain NO, you can add the following to layoutSubviews in the cell:
self.contentView.frame = self.bounds;
This worked to fix all of my custom collection view layouts that had problens with Xcode 6.
In another project without xibs i subclassed UICollectionViewCell and did this for the same effect:
#import "CVcell.h"
#implementation CVcell
#synthesize cellImage;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGFloat cellSize = self.contentView.bounds.size.width;
cellImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, cellSize, cellSize)];
[cellImage setClipsToBounds:YES];
cellImage.translatesAutoresizingMaskIntoConstraints = NO;
cellImage.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.contentView addSubview:cellImage];
}
return self;
}
#end
I always prefer autolayout when possible.
But Sometimes usings frames and bounds just is a timesaver when a view is determined straightforward by only its superview.
In the case of UICollectionViewCell I set an image to be the cells frame +
self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
But when I had different sizes of cells in the collectionView it messed up things and the image sometimes took the size of a different cell.
So I turned to working with the the cells bounds and - ye that acually worked out fine.
So maybe give that a try?
A simple auto layout solution is to set constraints to the container view.
So if we have an image view with a parent view, we basically want to tell the subview (the image view) to maintain a leading, trailing, bottom, and top space distance of 0 to the container view.
#Alfie Hanssen solution (here) didn't work properly for me, according with this article:
The size of the cell view in the XIB is 50 x 50 points, which is the default size of the collection view cells as set in the flow layout. Even if it’s a bit hard to work with a cell this small in Interface Builder, it’s better to not change the default size. The problem is that Auto Layout considers the manually set size as being fixed and generates a NSAutoresizingMaskLayoutConstraint error when it tries to adjust the cells height automatically
I have inspected the UICollectionViewCell and I found that there is a view between the cell and the contentView, and that view has intrinsic width and height constraints. Instead of the AutoresizingMask I'm just updating as below and seems working for me.
override func layoutSubviews() {
contentView.superview?.frame = bounds
super.layoutSubviews()
}
I'm adding subView and constraint programmatically, the following code works for me:
lazy var imageView: UIImageView = { [unowned self] in
let imageView = UIImageView(frame: self.contentView.frame)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
return imageView
}()
func updateCellWith(image: UIImage) {
contentView.subviews.forEach { $0.removeFromSuperview() }
contentView.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
imageView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 0).isActive = true
imageView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: 0).isActive = true
imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true
self.imageView.autoresizingMask.insert(.flexibleHeight)
self.imageView.autoresizingMask.insert(.flexibleWidth)
imageView.image = image
}
The solution was to turn off AutoConstraints for the cell xib and activate the flexible width/height arrows in the AutoResize for the imageviews.
I had the same problem. Switching between two layouts did not resize the Pictures (UIImage) inside my cells. My Cells where build without a xib. And I used two different cell classes for each CollectionViewCustomLayout.
I fixed this programatically with this:
self.autoresizesSubviews = YES;
in my UICollectionViewCell subclasses.
But this only worked for me by adding the Picture as a cells backgroundpicture like this:
cell.backgroundView[[UIImageView alloc] initWithImage: SumDummyImage ];

Resources