I have created a UICollectionView programmatically. I use a custom UICollectionViewCell subclass. Inside the cell class, I create a label with a class of my own (easier and quicker to set up its appearance).
The problem I'm having is : for several cells, the collectionView does not layout the label content. I know that the data is here (print in the console) that is, the text property of the cell does contain the string data I want to show, but for some reason the collectionView does not display the label content.
I tried with a simple test (print 'toto' inside the label) and I get a few toto's here and there, but not in all of the cells. As you can see I have 2 UICollectionViews inside the same ViewController, and this is why I test whether it's one or the other in the DataSource implementation.
Please tell me if you need more code.
Here's the code :
-(void)createBottomCollectionView {
// Layout
UICollectionViewFlowLayout *collectionViewLayout = [[UICollectionViewFlowLayout alloc] init];
collectionViewLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
collectionViewLayout.minimumLineSpacing = 0.0;
// UICollectionView
self.bottomCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(20, 354+20, 320-2*20, 35) collectionViewLayout:collectionViewLayout];
self.bottomCollectionView.showsHorizontalScrollIndicator = NO;
self.bottomCollectionView.bounces = YES;
self.bottomCollectionView.alwaysBounceHorizontal = YES;
self.bottomCollectionView.alwaysBounceVertical = NO;
self.bottomCollectionView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.bottomCollectionView.dataSource = self;
self.bottomCollectionView.delegate = self;
[self.bottomCollectionView registerClass:[SetFormatCollectionViewCell class] forCellWithReuseIdentifier:SetFormatCollectionViewCellIdentifier];
// Background
self.bottomCollectionView.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.bottomCollectionView];
[self.bottomCollectionView reloadData];
}
CollectionView datasource (dumb test with a "toto" value) in the real app I pull data with CoreData
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
if (collectionView == self.bottomCollectionView) {
SetFormatCollectionViewCell *cell = (SetFormatCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:SetFormatCollectionViewCellIdentifier forIndexPath:indexPath];
cell.text = #"toto";
return cell;
}
if (collectionView == self.collectionView) {
TrackingSetCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:TrackingSetCollectionViewCellIdentifier forIndexPath:indexPath];
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
return nil;
}
Custom Cell class :
#interface SetFormatCollectionViewCell : UICollectionViewCell
#property (strong,nonatomic) NSString *text;
#end
#implementation SetFormatCollectionViewCell
{
FormatLabel *aFormatLabel;
}
-(id)initWithFrame:(CGRect)frame {
if (self=[super initWithFrame:frame]) {
// Initialization code
aFormatLabel = [[FormatLabel alloc]initWithFrame:self.frame textColor:[UIColor blackColor] font:[UIFont fontWithName:#"ITCAvantGardeStd-Bk" size:22] alpha:1.0f border:YES];
[self.contentView addSubview:aFormatLabel];
}
return self;
}
-(void)prepareForReuse {
[super prepareForReuse];
self.text = #"";
}
-(void)setText:(NSString *)text {
_text = [text copy];
aFormatLabel.text = self.text;
}
FormatLabel Class (not important I think)
#interface FormatLabel ()
#property (assign,nonatomic) UIEdgeInsets edgeInsets;
#end
#implementation FormatLabel
-(id)initWithFrame:(CGRect)frame textColor:(UIColor *)color font:(UIFont *)font alpha:(CGFloat)alphaValue border:(BOOL)withBorder{
self = [super initWithFrame:frame];
if (self) {
// Set up
self.textAlignment = NSTextAlignmentCenter;
self.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
self.adjustsFontSizeToFitWidth = YES;
self.textColor = color;
self.alpha = alphaValue;
self.font = font;
if (withBorder) {
self.layer.borderWidth = 1.0f;
self.layer.borderColor = color.CGColor;
}
self.edgeInsets = UIEdgeInsetsMake(9, 6, 8, 6);
}
return self;
}
Thanks for helping
EDIT: for those who might have the same issue, I post 3 shots of the problem (you can find the answer just below). The 2nd shot contains colored cell the see the problem. The third shot is the one that I took just after accepting jmkk's answer.
Thanks for all the other answers!
Your problem lies with positioning of the FormatLabel view within the cell.
You're using cell's frame as the frame for the label, while what you need is the cell's bounds.
Cell's frame is relative to its superview, so applying the same position to cell's subview renders it offset relative to the cell itself.
Fix your code to do this:
aFormatLabel = [[FormatLabel alloc]initWithFrame:self.bounds textColor:[UIColor blackColor] font:[UIFont fontWithName:#"ITCAvantGardeStd-Bk" size:22] alpha:1.0f border:YES];
Related
I create a cell using this func:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
BOOL isFocusOn = [_userDefault boolForKey:#"mixFocusOn"];
CDCChannelStrip *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"cell" forIndexPath:indexPath];
if (isFocusOn == TRUE) {
NSNumber *setChan = [self.focusChannels objectAtIndex:indexPath.section];
NSInteger chanInt = [setChan intValue];
[cell initData:(chanInt)];
[self getParameters:(setChan)];
} else {
NSInteger chanInt = indexPath.section;
NSNumber *chanNum = [NSNumber numberWithInt:chanInt]; // doesnt matter
[cell initData:(chanInt)]; // init
[self getParameters:(chanNum)]; // params
}
[self.mixMonitorView setChannelsStripToType:(cell)];
cell.clipsToBounds = YES;
return cell;
}
The func in question is initData which looks like this:
- (void)initData:(NSInteger)channel {
self.isBus = false;
self.isSendChan = false;
self.recallSafeFade = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"recallSafe"]];
self.recallSafeFade.y = 80;
[self.recallSafeFade setUserInteractionEnabled:YES];
self.recallSafeHead = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"recallSafeHeadamp"]];
[self.recallSafeHead setUserInteractionEnabled:NO];
self.recallSafePan = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"recallSafePan"]];
self.recallSafePan.y = 768 - 141;
[self.recallSafePan setUserInteractionEnabled:YES];
self.channelNumber = channel;
[self setClipsToBounds:NO];
_background = [[UIView alloc] initWithFrame:CGRectMake(0, 80, 122, 547)];
[_background setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"singleFader"]]];
[self addSubview:_background];
[self addChannelName];
[self addInput];
[self addPan];
[self addOn];
[self addMeter];
[self addFader];
}
So the issue im having is, i need to call this func to setup my custom cell to look and function how i need it to. However, every time i call reload on the collectionview due to state changes, it layers the new views over the top of the old views (due to reocurring imageview alloc's)
So how can i apply this func to each cell automatically, yet not reapply it over the top every time i reload the cell?
Image of the issue ina view debugger here:
UICollectionViewCells are reused. So, avoid doing addSubView: (directly or indirectly as in your case: collectionView:cellForRowAtIndexPath: is calling initData: which is calling addSubView:), each time in collectionView:cellForItemAtIndexPath:.
You are using a UICollectionView and UICollectionViewCell only by code.
So there is no XIB/Storyboard were is the cell, and no IBOutlet.
According to the doc of dequeueReusableCellWithReuseIdentifier:forIndexPath:, that's the part you fall into:
If you registered a class for the specified identifier and a new cell
must be created, this method initializes the cell by calling its
initWithFrame: method.
So, in CDCChannelStrip.m, override initWithFrame: and initialize its properties (that are "always" visible/used).
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_myImageViewProperty = [[UIImageView alloc] initWithFrame:someFrame];
[self addSubview:_myImageViewProperty];
etc.
}
return self;
}
-(void)updateWithChannel:(NSInteger)channel
{
self.channelNumber = channel;
self.channelLabelName = #"Something";
//etc.
}
You can also use prepareForReuse to "reinit" the cell as "virgin" (like it was just after initWithFrame: for instance.
-(void)prepareForReuse
{
[super prepareForReuse];
self.channelLabelName = #"";
self.backgroundColor = [UIColor clearColor];
//etc.
[self.sometimesThatImageIsShown setHidden:YES];
}
Simplest way is to create a separate xib for cell or prototype cell. Design you cell there and in cellForItemAtIndexPath you just manipulate your views and set values to your labels, images and other controllers.
I am trying to create a Card Based News feed (Similar to Facebook app) in iOS.I'm implementing programmatically because the height of UITablecell has to increase/decrease based on the data.
Consider i have one UIlabel and one UIImageView added, then the height of UITablecell should be adjusted based on the fields. If one more text feild is added then height has to increase and if imageview is removed then height has to decrease.
The issue here is I couldn't to add CustomView on the UItablecell programmatically but when i create using Interface builder then its working fine but the height remains constant which i don't want to have.
Can some one please help me out.
TableViewCell.h
#interface TableViewCell : UITableViewCell
#property (strong,nonatomic) UIView *customView;
#property (strong,nonatomic) UILabel *customLabel;
#property (strong,nonatomic) UIImageView *customImage;
#end
TableViewCell.m
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// configure control(s)
[self addSubview:self.customView];
[self.customView addSubview:self.customLabel];
[self.customView addSubview:self.customImage];
}
return self;
}
- (UIView *)customView
{
if (!_customView)
{
_customView = [[UIView alloc] initWithFrame:CGRectMake(0, 10, self.contentView.frame.size.width, 50)];
[_customView setTranslatesAutoresizingMaskIntoConstraints:NO];
}
return _customView;
}
- (UIImageView *)customImage
{
if (!_customImage)
{
_customImage = [UIImageView new];
_customImage.clipsToBounds = YES;
[_customImage.layer setBorderColor: [[UIColor grayColor] CGColor]];
[_customImage.layer setBorderWidth: 1.0];
_customImage.contentMode = UIViewContentModeCenter;
[_customImage setTranslatesAutoresizingMaskIntoConstraints:NO];
}
return _customImage;
}
- (UILabel *)customLabel
{
if (!_customLabel)
{
_customLabel = [UILabel new];
[_customLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
}
return _customLabel;
}
UITableVIewController.m
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!_stubCell)
{
_stubCell = [tableView dequeueReusableCellWithIdentifier:#"TableCell"];
}
});
CGFloat height = [_stubCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height + 1;
}
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50.f;
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"TableCell";
// Similar to UITableViewCell, but
_stubCell = (TableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (_stubCell == nil) {
_stubCell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// Just want to test, so I hardcode the data
_stubCell.customLabel.text = #"Testing";
return cell;
}
I think it may be better to create multiple nibs for the same class UITableViewCell, one for each of the possible layouts that you need. Depending on which nib is used then set heightForRowAtIndexPath to the height of the nib.
This will give you predictability of the layout for each situation and you connect only the fields defined in UITableViewCell in cellForRowAtIndexPath.
never mind i found answer by myself. I am calculating the height of each UIView that is added the super view. Based on the total height the UITableview height increases and decrease and also using auto layout adjusting the layout constraints made me simple.
I am still working on the design once its done i'll post the code so that it will be help ful for other developers.
I have written a subclass of UITableViewCell to allow horizontal swipe to give some actions to users. Here is what I am doing:
Create a scrollView
Create a buttonView and add in scrollView.
Create a UIButton and add all cell controls as subview to it. Add in scroll view.
Add scrollView to cell contentView.
For #3 I am setting the highlighted image to give a feel of user tap like in normal cell.
The issue is when my table view is loaded on iOS 6 with 6 cells and user tap on any of the cell, cell gets highlighted properly and the details are shown properly for the tapped cell. But if user scrolls up and first cell is re-used and user tap on the top cell (which is second row), cell next to it gets highlighted. If user scrolls up and purge 2 cells and tap on the top cell, cell 2 cells down it gets highlighted. Although tapped cell shows the data of the correct cell.
Any clue?
- (id)initWithStyle:(UITableViewCellStyle)iStyle reuseIdentifier:(NSString *)iReuseIdentifier andMenuButtonDetails:(NSArray *)iMenuButtonDetails {
if ((self = [super initWithStyle:iStyle reuseIdentifier:iReuseIdentifier])) {
self.catchWidth = kMenuButtonWidth * [iMenuButtonDetails count];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(kScreenOrigin, kScreenOrigin, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds))];
self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.bounds) + self.catchWidth, CGRectGetHeight(self.bounds));
self.scrollView.delegate = self;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.scrollEnabled = YES;
[self.contentView addSubview:self.scrollView];
self.scrollViewButtonView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds) - self.catchWidth, kScreenOrigin, self.catchWidth, CGRectGetHeight(self.bounds))];
[self.scrollView addSubview:self.scrollViewButtonView];
if ([iMenuButtonDetails count]) {
// Adding menu buttons to the cell.
CGFloat anXOffset = kScreenOrigin;
for (NSDictionary *aMenuButton in iMenuButtonDetails) {
if ([aMenuButton containsObjectForKey:kTitleKey]) {
UIButton *aButton = [[UIButton alloc] initWithFrame:CGRectMake(anXOffset, kScreenOrigin, kMenuButtonWidth, kCellHeight64)];
[aButton addTarget:self action:#selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
if ([aMenuButton containsObjectForKey:kButtonTagKey])
aButton.tag = [[aMenuButton stringForKey:kButtonTagKey] intValue];
aButton.titleEdgeInsets = UIEdgeInsetsMake(kScreenOrigin, 2.0, kScreenOrigin, 2.0);
aButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
[aButton.titleLabel setTextAlignment:NSTextAlignmentCenter];
[aButton setTitle:[aMenuButton stringForKey:kTitleKey] forState:UIControlStateNormal];
[aButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
if ([aMenuButton objectForKey:kButtonColorKey]) {
aButton.backgroundColor = [aMenuButton objectForKey:kButtonColorKey];
}
[self.scrollViewButtonView addSubview:aButton];
anXOffset += kMenuButtonWidth;
}
}
}
self.scrollViewContentView = [UIButton buttonWithType:UIButtonTypeCustom];
self.scrollViewContentView.frame = CGRectMake(kScreenOrigin, kScreenOrigin, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds));
if (![Utilities isIOS7orAbove]) {
[self.scrollViewContentView addTarget:self action:#selector(cellHighlighted) forControlEvents:UIControlEventTouchDown];
[self.scrollViewContentView addTarget:self action:#selector(cellCancelHighlight) forControlEvents:UIControlEventTouchDragExit];
}
[self.scrollViewContentView addTarget:self action:#selector(selectCell:) forControlEvents:UIControlEventTouchUpInside];
self.scrollViewContentView.backgroundColor = [UIColor whiteColor];
UIImage *aBGHighlightedImage = nil;
if ([Utilities isIOS7orAbove]) {
aBGHighlightedImage = [UIImage imageNamed:kCellHighlightedImageIOS7];
} else {
aBGHighlightedImage = [UIImage imageNamed:kCellHighlightedImageIOS6];
}
[self.scrollViewContentView setBackgroundImage:[aBGHighlightedImage stretchableImageWithLeftCapWidth:11.0f topCapHeight:0] forState:UIControlStateHighlighted];
[self.scrollView addSubview:self.scrollViewContentView];
[self.scrollViewContentView addSubview:self.imageView];
[self.scrollViewContentView addSubview:self.textLabel];
[self.scrollViewContentView addSubview:self.detailTextLabel];
}
- (void)prepareForReuse {
[super prepareForReuse];
self.scrollViewContentView.enabled = YES;
[self.scrollView setContentOffset:CGPointZero animated:NO];
}
- (UITableViewCell *)tableView:(UITableView *)iTableView cellForRowAtIndexPath:(NSIndexPath *)iIndexPath {
MyTableViewCell *aCell = (MyTableViewCell *)[iTableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if (!aCell) {
aCell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"CellIdentifier" andMenuButtonDetails:aMenuButtons];
}
// Set data on cell now
return aCell
}
Let me know if there is something I'm missing here, but it seems like you're adding a ton of complexity to your class for no reason. Are you familiar with UICollectionView?
Here's an example implementation (which scrolls horizontally):
#interface asdf () <UICollectionViewDataSource, UICollectionViewDelegate>
#property (strong, nonatomic) UICollectionView *collectionView;
#end
#implementation asdf
- (id)init
{
self = [super init];
if (self)
{
self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.collectionViewLayout];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
[self.view addSubview:self.collectionView];
NSString *className = NSStringFromClass([UICollectionViewCell class]);
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:className];
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.collectionView.frame = self.view.bounds;
}
- (UICollectionViewLayout *)collectionViewLayout
{
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 0;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
return layout;
}
#pragma mark - UICollectionView
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 5;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *className = NSStringFromClass([UICollectionViewCell class]);
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:className forIndexPath:indexPath];
// This is for dequeuing
NSInteger tag = 12324;
UIView *view = [cell viewWithTag:tag];
if (view)
[view removeFromSuperview];
view = [[UIView alloc] initWithFrame:cell.bounds];
view.tag = tag;
// Add all of your subviews to the view property
[cell addSubview:view];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(collectionView.bounds.size.width, 50);
}
#end
I wrote this quickly as a sample, so it's not tailored specifically to what you're building, but this should give you a nice idea of how simple it is to implement a UICollectionView.
This answer may come across as random for what you're asking, but when possible, you should always try to use what Apple provides over what you would spend precious hours re-inventing the wheel w/ & likely experience random nuances like yours.
I have a subclass of UITableViewCell, and I am having problems with scrolling. All of the subviews are added to the cell in the storyboard, except for one UIView. I want to add this UIView as a subview of the cell based on a condition. The problem is that when the cells are scrolled off and onto the screen, the UIView is added to the cell a second time, or to the wrong cell. Here is my code, can you tell me what I am doing wrong?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
WavesFeedCell *cell = (WavesFeedCell *)[tableView dequeueReusableCellWithIdentifier:WavesFeedCellIdentifier forIndexPath:indexPath];
cell.cellWaveObject = [self.wavesArray objectAtIndex:indexPath.row];
//set the frames and text for the labels
cell.timeStampLabel.text = #"14m";
cell.waveTextLabel.text = cell.cellWaveObject.waveString;
cell.wavedByLabel.text = [NSString stringWithFormat:#"Waved by %#", cell.cellWaveObject.wavedByString];
//round the corners of the image view
[self setCornerRadiusForImageView:cell.profilePictureImageView];
//does the wave object have any agrees?
if (cell.cellWaveObject.numberOfAgrees > 0)
{
UIView *agreedView = [[UIView alloc] init];
UILabel *numberOfAgreesLabel = [[UILabel alloc] init];
numberOfAgreesLabel.font = [UIFont boldSystemFontOfSize:13.0f];
numberOfAgreesLabel.textColor = [UIColor whiteColor];
if (cell.cellWaveObject.numberOfAgrees > 1)
{
numberOfAgreesLabel.text = [NSString stringWithFormat:#"+%i Agree", cell.cellWaveObject.numberOfAgrees];
}
else
{
numberOfAgreesLabel.text = [NSString stringWithFormat:#"+%i Agrees", cell.cellWaveObject.numberOfAgrees];
}
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:AgreedViewImage]];
//get the width of the string
CGSize constraintSize = CGSizeMake(242.0f, 16.0f);
CGSize stringSize = [numberOfAgreesLabel.text sizeWithFont:numberOfAgreesLabel.font constrainedToSize:constraintSize];
CGFloat agreedViewWidth = stringSize.width + 10.0f;
//adjust the frame and add it to the cell
agreedView.frame = CGRectMake(310.0f - agreedViewWidth, cell.wavedByLabel.frame.origin.y, agreedViewWidth, 14.0f);
backgroundImageView.frame = CGRectMake(5.0f, 0.0f, agreedView.frame.size.width, agreedView.frame.size.height);
numberOfAgreesLabel.frame = CGRectMake(5.0f, 0.0f, agreedView.frame.size.width, agreedView.frame.size.height);
[agreedView addSubview:backgroundImageView];
[agreedView addSubview:numberOfAgreesLabel];
[cell.contentView addSubview:agreedView];
return cell;
}
else
{
return cell;
}
}
May be added subview is not removing from cell.Content View .
Try using following code within cellForRow method
UIView *agreedView=(UIView*)[cell.contentView viewWithTag:21];
//does the wave object have any agrees?
if (cell.cellWaveObject.numberOfAgrees > 0)
{
if (!agreedView) {
agreedView=[[UIView alloc] init];
agreedView.tag=21;
UILabel *numberOfAgreesLabel = [[UILabel alloc] init];
numberOfAgreesLabel.font = [UIFont boldSystemFontOfSize:13.0f];
numberOfAgreesLabel.textColor = [UIColor whiteColor];
numberOfAgreesLabel.tag=22;
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:AgreedViewImage]];
backgroundImageView.tag=23;
[agreedView addSubview:backgroundImageView];
[agreedView addSubview:numberOfAgreesLabel];
[cell.contentView addSubview:agreedView];
}
numberOfAgreesLabel=(UILabel*)[agreedView viewWithTag:22];
backgroundImageView=(UIImageView*)[agreedView viewWithTag:23];
if (cell.cellWaveObject.numberOfAgrees > 1)
{
numberOfAgreesLabel.text = [NSString stringWithFormat:#"+%i Agree", cell.cellWaveObject.numberOfAgrees];
}
else
{
numberOfAgreesLabel.text = [NSString stringWithFormat:#"+%i Agrees", cell.cellWaveObject.numberOfAgrees];
}
//get the width of the string
CGSize constraintSize = CGSizeMake(242.0f, 16.0f);
CGSize stringSize = [numberOfAgreesLabel.text sizeWithFont:numberOfAgreesLabel.font constrainedToSize:constraintSize];
CGFloat agreedViewWidth = stringSize.width + 10.0f;
//adjust the frame and add it to the cell
agreedView.frame = CGRectMake(310.0f - agreedViewWidth, cell.wavedByLabel.frame.origin.y, agreedViewWidth, 14.0f);
backgroundImageView.frame = CGRectMake(5.0f, 0.0f, agreedView.frame.size.width, agreedView.frame.size.height);
numberOfAgreesLabel.frame = CGRectMake(5.0f, 0.0f, agreedView.frame.size.width, agreedView.frame.size.height);
return cell;
}
else
{
if (agreedView) {
[agreedView removeFromSuperview];
}
return cell;
}
Better you set frames for your custom views in subclassed UITableView cell's class
hear is the sample code
//.h file of subclassed UITableView cell
#import <UIKit/UIKit.h>
#interface WavesFeedCell : UITableViewCell
#property(nonatomic, retain)UILabel *timeStampLabel;
#property(nonatomic, retain)UILabel *waveTextLabel;
#property(nonatomic, retain)UILabel *wavedByLabel;
#property(nonatomic, retain) id cellWaveObject; //your object from array
#end
//.m file subclassed UITableView cell
#import "WavesFeedCell.h"
#implementation WavesFeedCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
UILabel *label1 = [[UILabel alloc]initWithFrame:CGRectZero];
UILabel *label2 = [[UILabel alloc]initWithFrame:CGRectZero];
UILabel *label3 = [[UILabel alloc]initWithFrame:CGRectZero];
self.timeStampLabel = label1;
self.waveTextLabel = label2;
self.wavedByLabel = label3;
//these are added with zero rect
[self addSubview:label1];
[self addSubview:label2];
[self addSubview:label3];
//for agreed imageview
UIImageView *agreedImgView = [[UIImageView alloc]initWithFrame:CGRectZero];
agreedImgView.tag = 200; //to access in layoutsubviews.
[self addSubview:agreedImgView];
//without ARC
[agreedImgView release];
[label1 release];
[label2 release];
[label3 release];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)layoutSubviews
{
[super layoutSubviews];
//hear set frames for all labels
self.timeStampLabel.frame = CGRectMake(5, 5, self.bounds.size.width-30.0f, 40.0f);
self.waveTextLabel.frame = CGRectMake(5, 45, self.bounds.size.width-30.0f, 40.0f);
self.wavedByLabel.frame = CGRectMake(5, 95, self.bounds.size.width-30.0f, 40.0f);
//hear you check weather it is agreed or not
if(self.cellWaveObject.numberOfAgrees > 1)
{
UIImageView *agreedView = (UIImageView *)[self viewWithTag:200];
//set frme for imageview as you did
// remember dont add any views hear and set your required frames only because this method called many times
}
//in other class
//.m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
WavesFeedCell *cell = [self.aTableView dequeueReusableCellWithIdentifier:#"WavesFeedCell"];
if(cell == nil)
{
cell = [[WavesFeedCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"WavesFeedCell"];
}
//set cell properties
return cell;
}
I make a custom UICollectionViewCell and add a subView to its contentView:
BooksCell.h
#interface BooksCell : UICollectionViewCell
#property (strong, nonatomic) UIImageView *certifyImageView;
#end
BooksCell.m
- (id)initWithFrame:(CGRect)frame {
self= [super initWithFrame:frame];
if(self){
_coverImageView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 15, 88, 117)];
_coverImageView.userInteractionEnabled = YES;
[self.contentView addSubview:_coverImageView];
UIImage *certifyImage = [UIImage imageNamed:#"13-6.png"];
_certifyImageView = [[UIImageView alloc] initWithFrame:CGRectMake(17.5, _coverImageView.frame.size.height-3, certifyImage.size.width, certifyImage.size.height)];
_certifyImageView.image = certifyImage;
_certifyImageView.hidden = YES;
}
return self;
}
ViewController
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
BooksCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"BooksCell" forIndexPath:indexPath];
cell.coverImageView.image = [UIImage imageNamed:#"13-5.png"];
// **Here I want some cell display certifyImageView and some not.**
if(indexPath.row%2==0){
cell.certifyImageView.hidden = NO;
}
return cell;
}
I add the collectionView as subView to the Viewcontroller, and set it's frame correctly, now the collectionView displaied coverImageView and certifyImageView normally, but when I scroll the collectionView, certifyImageView displaied on the wrong cell,I guess it maybe caused by the Reuse Cell, and how to sole it?
I think because it is reusing the cell that already set the certifyImageView.hidden to NO so you have to set it back to YES
Maybe try this
if(indexPath.row%2==0){
cell.certifyImageView.hidden = NO;
}
else{
cell.certifyImageView.hidden = YES;
}
This way you will make sure that the certifyImageView will be set to hidden if thats what you want.