Self sizing tableview UILabel overflow - ios

I'm having difficulty laying out my custom cell. I have an image view and two labels. A titleLabel and overview label.
My problem is the overviewLabel is extending outside of the cell and is inconsistent. I think this throws off the rest of the labels.
My goal is to fit the labels better to the cell and improve the layout.
My constraints are as follows.
Custom Cell Class
self.photoImageView.translatesAutoresizingMaskIntoConstraints = false;
[self.photoImageView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor].active = YES;
[self.photoImageView.widthAnchor constraintEqualToAnchor:self.photoImageView.heightAnchor].active = YES;
[self.photoImageView.topAnchor constraintEqualToAnchor:margins.topAnchor].active = YES;
[self.photoImageView.bottomAnchor constraintLessThanOrEqualToAnchor:margins.bottomAnchor constant:0].active = YES;
self.photoImageView.contentMode = UIViewContentModeScaleAspectFit;
self.photoImageView.layer.cornerRadius = 17;
self.photoImageView.layer.masksToBounds = YES;
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false;
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.photoImageView.trailingAnchor].active = YES;
[self.titleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:margins.trailingAnchor].active = YES;
[self.titleLabel.topAnchor constraintEqualToAnchor:margins.topAnchor].active = YES;
self.titleLabel.font = [UIFont fontWithName:#"Avenir-Book" size:13];
self.titleLabel.textAlignment = NSTextAlignmentLeft;
self.overviewLabel.translatesAutoresizingMaskIntoConstraints = false;
[self.overviewLabel.leadingAnchor constraintEqualToAnchor:self.photoImageView.trailingAnchor].active = YES;
[self.overviewLabel.trailingAnchor constraintEqualToAnchor:margins.trailingAnchor].active = YES;
[self.overviewLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:5].active = YES;
[self.overviewLabel.bottomAnchor constraintGreaterThanOrEqualToAnchor:margins.bottomAnchor constant:0].active = YES;
[self.overviewLabel sizeToFit];
In my viewdidLoad for mytableview I have the following
self.moviesTableView.estimatedRowHeight = 100;
self.moviesTableView.rowHeight = UITableViewAutomaticDimension;

Related

UICollectionViewCompositionalLayout equal item height using autolayout

I'm using a UICollectionViewCompositionalLayout to create a grid. Each cell contains a multi-line label. My goal is that, when 1 item in a group/row grows, all others in that group/row grow to the same height e.g. in the attached pic, I would like the cells in column 2 and 3, row 2, to match the height of the first cell that contains ("1000\ndetail").
I have tried various things like setting the height of the items to fractional(1) but that then prevented multi line. Other attempts such as changing the dimensions of the group did not help either. How can I set up my UICollectionViewCompositionalLayout to achieve my goal please?
Collection View:
NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.333] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1]];
NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];
NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1] heightDimension:[NSCollectionLayoutDimension estimatedDimension:40]];
NSCollectionLayoutGroup *group = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:groupSize subitem:item count:3];
NSCollectionLayoutSection *section = [NSCollectionLayoutSection sectionWithGroup:group];
UICollectionViewCompositionalLayout *compositionalLayout = [[UICollectionViewCompositionalLayout alloc] initWithSection:section];
UICollectionView *cv = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:compositionalLayout];
cv.translatesAutoresizingMaskIntoConstraints = NO;
cv.dataSource = self;
cv.delegate = self;
[self.view addSubview:cv];
[cv registerClass:[GridCVCell class] forCellWithReuseIdentifier:#"Cell"];
[cv.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:100].active = YES;
[cv.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:0].active = YES;
[cv.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:0].active = YES;
[cv.heightAnchor constraintEqualToConstant:300].active = YES;
CollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame {
if ([super initWithFrame:frame]) {
UILabel *titleL = [UIlabel new];
titleL.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:titleL];
[titleL.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:10].active = YES;
[titleL.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-10].active = YES;
[titleL.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor constant:-2].active = YES;
[self.contentView.heightAnchor constraintEqualToAnchor:titleL.heightAnchor constant:10].active = YES;
}
return self;
}

Custom UITableViewCell auto layout doesn't work

