I'm building a UITableView with style tableview Grouped, and i give a gap (margin left) on method frame UITableViewCell like this
- (void)setFrame:(CGRect)frame {
if(IOS_7){ //above ios 6
CGFloat gap = 10.0f;
frame.origin.x += gap;
frame.size.width -= gap*2;
}
[super setFrame:frame];
}
the result like this.
and then after 5s, i did call method
[_table beginUpdates];
[_table endUpdates];
the result like this.
the gap on the right twice from my gap = (gap*2)
this problem only on ios 8,
is the iOS 8 call twice setFrame in uitableviewcell ?
and how to solve it ?
note:
- i have been tried with reset frame with CGRectMake(0.0f, frame.origin.y, [UIScreen mainScreen].bounds.size.width, frame.size.height); but if i'm using with ipad with left menu side, it's not solve my problem,
- does not use custom cell (just using default uitableviewcell)
You are setting the frame wrong. You should be doing this:
- (void)setFrame:(CGRect)frame {
if(IOS_7){ //above ios 6
CGFloat gap = 10.0f;
frame.origin.x += gap;
frame.size.width -= gap*2;
[super setFrame: frame];
}
}
Related
I have a issue that my viewDidLayoutSubviews creates a strange offset between my table wiche is right under the view and my view
I for example uncomment this section of my code and scroll in my table this content view diapers as soon as I start to scroll
looks like this:
Offset between view and table
I really do not have a clue why this exists. The problem is not regarding the constrains I have tested it with connecting the view with the code and not.
What I do
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[self.TableView setContentInset:UIEdgeInsetsMake(self.ContainerView.frame.size.height, 0.f, 0.f, 0.f)];
[self.TableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
float headerImageYOffset = 88 + self.ContainerView.bounds.size.height - self.view.bounds.size.height;
CGRect headerImageFrame = _ContainerView.frame;
headerImageFrame.origin.y = headerImageYOffset;
}
What I do when I scroll
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat scrollOffset =-scrollView.contentOffset.y;
CGFloat yPos = scrollOffset - _obergurglContainerView.bounds.size.height;
_obergurglContainerView.frame = CGRectMake(0, yPos, _obergurglContainerView.frame.size.width, _obergurglContainerView.frame.size.height);
float Alpha = 1.0-(-yPos/_obergurglContainerView.frame.size.height);
_obergurglTitleImageView.alpha = Alpha;
NSLog(#"THE Alpha Value : %f", Alpha);
NSLog(#"The off set of the scroll view is %f",scrollOffset);
}
Thanks for help and fast answer ! :)
So reading again the question I figured out about your problem.
I think you shouldn't use viewDidLayoutSubviews.
viewDidLayoutSubviews is called all the time while you are scrolling, which is modifying the inset in your tableview all the time.
try to place
[self.TableView setContentInset:UIEdgeInsetsMake(self.ContainerView.frame.size.height, 0.f, 0.f, 0.f)];
where you create your tableview.
So far I have customized the tableview and implemented the iPad General Setting Page. Below is the code for tableview which will change frame accordingly. But the issue is when I insert/delete rows or section in the tableview. My tableviewcell backgroundview (not cell) width get shrinks. Any idea what wrong am I doing here?
- (void)setFrame:(CGRect)frame
{
if (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad)
{
CGFloat inset =10;
frame.origin.x += inset;
frame.size.width -= 2 * inset;//The issue is in this line
}
[super setFrame:frame];
}
I found the simple solution to achieve this. No need of customizing UITableView subclass. Just take the outlet of tableview and set the frame and change the color of backgroundview. like that below:-
CGFloat tableBorderLeft = 10;
CGFloat tableBorderRight = 10;
CGRect tableRect = self.view.frame;
tableRect.origin.x += tableBorderLeft; // make the table begin a few pixels right from its origin
tableRect.size.width -= tableBorderLeft + tableBorderRight; // reduce the width of the table
yourTableView.frame = tableRect;
self.view.backgroundColor=[UIColor colorWithRed:(239/255.0f) green:(239/255.0f) blue:(244/255.0f) alpha:1.0];
I am using UITableViewAutomaticDimension for multiline UILabel in UITableViewCell and everything works fine on iPhone. To add a margin to the table view on iPad I'm using a custom subclass overriding setFrame:
- (void)setFrame:(CGRect)frame {
if (IS_IPAD) {
CGFloat inset = 100;
frame.origin.x += inset;
frame.size.width -= 2 * inset;
}
[super setFrame:frame];
}
The problem is, that the UITableViewAutomaticDimension is returning the wrong (too small) height for the cell on iPad and the label gets cut off. I assume it's returning the height calculated for the full width.
Is there any way to get the table view calculate the right height?
EDIT:
found a quite hacky solution, but this does not work when setting attributedText
- (void)setFrame:(CGRect)frame {
if (IS_IPAD) {
CGFloat inset = 100;
frame.origin.x += inset;
frame.size.width -= 2 * inset;
for (UIView *subview in self.contentView.subviews) {
if ([subview isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel *)subview;
if (label.numberOfLines == 0) {
label.preferredMaxLayoutWidth = frame.size.width;
}
}
}
}
[super setFrame:frame];
}
If you are doing something like this. Combining technology of Size Classes and Auto-Layout is able to solve the problem in a very easy way. Otherwise, it will require a lot of redrawing and calculation when you want to do that in a manual way. Also, when you are using UITableViewAutomaticDimension, you should go with this way as well because this flag simply indicates that iOS should calculate the cell height automatically via Auto-Layout.
I've set up the positioning for my UILabels like so:
- (void) layoutSubviews {
[super layoutSubviews];
CGRect cvf = self.contentView.frame;
self.imageView.frame = CGRectMake(0.0,
0.0,
cvf.size.height-1,
cvf.size.height-1);
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
CGRect frame = CGRectMake(cvf.size.height + 5,
self.textLabel.frame.origin.y-10,
cvf.size.width - cvf.size.height - 2*1,
self.textLabel.frame.size.height);
self.textLabel.frame = frame;
frame = CGRectMake(cvf.size.height + 5,
self.detailTextLabel.frame.origin.y-8,
cvf.size.width - cvf.size.height - 2*1,
self.detailTextLabel.frame.size.height);
self.detailTextLabel.frame = frame;
frame = CGRectMake(cvf.size.height + 5,
self.bestMatchLabel.frame.origin.y-4,
cvf.size.width - cvf.size.height - 2*1,
self.bestMatchLabel.frame.size.height);
self.bestMatchLabel.frame = frame;
}
For some reason, upon reloading the UITableView, bestMatchLabel moves up a few pixels, so that it looks like the below picture. Every time I reload it, it moves up more and more. I sense that there's something about the Y positioning thats causing it to relate its current position to its previous one. Am I correct?
It is obvious the code :
self.textLabel.frame.origin.y-10,
self.detailTextLabel.frame.origin.y-8
self.bestMatchLabel.frame.origin.y-4,
make the y change every load. You must set a fix y in every layout.
I've got a UICollectionView that takes the whole of the screen. The UICollectionView has cells as big as the UICollectionView itself, and I use paging.
On rotation of the device I want the cells to adjust their size to the new UICollectionView size. I currently achieve this by interchanging a layout object in willAnimateRotationToInterfaceOrientation::
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[_collectionView setCollectionViewLayout:[self collectionViewFlowLayoutForOrientation:toInterfaceOrientation] animated:YES];
}
with collectionViewFlowLayoutForOrientation: being as follows:
- (UICollectionViewFlowLayout *)collectionViewFlowLayoutForOrientation:(UIInterfaceOrientation)orientation
{
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
CGFloat width = UIInterfaceOrientationIsLandscape(orientation) ? MAX(screenSize.width, screenSize.height) : MIN(screenSize.width, screenSize.height);
CGFloat height = UIInterfaceOrientationIsLandscape(orientation) ? MIN(screenSize.width, screenSize.height) : MAX(screenSize.width, screenSize.height);
UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[collectionViewFlowLayout setItemSize:CGSizeMake(width, height)];
[collectionViewFlowLayout setMinimumLineSpacing:0.0f];
[collectionViewFlowLayout setSectionInset:UIEdgeInsetsZero];
[collectionViewFlowLayout setMinimumInteritemSpacing:0.0f];
return collectionViewFlowLayout;
}
It doesn't work as intended.
First of all, I get a message in the console indicating I probably am doing something not entirely legitimate:
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values.
It is a fair message, as starting the animation to rotate, the screen / UICollectionView still has the frame for the old orientation. I'd be inclined to abide it.
Secondly, the contentOffset is incorrect after rotation as it doesn't get recalculated.
I've seen other solutions which just invalidate the layout in willRotateToInterfaceOrientation:duration:, but this doesn't recalculate the contentOffset either. I followed it up by changing the contentOffset and contentSize as follows, but the result is not perfect either:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
CGSize fromCollectionViewSize = [self collectionViewSizeForOrientation:[self interfaceOrientation]];
CGSize toCollectionViewSize = [self collectionViewSizeForOrientation:toInterfaceOrientation];
CGFloat currentPage = [_collectionView contentOffset].x / [_collectionView bounds].size.width;
NSInteger itemCount = [_collectionView numberOfItemsInSection:0];
UICollectionViewFlowLayoutInvalidationContext *invalidationContext = [[UICollectionViewFlowLayoutInvalidationContext alloc] init];
[invalidationContext setContentSizeAdjustment:CGSizeMake((toCollectionViewSize.width - fromCollectionViewSize.width) * itemCount, toCollectionViewSize.height - fromCollectionViewSize.height)];
[invalidationContext setContentOffsetAdjustment:CGPointMake(currentPage * toCollectionViewSize.width - [_collectionView contentOffset].x, 0)];
[[_collectionView collectionViewLayout] invalidateLayoutWithContext:invalidationContext];
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
So, my question is: What solution gives the intended result?
Try adding the line
[_collectionView invalidateIntrinsicContentSize] just before you set your layout. This should cause it to re-calculate the layout, and, hopefully get rid of your warning message.