UITableView getting clipped by 1 pixel on the right - ios

I'm using a custom cell which have a background image. But the tableview is getting clipped by 1 pixel on the right. No matter what I tried, the image wont occupy the whole width.
So far I tried the below settings :
Also, this :
tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
What might be the issue?
Test Image :

My UITableView was starting from (-1,0)
After setting a width constraint, the tableview occupied the whole width.
Thanks.

Related

scrolling/resizing UITableView

I'll get right to the point.
I have a UIViewController that has two subviews in it. The top one (let's call it HeaderView from now one) is a custom UIView and the bottom one is a UITableView.
I have set them up in InterfaceBuilder so that the HeaderView has 0 margin from the left, top and right, plus it has a fixed height.
The UITableView is directly underneath with 0 margin from all sides.
My goal is to achieve a behaviour such that when I start scrolling the UITableView's content the HeaderView will start shrinking and the UITableView becomes higher without scrolling. This should go on until the HeaderView has reached a minimum height. After that the UITableView should start scrolling as normal. When scrolling down the effect should be reversed.
I have initially started this out using a UIScrollView instead of the UITableView and I have achieved the desired result. Here is how:
connect the UIScrollView to the outlet
#IBOutlet weak var scrollView: UIScrollView!
set the UIScrollViewDelegate in the controller's viewDidLoad() method
self.scrollView.delegate = self
and declared the UIViewController to conform to the protocol
intercept when the UIScrollView scrolls:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.adjustScrolling(offset: scrollView.contentOffset.y, scrollView: scrollView)
}
in my adjustScrolling(offset:scrollView:) method the "magic" happens
Now let's look at what happens in this method.
private func adjustScrolling(offset: CGFloat, scrollView: UIScrollView) {
// bind value between 0 and max header scroll
let actualOffset: CGFloat = offset < 0 ? 0 : (offset >= self.maxHeaderScroll ? self.maxHeaderScroll : offset)
// avoid useless calculations
if (actualOffset == self.currentOffset) {
return
}
/**
* Apply the vertical scrolling to the header
*/
// Translate the header up to give more space to the scrollView
let headerTransform = CATransform3DTranslate(CATransform3DIdentity, 0, -(actualOffset), 0)
self.header.layer.transform = headerTransform
// Adjust header's subviews to new size
self.header.didScrollBy(actualOffset)
/**
* Apply the corrected vertical scrolling to the scrollView
*/
// Resize the scrollView to fill all empty space
let newScrollViewY = self.header.frame.origin.y + self.header.frame.height
scrollView.frame = CGRect(
x: 0,
y: newScrollViewY,
width: scrollView.frame.width,
height: scrollView.frame.height + (scrollView.frame.origin.y - newScrollViewY)
)
// Translate the scrollView's content view down to contrast scrolling
let scrollTransform = CATransform3DTranslate(CATransform3DIdentity, 0, (actualOffset), 0)
scrollView.subviews[0].layer.transform = scrollTransform
// Set bottom inset to show content hidden by translation
scrollView.contentInset = UIEdgeInsets(
top: 0,
left: 0,
bottom: actualOffset,
right: 0
)
self.currentOffset = actualOffset
}
If I haven't forgotten anything this should be enough to achieve the desired effect. Let me break it down:
I calculate the actualOffset binding it between 0 and self.MaxHeaderScroll which is just 67 (I think, it's calculated dynamically but this doesn't really matter)
If I see that the actualOffset hasn't changed since the last time this function was called I don't bother to aplly any changes. This avoids some useless calculations.
I apply the scrolling to the header by translating it up with a CATransform3DTranslate on just the y axis by negative actualOffset.
I call self.header.didScrollBy(actualOffset) so that the HeaderView can apply some visual changes internally. This doesn't concearn the question though.
I resize the scrollView so that it keeps 0 margin from top and bottom now that the HeaderView is higher up.
I translate down the scrollView's content by the same actualOffset amount to contrast the scrolling. This piece is essential to the correct visual effect that I want to achieve. If I didn't do this, the scrollView would still resize correctly but the content would start scrolling right away, which I don't want. It should only start scrolling once the HeaderView reaches it's minimum height.
I now set a bottom inset in the scrollView so that I am able to scroll it all the way to the end. Without this, the last part of the scrollView would be cut off since the scrollView itself would think it reached the end of it's content.
Lastly I store the actualOffset for later comparison
As I said, this works fine. The problem arises when I switch from a UIScrollView to a UITableView. I assumed it would work since UITableView inherits from UIScrollView.
The only piece of code that doesn't work is the number 6. I don't really know what is going wrong so I will just list everything I have found out and/or noticed. Hopefully someone will be able to help me out.
in the case of the UIScrollView, in point 6, the scrollView.subviews[0] refers to a view that holds all the content inside it. When I change to UITableView this subview seems to be of the type UITableViewWrapperView which I could not find any documentation about, nor does XCode recognize it as a valid class. This is already frustrating.
if in point 6 I also give some translation on the x axis (let's say of 50) I can see an initial very quick translation that is immediately brought back to 0. This only happens when the UITableView starts scrolling, it doesn't go on while scrolling.
I have tried changing the frame of the subview in point 6 to achieve the desired result. Although the scrolling is correct, the top cells start disappearing as I scroll the UITableView. I thin this is because I am using dequeueReusableCell(withIdentifier:for:) to instatiate the cells and the UITableView thinks that the top cells aren't visible when they actually are. I wasn't able to work around this problem.
I have tried setting the self.tableView.tableHeaderView to a UIView of the actualOffset height to contrast scrolling but this gave a weird effect where the cells would not scroll correctly and when the UITableView was brought back to the initial position, there would be a gap on top. No clue about this either.
I know there's a lot here so please don't hesitate asking for more details. Thank you in advance.
I made something like this recently, so heres how I achieved it:
Make a UIView with a height constraint constant and link this to your view/VC, have you UITableview constrained to the VC's view full screen behind the UIView.
Now set your UITableViews contentInset top to the starting height of your 'headerView' now, in the scrollViewDidScroll you adjust the constant until the height of the header is at its minimum.
Here is a demo
If you just run it, the blue area is your 'header' and the colored rows are just any cell. You can autolayout whatever you want in the blue area and it should auto size and everything

Proportional sized UIImageView in a UITableVIewCell is not behaving correctly all the time

I have a UIImage in a tableview cell that I want to show in a circle. When my table is rendered the first time the images are shown in a diamond shape instead of a circle, but when I go to that same screen after the first time the images are rendered in circle. I have found the problem, but I don't know the solution. Here's the problem: In the storyboard the UIImage view has a width and height set to 135, this is a random number because I assumed that I could overwrite it with the following two constraints in the storyboard: 1) a constraint that sets the height proportional to the superview's height and 2) a 1:1 ratio for the height and the width of the UIImage. Here's the snapshot of my constraints:
I added prints to tableView:cellForRowAtIndexPath where I change the layout to a circle to see the UIImage width. The first time it prints 135 and the second time it prints 100. This means that the proportional size constraints weren't effective in the first round, but they are effective after. I tried to set the fixed height and width in the storyboard to zero but that didn't help, it showed the image in a square. How can I enforce the proportional constraints all the time? Or disable the fixed size properties for this particular view? Thanks!
P.S. Here's the code inside tableView:cellForRowAtIndexPath that changes the layout to a circle (nothing else in that method that touches the image or the layout):
cell.imageView.layer.cornerRadius = cell.imageView.frame.size.width / 2
cell.imageView.clipsToBounds = true
cell.imageView.image = data.image
Try to reload table in viewWillLayoutSubViews.
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
[self.tableView reloadData];
}