I'm trying to implement a custom table cell using Auto Layout programmatically like below, but for some reason I didn't get the expected result.
Expected:
Actual:
My observation is:
The cell height doesn't grow as the content grows, and content overflows;
The bar element should be a vertical blue bar, but it's not properly showing up;
Setting background colors on the UIView elements doesn't work at all for some reason.
Please share some pointers on what I did wrong. Thanks in advance
UITableViewCell Code is below:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.infoContainer = [[UIView alloc] init];
self.title = [[UILabel alloc] init];
self.time = [[UILabel alloc] init];
self.bar = [[UIView alloc] init];
[self.infoContainer addSubview:self.bar];
[self.infoContainer addSubview:self.title];
[self.infoContainer addSubview:self.time];
[self.contentView addSubview:self.infoContainer];
self.infoContainer.translatesAutoresizingMaskIntoConstraints = NO;
self.title.translatesAutoresizingMaskIntoConstraints = NO;
self.time.translatesAutoresizingMaskIntoConstraints = NO;
self.bar.translatesAutoresizingMaskIntoConstraints = NO;
[self.infoContainer.leftAnchor constraintEqualToAnchor:self.contentView.leftAnchor constant:18].active = YES;
[self.infoContainer.rightAnchor constraintEqualToAnchor:self.contentView.rightAnchor constant:-18].active = YES;
[self.infoContainer.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:10].active = YES;
self.infoContainer.backgroundColor = [UIColor yellowColor];
[self.bar.leftAnchor constraintEqualToAnchor:self.infoContainer.leftAnchor constant:0].active = YES;
[self.bar.topAnchor constraintEqualToAnchor:self.infoContainer.topAnchor constant:0].active = YES;
[self.bar.bottomAnchor constraintEqualToAnchor:self.infoContainer.bottomAnchor constant:0].active = YES;
[self.bar.heightAnchor constraintEqualToAnchor:self.infoContainer.heightAnchor].active = YES;
[self.bar.widthAnchor constraintEqualToConstant:10];
self.bar.backgroundColor = [UIColor blueColor];
[self.title.leftAnchor constraintEqualToAnchor:self.bar.rightAnchor constant:15].active = YES;
[self.title.rightAnchor constraintEqualToAnchor:self.infoContainer.rightAnchor constant:0].active = YES;
[self.title.topAnchor constraintEqualToAnchor:self.infoContainer.topAnchor constant:0].active = YES;
[self.time.leftAnchor constraintEqualToAnchor:self.title.leftAnchor constant:0].active = YES;
[self.time.rightAnchor constraintEqualToAnchor:self.title.rightAnchor constant:0].active = YES;
[self.time.topAnchor constraintEqualToAnchor:self.title.bottomAnchor constant:10].active = YES;
}
return self;
}
and in the table view, I have:
self.recentView.rowHeight = UITableViewAutomaticDimension;
self.recentView.estimatedRowHeight = 64.0f;
Thanks!
Automatic height completely depends on hooking constraints properly from top to bottom , so you miss 2 constraints
1-
[self.infoContainer.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:10].active = YES;
2-
[self.time.bottomAnchor constraintEqualToAnchor:self.infoContainer.bottomAnchor constant:10].active = YES;
Tip : If you set top & bottom constraints here
[self.bar.topAnchor constraintEqualToAnchor:self.infoContainer.topAnchor constant:0].active = YES;
[self.bar.bottomAnchor constraintEqualToAnchor:self.infoContainer.bottomAnchor constant:0].active = YES;
Then no need for
[self.bar.heightAnchor constraintEqualToAnchor:self.infoContainer.heightAnchor].active = YES;

after change my tableframe its start scroll horizontally?

