How to remove UITableViewCell left space? - uitableview

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.

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.

UICollectionViewCell contentView padding

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

UITableView in UITableViewControllers row-dividers off?

I've got my custom UITableViewCell working now, with 'dynamic' height using Auto Layouts.
However, these row-dividers are kind of off.
It's a UITableViewController. The width of the image is the full width of the iPhone in the simulator.
Anyone have a clue? It's kind of a UITableViewController right of the shelf, not much code in it, mostly code for datasource/delegation.
To clearify I want the separators, but I want them equally indented on both sides. The default indention is fine, which is on the left side, but not the right side.
As Fogmeister mentioned, you could remove the separators entirely and just add a separator view on your custom table cells or you could extend the separators by setting the
cell.separatorInset = UIEdgeInsetsZero
cell.layoutMargins = UIEdgeInsetsZero
tableView.separatorInset = UIEdgeInsetsZero
tableView.layoutMargins = UIEdgeInsetsZero
note that this is only available for iOS 8 onwards.
These are called separators.
You can turned them off in Interface Builder as a property on the tableView.
Select the tableview and select the "None" property for the separator.
The default for the UITableViewCell separators is to be indented. However, by digging into your UITableViewCell's subviews, you can move and size the separator by altering its frame.
In your custom UITableViewCell class, override the layoutSubviews() method so you can grab the separator object as the cell's subviews are being laid out by iterating through your cell's subviews and check for a subview of the UITableViewCellSeparator type. If you want to make the separator span the entire cell's width, for example, change its frame's origin.x to 0 and make the separator the full width of the cell's contentView.
override func layoutSubviews() {
super.layoutSubviews()
for subview in self.subviews {
if subview.dynamicType == NSClassFromString("_UITableViewCellSeparatorView") {
var newFrame = subview.frame
newFrame.origin.x = 0
newFrame.size.width = self.contentView.frame.width
separator.frame = newFrame
}
}
}

Why is UIScrollView leaving space on top and does not scroll to the bottom

