I am using stroyboards for my project. My project is based on parsing json datas and displaying it in JSON. While parsing JSON I will receive two different datas. Title and Description
i have to parse this and have to fix in UItextview inside a uitableviewcell i have structured a uitableviewcell like this
TEXTVIEW,TEXTVIEW,LABEL,LABEL,LABEL,LABEL,LABEL;
Now my problem is my text view has to resize according to data, and based on that tableviewcell also has to resize I tried the above code but the view gets collapsing.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Need_Request";
NeedReqListCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
type = (NSString *)[array4 objectAtIndex:indexPath.row];
if([type isEqualToString:#"Money Donation"]) {
cell.createdby.text = (NSString *)[array3 objectAtIndex:indexPath.row];
cell.product.text = (NSString *)[array4 objectAtIndex:indexPath.row];
cell.expiration.text = (NSString *)[array5 objectAtIndex:indexPath.row];
cell.titleview.text = (NSString *)[array1 objectAtIndex:indexPath.row];
[cell.descview setHidden:TRUE];
[cell.totalquantity setHidden:TRUE];
[cell.fulfilledquantity setHidden:TRUE];
return cell;
}
else if([type isEqualToString:#"Service"]) {
cell.createdby.text = (NSString *)[array3 objectAtIndex:indexPath.row];
cell.product.text = (NSString *)[array4 objectAtIndex:indexPath.row];
cell.expiration.text = (NSString *)[array5 objectAtIndex:indexPath.row];
cell.titleview.text = (NSString *)[array1 objectAtIndex:indexPath.row];
cell.descview.text = (NSString *)[array2 objectAtIndex:indexPath.row];
[cell.totalquantity setHidden:TRUE];
[cell.fulfilledquantity setHidden:TRUE];
return cell;
}
cell.createdby.text = (NSString *)[array3 objectAtIndex:indexPath.row];
cell.product.text = (NSString *)[array4 objectAtIndex:indexPath.row];
cell.expiration.text = (NSString *)[array5 objectAtIndex:indexPath.row];
cell.totalquantity.text = (NSString *)[array6 objectAtIndex:indexPath.row];
cell.fulfilledquantity.text = (NSString *)[array7 objectAtIndex:indexPath.row];
cell.titleview.text = (NSString *)[array1 objectAtIndex:indexPath.row];
cell.descview.text = (NSString *)[array2 objectAtIndex:indexPath.row];
CGRect bodyFrame = cell.titleview.frame;
bodyFrame.size = cell.titleview.contentSize;
[cell.titleview setFrame:bodyFrame];
CGRect bodyFrame1 = cell.descview.frame;
bodyFrame1.size = cell.descview.contentSize;
[cell.descview setFrame:bodyFrame1];
CGRect bodyFrame2 = cell.createdby.frame;
[cell.createdby setFrame:bodyFrame2];
CGRect bodyFrame3 = cell.product.frame;
[cell.product setFrame:bodyFrame3];
CGRect bodyFrame4 = cell.expiration.frame;
[cell.expiration setFrame:bodyFrame4];
CGRect bodyFrame5 = cell.totalquantity.frame;
[cell.totalquantity setFrame:bodyFrame5];
CGRect bodyFrame6 = cell.fulfilledquantity.frame;
[cell.fulfilledquantity setFrame:bodyFrame6];
return cell;
}
when i tried this code my screen looks like this
Please help me to Solve this issue
Check this link - http://www.springtiger.co.uk/2010/11/28/dynamically-generate-labels-frame-to-match-its-content/
It will explain how to resize UIlabel to fit contents.
One more suggestion would be use a single control and use NSFormatted Text instead of so many labels. (Again it depends on your requirement).
You need to move the labels' frame origin as well so that they are placed below each other. So after you calculate the first textView's size and bounds, set the origin of the second textView to whichever offset from the bottom of the first textView. But that gets complicated when you have to take into account different orientations and device screen sizes...
Why don't you use auto-layout and constraints?
Related
I have a table view that loads 3 custom cells. 1 custom cell has an ImageView in it, and it seems to be the culprit of the table view moving when any cell is tapped.
This is what I've tried, but it hasn't worked.
If I use a static value (i.e. return 180) it works just fine, but anything other than that the table view jumps.
Anyone know why? Thanks!
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
id model = self.Model[indexPath.row];
if ([model isKindOfClass:[FR self]]) {
ListTableViewCell *cellOne = [tableView dequeueReusableCellWithIdentifier:#"1Cell" forIndexPath:indexPath];
if (!cellOne) {
cellOne = [[ListTableViewCell alloc] init];
FR *fD = (FR *)model;
NSString *title = [NSString stringWithFormat:#"%#", fD.title];
NSString *dateString = [self timeSincePublished:fD.pubDate];
NSString *description = [self removeHTMLTags:fD.description];
NSString *link = [NSString stringWithFormat:#"%#", fD.link];
cellOne.labelHeadline.text = title;
cellOne.labelDescription.text = description;
cellOne.labelPublished.text = dateString;
}
// Make sure the cell's frame is updated
[cellOne setNeedsLayout];
[cellOne layoutIfNeeded];
CGFloat heightOne = [cellOne.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return heightOne + 2;
} else if ([model isKindOfClass:[D self]]) {
// more code
}
As far as I know, this is a bug. The workaround to avoid the table jumping right after tapping a cell is to add:
[self.tableview reloadData];
in your table viewWillDisappear
https://devforums.apple.com/message/1050163#1050163
https://devforums.apple.com/message/1042398#1042398
I have a cell. Whenever the text in cell row is equal to "(null)" I want the label to be on the right hand side of the the cell.
Here is my code at the moment, but it isn't doing anything. No errors, it just doesn't align to the right hand side of the cell. Any ideas?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"ChatListItem";
NSDictionary *itemAtIndex = (NSDictionary *)[messages objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if([[itemAtIndex objectForKey:#"user"] isEqualToString:#"(null)"]){
cell.textLabel.textAlignment=UITextAlignmentRight;
cell.detailTextLabel.textAlignment=UITextAlignmentRight;
}
cell.textLabel.text = [itemAtIndex objectForKey:#"text"];
cell.detailTextLabel.text = [itemAtIndex objectForKey:#"user"];
return cell;
}
First, did you step through the code and check the contents of the value for keys "user" and "text"?
If all is as expected, you should do the following:
Replace UITextAlignmentRight with NSTextAlignmentRight to silence compiler warnings.
Explicitly set NSTextAlignmentRight and NSTextAlignmentLeft, otherwise you will not get the correct update in recycled cells.
Finally, make sure the label's width is fixed. Otherwise, the width of the label will be based on its content, so that the alignment (within the label) loses its effect.
The only working solution for your case (without subclassing of the UITableViewCell of course)
is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ChatListItem";
NSDictionary *dict = [_tableData objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = dict[#"text"];
cell.detailTextLabel.text = dict[#"user"];
if ([dict[#"user"] isEqualToString:#"(null)"]) {
[self performSelector:#selector(alignText:) withObject:cell afterDelay:0.0];
}
return cell;
}
- (void)alignText:(UITableViewCell*)cell
{
CGRect frame = cell.textLabel.frame;
frame.origin.x = cell.frame.size.width - (frame.size.width + 10.0);
cell.textLabel.frame = frame;
frame = cell.detailTextLabel.frame;
frame.origin.x = cell.frame.size.width - (frame.size.width + 10.0);
cell.detailTextLabel.frame = frame;
[cell setNeedsDisplay];
}
As for me, I would better make a subclass.
I've looked over older questions and tried all the suggestions, but still cannot seem to get a multi-line UILabel to work. I have a UITableView and the cell is created by tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *fieldValue = [self fieldValueAtIndexPath:indexPath];
NSString *fieldName = [self fieldNameAtIndexPath:indexPath];
NSString *title = [[self appDelegate] displayNameForFieldName:fieldName];
Field fieldCode = [[self appDelegate] fieldCodeForFieldName:fieldName];
DetailCell *cell = nil;
NSString *identifier = nil;
BOOL isNotes = [fieldName caseInsensitiveCompare:#"Notes"] == NSOrderedSame;
switch( isNotes ) {
case NO:
{
identifier = #"DetailCell";
cell = (DetailCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
NSInteger rows = [self heightForText:fieldValue andFont:[self textFont] andWidth:cell.value.frame.size.width] / _oneRowSize.height;
cell.value.text = fieldValue;
cell.name.text = [title lowercaseString];
cell.name.numberOfLines = MAX( 1, rows );
cell.value.numberOfLines = cell.name.numberOfLines;
break;
}
case YES:
{
cell = (DetailCell *)[tableView dequeueReusableCellWithIdentifier:#"DetailCellNotes" forIndexPath:indexPath];
// cell = (DetailCell *)[tableView dequeueReusableCellWithIdentifier:#"DetailCellNotes"];
cell.value.text = #"This is a very long line of text which should take up several lines";
cell.name.text = [title lowercaseString];
cell.value.numberOfLines = 5; // No more than 5 lines of text
cell.value.backgroundColor = [UIColor purpleColor];
cell.value.lineBreakMode = NSLineBreakByWordWrapping;
cell.value.frame = CGRectMake(cell.value.frame.origin.x, cell.value.frame.origin.y, 180, 70);
[cell.value sizeThatFits:CGSizeMake(180., 70.)];
break;
}
}
cell.fieldName = fieldName;
return cell;
}
The height in the table view is defined like so
- (CGFloat) tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
NSString *fieldName = [self fieldNameAtIndexPath:indexPath];
CGFloat height = 0.0;
if([fieldName isEqualToString:#"Notes"])
{
height = 70.;
}
else if([fieldName isEqualToString:#"Image"])
{
height = 100.;
};
return height;
}
which makes the cell large enough to hold a 3-line label. However when the cell appears the label is only one line (shown by the background being purple).
The tableview uses prototype cells, and I've also tried to set it to numberOfLines=5 and WordWrapping, but that didn't change the effects either. I've also tried both of the commented out lines (though searches suggest that sizeToFit might actually reset numberOfLines to 1).
I wonder what I've missed. I can't see any other place where the it might be overridden.
Thanks.
You are calling dequeueReusableCellWithIdentifier: to create your cell. This is a mistake, because it means that the cell has not assumed its final size. It is much better to call dequeueReusableCellWithIdentifier:forIndexPath:. This means that the cell will actually have the height that you are giving it in heightForRowAtIndexPath:. You should then be able to set the height of the label successfully.
I'm new in iOS programming, and I have a strange problem...
I created a tableview, add cells with "subtitle" style. In my code, I can set the image, all works fine. the code (g, gf and picturesArray are strings array) :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * cellIdentifier = #"fCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSString *feed = [self.g objectAtIndex:indexPath.row];
NSString *feed1 = [self.gf objectAtIndex:indexPath.row];
NSString *feed2 = [self.picturesArray objectAtIndex:indexPath.row];
[cell.textLabel setText:feed];
[cell.detailTextLabel setText:feed1];
cell.imageView.image = [UIImage imageNamed:feed2];
return cell;
}
Next, I want to go to a new view when I click on a cell. Here the code :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
GUDdfViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"GUdfView"];
detail.titleString = [self.gf objectAtIndex:indexPath.row];
detail.descriptionString = [self.gfs objectAtIndex:indexPath.row];
detail.contentString = [self.gfc objectAtIndex:indexPath.row];
detail.imageNameString = [self.picturesArray objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detail animated:YES];
}
OK. All works; in my new view, title and subtitle are present with good content.
BUT ! the image is not displayed... Here the line where I set the image in "GUDdfViewController" :
[self.pictureLogoOutlet setImage:[UIImage imageNamed:self.imageNameString]];
When I use NSLog, it says me that my object (pictureLogoOutlet.image) is null. I also tried this :
[self.pictureLogoOutlet setImage:[UIImage imageNamed:#"baguette.png"]];
but the problem is the same...
Do you know why I have this problem ? I really don't understand.
pictureLogoOutlet in nil because your GUDdfViewController has not yet initialized its IBOutlets.
You have to create property of UIImage to your viewocntroller and using that property load imageView in your GUDdfViewController's viewDidLoad.
I have table view that rendering cells. I created the cell once and reuse it. In each cell there is a button to do vote action for a place. On the vote action I want to change the background image of the button. When I click on the button in a certain cell the background image changes, but when I scroll down I find another button with the changed background image. I believe that the problem is because I'm using dequeueReusableCellWithIdentifier but I can't find a way to solve this problem.
Here is my code:
// .h file
#interface VotePlaceView : UIView < UITableViewDataSource, UITableViewDelegate>
{
VotePlaceView *votePlaceCell;
}
and in the implementation file
// .m File
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"votePlaceCell"];
if (cell)
{
votePlaceCell = (VotePlaceView*)[cell viewWithTag:10];
}
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"votePlaceCell"];
//GlobalObjects is a customised thing for me to load the cell in different languages
votePlaceCell = [[GlobalObjects loadNibNamed:#"votePlaceCell" owner:self options:nil] objectAtIndex:0];
votePlaceCell.tag = 10;
[cell addSubview:votePlaceCell];
}
.
. //Fill data in the cell
.
//This gives different IDs, no ID like the others (unique ID)
NSLog(#"ID %d", [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue]);
UIButton* voteButton = (UIButton*)[votePlaceCell viewWithTag:20];
voteButton.tag = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
return cell;
}
-(IBAction)votePlace:(UIButton *)sender
{
// I tried two ways to achieve my point with no luck
//Selected case give the new background image
//THE FIRST WAY
sender.selected = YES;
//OR THE SECOND WAY
UIButton* newVotePlace;
newVotePlace = (UIButton*)[[sender superview] viewWithTag:sender.tag];
newVotePlace.selected = YES;
}
Any idea?
The Solution
#Akhilrajtr's answer solved my problem, after I made some changes to his answer. Here is the solution, in case if anyone faced the same problem.
Instead of using a UIButton, I used UIButton and UIImageView. I put the UIImageView behind the UIButton and I give the UIImageView two images in the default case and in the highlighted case. I cleared the background image of the UIButton and then followed the accepted answer as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.
.
int placeId = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
UIButton* voteButton = (UIButton*)[votePlaceCell viewWithTag:20];
if (!voteButton) {
voteButton = (UIButton*)[votePlaceCell viewWithTag:placeId];
}
voteButton.tag = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
if ([selectedIdArray containsObject:[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"]]) {
UIImageView* voteImage;
voteImage = (UIImageView*)[votePlaceCell viewWithTag:11];
voteImage.highlighted = YES;
} else {
UIImageView* voteImage;
voteImage = (UIImageView*)[votePlaceCell viewWithTag:11];
voteImage.highlighted = NO;
voteButton.selected = NO;
}
return cell;
}
-(IBAction)votePlace:(UIButton *)sender
{
[selectedIdArray addObject:[NSNumber numberWithInt:sender.tag]];
UIImageView* voteImage;
voteImage = (UIImageView*)[[sender superview] viewWithTag:11];
voteImage.highlighted = YES;
}
Try this,
Create a NSMutableArray *selectedIdArray (don't forget to instatiate selectedIdArray in viewDidLoad:) to store selected ID's , and in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.
.
//Other codes
.
.
NSLog(#"ID %d", [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue]);
int placeId = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
UIButton* voteButton = (UIButton*)[votePlaceCell viewWithTag:20];
if (!voteButton) {
voteButton = (UIButton*)[votePlaceCell viewWithTag:placeId];
}
voteButton.tag = [[[self.votePlacesResults objectAtIndex:indexPath.row] valueForKey:#"id"] intValue];
if ([selectedIdArray containsObject:[NSNumber numberWithInt:placeId]) {
voteButton.selected = YES;
} else {
voteButton.selected = NO;
}
return cell;
}
and in
-(IBAction)votePlace:(UIButton *)sender
{
[selectedIdArray addObject:[NSNumber numberWithInt:sender.tag]];
sender.selected = YES;
}
You need to store an array containing information about the background for each cell, and set the background for each cell in cellForRowAtIndexPath.
As you're using selected on the button, create an NSMutableArray with as many entries as the cells, and instead of setting the button itself to selected, change the bool on the selected index of the array, then you can set selected dependent on the value of the desired index of NSMutableArray in cellForRowAtIndexPath.