I create a table view in story board. when i change my tableView frame it become horizontal scroll and stop vertical scrolling. i am using auto resizing.
Code on viewDidLoad for table:
_inviTableView.layer.cornerRadius = 5;
_inviTableView.backgroundColor = [UIColor whiteColor];
_inviTableView.layer.masksToBounds = NO;
_inviTableView.layer.shadowOffset = CGSizeMake(0, 0);
_inviTableView.layer.shadowRadius = 10.0;
_inviTableView.layer.shadowOpacity = 0.5;
_inviTableView.clipsToBounds = YES;
[_inviTableView.layer setShadowColor:[UIColor blackColor].CGColor];
_inviTableView.delegate = self;
_inviTableView.dataSource = self;
[self.inviTableView registerClass:[inviYourBoastTableViewCell class] forCellReuseIdentifier:#"inviCell1"];
[self.inviTableView registerNib:[UINib nibWithNibName:#"inviYourBoastTableViewCell" bundle:Nil] forCellReuseIdentifier:#"inviCell1"];
self.inviTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
ViewDidAppear code:
#pragma mark:didappear
-(void)viewDidAppear:(BOOL)animated{
orignalInviTblFrame = _inviTableView.frame;
}
Method where i changed my table frame:
-(IBAction)getYourTopBoastValue:(UIButton*)senders{
inviDetailViewDataIndex = -1;
inviTopDetailViewIndex = (int)senders.tag-1;
[_inviDetailTableView reloadData];
self.inviTableView.frame = CGRectMake(orignalInviTblFrame.origin.x,_inviSelectedView.frame.size.height, orignalInviTblFrame.size.width, orignalInviTblFrame.size.height-_inviSelectedView.frame.size.height);
_inviSelectedView.hidden = NO;
[_inviTableView reloadData];
}
Note:_inviSelectedView is another tableView

super view - view - sub view. Implementation that masks textField not interactable. iOS. Help please

Thank you for looking, I try to implement in the super view (view controller) a custom view I created.
fromAge = [[simpleFormCell alloc]initWithFrame:CGRectMake(0, spaceFromTopLabel + 190, 200, 30)];
fromAge.title = #"Age";
fromAge.placeholder = #"";
fromAge.widthOfTextField = 60;
[fromAge populateView];
fromAge.textField.delegate = self;
fromAge.textField.tag = fromAgeTextFieldTag;
[fromAge.textField setInputView:multipurposePicker];
[scrollViewBackground addSubview:fromAge];
toAge = [[simpleFormCell alloc]initWithFrame:CGRectMake(0, spaceFromTopLabel + 190, 200, 30)];
toAge.title = #"to";
toAge.placeholder = #"";
toAge.widthOfTextField = 60;
toAge.leftPaddingForLabel = 210;
toAge.leftPaddingForTextField = 240;
[toAge populateView];
toAge.textField.delegate = self;
toAge.textField.tag = toAgeTextFieldTag;
[toAge.textField setInputView:multipurposePicker];
[scrollViewBackground addSubview:toAge];
simpleFormCell is a custom view with the following implementation:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
title = #"test";
placeholder = #"test2";
numberofLine = 1;
leftPaddingForLabel = 20;
leftPaddingForTextField = 140;
widthOfLabel = 90;
widthOfTextField = 160;
height = 30;
//[self populateView];
}
return self;
}
- (void)populateView{
label = [[UILabel alloc]initWithFrame:CGRectMake(leftPaddingForLabel, 0, widthOfLabel, (height * numberofLine))];
label.text = title;
label.textAlignment = UITextAlignmentLeft;
label.backgroundColor = [UIColor clearColor];
[self addSubview:label];
textField = [[UITextField alloc]initWithFrame:CGRectMake(leftPaddingForTextField, 0, widthOfTextField, (height * numberofLine))];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.placeholder = placeholder;
textField.textAlignment = UITextAlignmentCenter;
textField.tag = tag;
[textField setReturnKeyType:UIReturnKeyNext];
[self addSubview:textField];
}
I have a similar method that called [self populateView] in the init. That seems to work fine. Please assume that multipurposePicker is working correctly. This is the code but wont apply to these two instances.
- (id)initWithPreset1:(CGRect)frame title:(NSString *)titleValue numberOfLine:(int)numberOfLineValue delegate:(id) delegateValue tag:(int)tagValue{
self = [super initWithFrame:frame];
if (self) {
title = titleValue;
placeholder = #"";
numberofLine = numberOfLineValue;
leftPaddingForLabel = 20;
leftPaddingForTextField = 140;
widthOfLabel = 110;
widthOfTextField = 160;
height = 30;
tag = tagValue;
[self populateView];
textField.delegate = delegateValue;
}
return self;
}
These white boxes wont respond to my touch. (textFieldDidBeginEditing wont fire).
[fromAge becomeFirstResponder] works. It just wont respond to my touch. I made sure that there is nothing on top of it. Please help. Thank you!
I found the problem! Anna Karenina's comment guided me to the right solution. This has nothing to do with view hierarchy as I first thought. What happened was toAge was blocking fromAge. This makes fromAge textfield non-responsive. As per Anna's comment, eventhough toAge textfield was shown, it was out of the view that supports it. This prevents it from accepting any touches. Thus neither boxes receive any touches. Thank you Anna!

How to prevent UIView from being resized to fit ScrollView height (autoresizing disabled)?

I'm writing a PDF reader using vfr-reader library. To display two pages in landscape i'm rendering each page into its own view, then add these two views to a container view, then add container view to a scroll view. Each view's autoresizingMask is set to UIViewAutoresizingNone, contentMode is UIViewContentModeRedraw, autoresizingSubviews is set to 'NO' for all views.
But still somehow container view is autoresized to fit scroll view's height, and I don't know where is this happening. I care about this because, when autoresizing container view, it's width becomes larger than screen width, and I cannot scroll to the next two pages with a single swipe (two swipes are needed), which sucks. What am I missing?
EDIT gonna add some come if it helps. In the ViewController I create a Scroll View with following options:
theScrollView = [[ReaderScrollView alloc] initWithFrame:viewRect];
theScrollView.scrollsToTop = NO;
theScrollView.pagingEnabled = YES;
theScrollView.delaysContentTouches = NO;
theScrollView.showsVerticalScrollIndicator = NO;
theScrollView.showsHorizontalScrollIndicator = NO;
theScrollView.contentMode = UIViewContentModeRedraw;
theScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theScrollView.backgroundColor = [UIColor clearColor];
theScrollView.userInteractionEnabled = YES;
theScrollView.autoresizesSubviews = NO;
theScrollView.delegate = self;
[self.view addSubview:theScrollView];
When I'm drawing pages I'm adding an UIView to the Scroll View, which is being initiated this way:
if ((self = [super initWithFrame:frame]))
{
self.autoresizesSubviews = YES;
self.userInteractionEnabled = YES;
self.contentMode = UIViewContentModeRedraw;
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.backgroundColor = [UIColor clearColor];
theScrollView = [[ReaderScrollView alloc] initWithFrame:self.bounds]; // Not sure about this part - why is the 2nd scroll view added?
// this is the way its done in vfr reader
theScrollView.scrollsToTop = NO;
theScrollView.delaysContentTouches = NO;
theScrollView.showsVerticalScrollIndicator = NO;
theScrollView.showsHorizontalScrollIndicator = NO;
theScrollView.contentMode = UIViewContentModeRedraw;
theScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theScrollView.backgroundColor = [UIColor clearColor];
theScrollView.userInteractionEnabled = YES;
theScrollView.autoresizesSubviews = NO;
theScrollView.bouncesZoom = YES;
theScrollView.delegate = self;
theContentView = [[ReaderContentPage alloc] initWithURL:fileURL page:page password:phrase landscape:(BOOL)isLandscape position:FALSE];
CGRect viewRect = CGRectZero;
viewRect.size.width = theContentView.bounds.size.width;
viewRect.size.height = theContentView.bounds.size.height;
if( isLandscape){
NSLog(#"Landscape detected in content view");
if (theContentView == NULL)
{
theContentView = [[ReaderContentPage alloc] initWithURL:fileURL page:(page+1) password:phrase landscape:(BOOL)isLandscape position:FALSE];
theContentView2 = NULL;
viewRect.size.width = theContentView.bounds.size.width;
viewRect.size.height = theContentView.bounds.size.height;
} else {
if (page == 1)
theContentView2 = NULL;
else
theContentView2 = [[ReaderContentPage alloc] initWithURL:fileURL page:(page+1) password:phrase landscape:(BOOL)isLandscape position:TRUE];
if (theContentView2 != NULL)
viewRect.size.width = theContentView.bounds.size.width*2;
}
}
if (theContentView != nil) // Must have a valid and initialized content view
{
theContainerView = [[UIView alloc] initWithFrame:viewRect];
theContainerView.autoresizesSubviews = NO;
theContainerView.userInteractionEnabled = NO;
theContainerView.contentMode = UIViewContentModeRedraw;
theContainerView.autoresizingMask = UIViewAutoresizingNone;
theContainerView.backgroundColor = [UIColor whiteColor];
theScrollView.contentSize = theContentView.bounds.size; // Content size same as view size
theScrollView.contentOffset = CGPointMake((0.0f - CONTENT_INSET), (0.0f - CONTENT_INSET));
theScrollView.contentInset = UIEdgeInsetsMake(CONTENT_INSET, CONTENT_INSET, CONTENT_INSET, CONTENT_INSET);
theThumbView = [[ReaderContentThumb alloc] initWithFrame:theContentView.bounds]; // Page thumb view
[theContainerView addSubview:theThumbView]; // Add the thumb view to the container view
[theContainerView addSubview:theContentView]; // Add the content view to the container view
if(( isLandscape) && (theContentView2 != NULL)){
[theContainerView addSubview:theContentView2]; // Add the content view to the container view
}
[theScrollView addSubview:theContainerView]; // Add the container view to the scroll view
[self updateMinimumMaximumZoom]; // Update the minimum and maximum zoom scales
theScrollView.zoomScale = theScrollView.minimumZoomScale; // Zoom to fit
}
[self addSubview:theScrollView]; // Add the scroll view to the parent container view
[theScrollView addObserver:self forKeyPath:#"frame" options:NSKeyValueObservingOptionNew context:NULL];
self.tag = page; // Tag the view with the page number
}
return self;
And ReaderContentPage is created this way:
if ((self = [super initWithFrame:frame]))
{
self.autoresizesSubviews = NO;
self.userInteractionEnabled = NO;
self.clearsContextBeforeDrawing = NO;
self.contentMode = UIViewContentModeRedraw;
self.autoresizingMask = UIViewAutoresizingNone;
self.backgroundColor = [UIColor clearColor];
view = self; // Return self
}
In the function updateMinimumMaximumZoom in the class ReaderContentView:
The calculation of the zoomscale to fit the screen is done with single view, but in landscape it should be calculated form theContainerView.
Try replacing this code
CGFloat zoomScale = ZoomScaleThatFits(targetRect.size, theContentView.bounds.size);
with
CGFloat zoomScale = ZoomScaleThatFits(targetRect.size, theContainerView.bounds.size);
There is a contentMode property in UIScrollView, change it to UIViewContentModeCenter or something else to prevent resizing.

Resources