I am new to objective-C programming.
I am using UIScrollView with some labels, image and text view on it.
I have turned off Autolayout and already tried with "Adjust scroll View Insets" on (situation described in title) and off (doesn't scroll).
This is what I insert into viewDidLoad:
[scroller setScrollEnabled:YES];
[scroller setContentSize:CGSizeMake(320, 687)];
But I must be missing something very simple.
1... Why is UIScrollView leaving space on top
With Storyboard- Goto view controller > Attribute Inspector > Uncheck Adjust Scroll View Insets property
With Code- For extra space set viewController property automaticallyAdjustsScrollViewInsets to NO, by default it is YES.
self.automaticallyAdjustsScrollViewInsets = false;
scroller.contentInset = UIEdgeInsetsZero;
scroller.scrollIndicatorInsets = UIEdgeInsetsZero;
scroller.contentOffset = CGPointMake(0.0, 0.0);
2... does not scroll to the bottom
To make it scroll try with large number in contentSize like CGSizeMake(320, 1687). If it works that means you are not setting the contentSize large enough to have all its content.
Just select your view controller and set shown option to false (uncheck)
iOS 11
In my case only changing this UIScrollView Content Insets property in IB from Automatic to Never helped.
iOS 11 && 12
if #available(iOS 11.0, *) {
scrollView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
Swift 3.0
self.automaticallyAdjustsScrollViewInsets = false
scrollView.contentInset = UIEdgeInsets.zero
scrollView.scrollIndicatorInsets = UIEdgeInsets.zero;
Actually, the margin has nothing to do with ScrollViewInsets or contentOffset. It's just a conflict between SuperView.Top and SafeArea.Top pinning, happens when you pin the UIScrollView to top, bottom, left and right.
This is the right way to cover the top margin.
1) Pin all the four sides.
2) Select the top constraint > Change Second Item to Superview.Top
3) Then the last step is to change the Constant to 0 (Zero).
You might want to check this too:
https://github.com/29satnam/MoveTextFieldWhenKeyboardAppearsSwift
I did below, my problem solved
changing UIScrollView Content Insets property in from Automatic to Never and Adding below code in viewDidLoad()
scroller.contentInset = UIEdgeInsetsZero;
scroller.scrollIndicatorInsets = UIEdgeInsetsZero;
scroller.contentOffset = CGPointMake(0.0, 0.0);`
On iPhoneX this will also occur due to some non-sense safe area stuff that auto-layout tried to account for. Fix (for iPhoneX) with this:
if (#available(iOS 11.0, *)) {
scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
In your view .m file, use this code to fix this problem
-(void)layoutSubviews{
// To fix iOS8 bug of scrollView autolayout
if([[[[[UIDevice currentDevice]systemVersion] componentsSeparatedByString:#"."]objectAtIndex:0] integerValue] == 8){
[self.tableView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
}
}
Swift 3.0
self.automaticallyAdjustsScrollViewInsets = false
scrollView.contentInset = UIEdgeInsets.zero
scrollView.scrollIndicatorInsets = UIEdgeInsets.zero;
scrollView.contentOffset = CGPoint(x: 0.0, y: 0.0);
Swift 3 (Auto Layout)
Change "Layout Margins" to explicit
Set margins to your needs
This works for me,
_scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
_scrollView.contentOffset = CGPointMake(0.0, 0.0);
[_scrollView setContentSize:CGSizeMake(self.view.frame.size.width, self.view.frame.size.height)];
After user interface orientation going to landscape, my UIScrollView shown its UIScrollIndicator being misplaced. To fix this, you need to add the following code.
As per iOS 13, yet supporting iOS 12 and earlier:
// Fixes the scroll indicator misplacement when rotated in landscape
if #available(iOS 13.0, *) {
v.automaticallyAdjustsScrollIndicatorInsets = false
} else {
// Fallback on earlier versions
v.contentInsetAdjustmentBehavior = .never
}
v.contentInset = .zero
v.scrollIndicatorInsets = .zero

UITableView: the proper way to display a separator for the last cell

The question is what's the right-most way to display a separator in the last cell in a table/section.
Basically this is what I am after.
This is from the native music app, which makes me think that it should be possible to achieve just by means of UITableView, they would not be using some private API for cell separators, right?
I know you can get away without using actual separators, but adding one pixel line in the bottom of the cell. But I'm not a fan of this approach because
When a cell is selected/highlighted its separator and the separator of the previous cell are automatically hidden (see the second screenshot with "You've got to be crazy" selected). And this is
something I want UITableView to handle instead of doing myself if I use one-pixel line
(which is especially handy when cell separators do not extend all
the way to the edge of the table view, separators and selected cell background do not look nice together).
I would like to keep my cells as flat as possible for scrolling performance.
Also there is something in UITableView reference that makes me think that there is an easy way to get what I want:
In iOS 7 and later, cell separators do not extend all the way to the
edge of the table view. This property sets the default inset for all
cells in the table, much like rowHeight sets the default height for
cells. It is also used for managing the “extra” separators drawn at
the bottom of plain style tables.
Does somebody know how exactly to use these “extra” separators drawn at the bottom of plain style tables? Because this is exactly what I need.
I thought assigning separatorInsetto the UITableView, not UITableViewCell would do the trick, but it does not, the last cell is still missing its separator.
Right now I only see one option: to have a custom section footer to mimic the separator for the last cell. And this is not good, especially if you want to have an actual section footer using tableView:titleForFooterInSection: method.
This worked flawlessly for me to add a separator to the last cell. have fun!
self.tableView.tableFooterView = [[UIView alloc] init];
When you add headerView or footerView to your TableView, last separator line will disappear.
Example below will let you make workaround for showing separator on the last cell. The only thing you have to implement more is to make this separator disappearing after selecting cell, so behavior is the same like in the rest of cells.
For Swift 4.0
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let result = UIView()
// recreate insets from existing ones in the table view
let insets = tableView.separatorInset
let width = tableView.bounds.width - insets.left - insets.right
let sepFrame = CGRect(x: insets.left, y: -0.5, width: width, height: 0.5)
// create layer with separator, setting color
let sep = CALayer()
sep.frame = sepFrame
sep.backgroundColor = tableView.separatorColor?.cgColor
result.layer.addSublayer(sep)
return result
}
I just found something that works for me. In a few words: give your UITableView a tableFooterView and set its frame's height to 0. This makes an actual separator show, with the right insets.
In more details: if you are using the storyboard, drag a UIView to the bottom of your Table View (in the tree view on the left) so it shows just below Table View Cell, at the same hierarchical level. This creates a tableFooterView. Of course this can be done programmatically as well.
Then, in your UITableViewController's implementation:
UIView *footerView = self.tableView.tableFooterView;
CGRect footerFrame = footerView.frame;
footerFrame.size.height = 0;
[footerView setFrame:footerFrame];
Let me know if that works for you! It might also work for the first separator if you use a tableHeaderView instead, I haven't tried it though.
So here's a super simple solution in Swift 4 which works:
Inside override func viewDidLoad(){}, I simply implemented this line of code:
self.tableView.tableFooterView = UIView(frame: .zero)
Hence it ensures that only the last cell gets the separator inset.
This worked perfectly for me, hope it does for you too!
this will do exactly what you want .. even though the line will take the entire width of the cell:
in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.tableView.separatorColor = [UIColor redColor];
self.tableView.separatorInset = UIEdgeInsetsZero;
You can do something like this if you are not using sections:
- (void)viewDidLoad
{
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(insetLeftSide, 0, width - insetRightSide, 1)];
}
If you are using sections implement the footer in each section as a one point View in the methods
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
}
This will allow you to have a separator for your last cell which in fact is not a separator is a footer that you can play with it and make it look like a separator
Swift 3
I found this old issue, so I tried the same in Swift:
tableView.tableFooterView = UIView()
tableView.tableFooterView?.height = 0 // Maybe not necessary
But it lead to another problem (in my case). So I solved it differently. I added an extra cell at the end of this section, empty and with height equal to zero:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return previousNumberOfRows + 1
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return indexPath.row == previousNumberOfRows ? 0 : previousCellHeight
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == items.count {
return UITableViewCell()
} else {
previousCellInitialization()
}
This is a less concise solution, but works in more cases, if you have multiple sections, existing footer view(s)...
I had a similar issue and found a workaround. Apple hides the last uitableviewcell separator and then displays it if you select the cell or if you call select and deselect on that cell.
So I taught the best is in - (void)layoutSubviews. The separator view is called _separatorView and it's a private property. Using the cell's selected / highlighted states you can come up with something like this:
- (void)layoutSubviews
{
// Call super so the OS can do it's layout first
[super layoutSubviews];
// Get the separator view
UIView *separatorView = [self valueForKey:#"_separatorView"];
// Make the custom inset
CGRect newFrame = CGRectMake(0.0, 0.0, self.bounds.size.width, separatorView.frame.size.height);
newFrame = CGRectInset(newFrame, 15.0, 0.0);
[separatorView setFrame:newFrame];
// Show or hide the bar based on cell state
if (!self.selected) {
separatorView.hidden = NO;
}
if (self.isHighlighted) {
separatorView.hidden = YES;
}
}
Something like this.
In iOS 8, if you have a plain style UITableView, and add a footer, the last separator is gone. However, you can easily recreate it by adding a custom separator view to the footer.
This example exactly mimics Today Widget separator style
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
//create footer view
let result = UIView()
result.frame.size.height = tableView.rowHeight
//recreate last cell separator, which gets hidden by footer
let sepFrame = CGRectMake(15, -0.5, tableView.frame.width, 0.5);
let vibrancyEffectView = UIVisualEffectView.init(effect: UIVibrancyEffect.notificationCenterVibrancyEffect())
vibrancyEffectView.frame = sepFrame
vibrancyEffectView.contentView.backgroundColor = tableView.separatorColor
result.addSubview(vibrancyEffectView)
return result
}
If you add an empty footer then the tableview will remove all the remaining line separators (for non-existent cells) but will still include the separator for the last cell:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
return [UIView new];
}
I used the table view style "grouped" to add this line:
And furthermore it avoids sticking the last separator line to stick on the screen when scrolling out!
Works in iOS 7.x and 8.x (put it in cellForRowAtIndexPath):
(PS substitute "max elements of your datasource" with your array datasource count)
if (row == <max elements of your datasource>-1) {
UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.contentView.frame.size.height-1, self.view.frame.size.width, 1)];/// change size as you need.
separatorLineView.tag = 666;
separatorLineView.backgroundColor = [UIColor colorWithRed: 204.0/255.0 green: 204.0/255.0 blue: 204.0/255.0 alpha:1.0];
UIView *separator = [cell.contentView viewWithTag:666];
// case of orientation changed..
if (separator.frame.size.width != cell.contentView.frame.size.width) {
[[cell.contentView viewWithTag:666] removeFromSuperview];
separator = nil;
}
if (separator==nil) [cell.contentView addSubview:separatorLineView];
}
This is definitely help. Working.
but set separator "none" from attribute inspector.
Write following code in cellForRowAtIndexPath method
if(indexPath.row==arrData.count-1){
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,
cell.contentView.frame.size.height - 1.0,
cell.contentView.frame.size.width, 1)];
lineView.backgroundColor = [UIColor blackColor];
[cell.contentView addSubview:lineView];
}
The code below worked for me:
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 0.35)];
footerView.backgroundColor = [UIColor whiteColor];
CGRect frame = footerView.frame;
frame.origin.x = 15;
frame.size.width = frame.size.width - 15;
UIView *blackView = [[UIView alloc] initWithFrame:frame];
[blackView setBackgroundColor:[UIColor blackColor]];
blackView.alpha = 0.25;
[footerView addSubview:blackView];
tableView.tableFooterView = footerView;
Hope it works for you too.

Resources