iOS Xcode fill background image based on percentage

Looking to fill the background image in Xcode iOS based on a percentage.
The Constraints
The image must fill the entire screen (centered), so that the smallest dimension (width or height) fits. (Even if image becomes pixelated because it has a small file size.)
This must work universal, both iPad and iPhone devices.
Examples
You can use UIImageView. To make an image fill the screen, set imageView.contentMode to ScaleAspectFill.
To make UIImageView fill the screen, use auto layout. The easiest way is to add 4 constraints for UIImageView. Spacing to nearest neighbor = 0 will do. Like so:
Or leading/trailing/top/bottom space to superview = 0, if you like.
Set height and width of your image view to the width and height of your screen
var image:UIImageView = UIImageView(frame: CGRectMake(0, 0, self.view.frame.width, self.view.frame.height))
You want to make a UIImageView with the contentMode set to .ScaleAspectFill and add it as the bottom subview of your view.

UIScrollView decrease bottom height

I want to decrease the bottom height of UIScrollView. For more details click on this link
scrollview image
in that image red color box is extra space. dashly image is another view. My scroller runs between Apple and Dashly view. When i move that scroller content size bottom shows more height.
I done this through storyboard. Added constraints also.
//_scrollViewOutlet.contentSize = CGSizeMake(320, 650);
_scrollViewOutlet.contentInset = UIEdgeInsetsMake(0, 0, -7, 0);
i tried the above two lines but it is not worked. Thanks in advance.
_scrollViewOutlet.contentInset = UIEdgeInsetsMake(0, 0, -100, 0);
It works fine for me.
The issue you have is that the scrollview thinks it has a larger content size than it does.
You need to set the content size of the scrollview, calculate this correctly and set it, then it will work fine.
Dont hack it, by adjusting the insets.

Resizing UIImageView inside a UITableViewCell

in my app the UITableViewCell size are dynamic which means each has it's own height. inside of each cell there is a background image in a UIImageView. Through storyboard, i used autolayouts to customize the UIImageView to automatically stretch as the cell is stretched. The problem is that when they stretch the whole image stretches with the corners. So i was looking up online and i came over using resizableImageWithCapInsets: in order to stretch the stretchable sides and exclude the unwanted ones. So i tried the following code in tableView: cellForRowAtIndexPath: as i wanted the image to be stretched vertically only (height):
[cell.backgroundImage.image resizableImageWithCapInsets:UIEdgeInsetsMake(16, 0, 16, 0)];
however, the problem persisted as in the picture below
As you can see, the image corners are still stretched. What am i doing wrong? is the edgeInset values wrong? or should i place the code somewhere else ?
You create UIEdgeInsets values using the UIEdgeInsetsMake() function. UIEdgeInsets encapsulates four different CGFloat values for the inset values of the top, bottom, left, and right individually. Positive inset values shrink the content area, while negative inset values will effectively increase it. Make sure you create the image first and apply the insets there and then, Once that is done then apply the image to the backgroundView as opposed to trying to edit the edge insets from the backgroundView.image property.
UIImageView *cellBGIV =
[[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"imageName"]
resizableImageWithCapInsets:UIEdgeInsetsMake(5.0, 5.0, 5.0, 5.0)]];
cell.backgroundView = cellBGIV;

Resources