poor performance of scrollview inside tableview ios - ios

I have trouble with table view and its response because every cell has scrollView with 72 labels in it. I know that scrollView needs to load all elements first, and than load on screen, and because of that table view is slow, but is there a way maybe not to allocate and call initWithFrame method every time I create label? I tried to reuse label with different frame, but it is not working.
Here is code I need to optimize somehow to create labels faster.
int listSize = 36;
for(int i=0;i<listSize;i++){
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0+i*200, 0, 200, 80)];
label.text = #"HELLO";
label.textColor = [UIColor blackColor];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont fontWithName:#"ArialMT" size:18];
[scrolView addSubview:label];
UILabel *grayBorderInFront = [[UILabel alloc] initWithFrame:CGRectMake(2+i*200, 5, 1, scrolView.frame.size.height-10)];
grayBorderInFront.text = #"";
grayBorderInFront.backgroundColor = [UIColor lightGrayColor];
[scrolView addSubview:grayBorderInFront];
}

You can always have one TableView and eachCell has a horizontal CollectionView.
Set the scroll direction property to horizontal and use the UIViewCollectionFlowLayout
The CollectionView will guarantee that your labels (that are cells) are being reused and that you are doing an efficient job.

Few weeks ago I implemented EPG layout for iPhone app using collectionView with custom layout.
On the iPad app other developer implemented the EPG with scrollView with array of collectionView flow layout.
The custom layout work mach better.
You mentioned that you need iOS 5 hence you can try the following open source replacement to collection view:
https://github.com/steipete/PSTCollectionView

Save your labels in an array and then add them just to the view. Or you could even cache the whole scrollview.
Edit:
You keep a list of values that are updating. For all the labels created in the scrollview you set a tag label1.tag = 4; (starting from 1 instead of zero because 0 is the default one and other views have it as well).
Then, in your cellForViewAtIndexPath instead of creating a new label every time, you get the labels with [cell viewWithTag:] and you get a reference of the label. The only thing you have to do is to change the value of the label. You can also use the tag as index in the array:
int index = 3; // third label
[(UILabel*)[cell viewWithTag:index+1] setText:[myLabelsArray objectAtIndex:index]];

Related

Making a UIView keep its size when used as a table header view

If I use the following code to add a tableHeaderView to a table...
UILabel *label = [UILabel new];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.text = #"Hello, world!";
self.tableView.tableHeaderView = label;
The result is that the content of the table is pushed down by the height of the label.
This is fine and is what I want.
However, when I use my own custom view (set up in code) which has its own subviews etc... then the content of the table is not pushed down and the header view overlaps onto the content.
I'm not using AutoLayout to place the subviews of my custom view because of the nature of the view it doesn't really work as an AutoLayout view.
The frame of my custom view is (0, 0, 0, 0) with the content of the header view being drawn outside its bounds.
I have implemented the - (CGSize)sizeThatFitsSize:(CGSize)size method of my custom view but that hasn't changed anything.
Is there something else I need to implement also?
Example
If I use the following code to put a label inside my custom view...
- (instancetype)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
UILabel *label = [UILabel new];
label.text = #"Hello, world!";
[label sizeToFit];
[self addSubview:label];
label.frame = CGRectMake(0, 0, CGRectGetWidth(label.bounds), CGRectGetHeight(label.bounds));
}
return self;
}
Then the label appears in the same place as before but the content is not pushed down.
The frame of the view when you set it as the table header view is the size that the table view allocates and maintains for the view.
So, you need to determine the required size for your header view and change it's frame before setting it.
The table view will not make and queries or size changes for you. Autoresizing rules do apply so if the table view frame changes the header view will be resized according to the rules you specify. This may lead to different issues.

UIScrollView with dynamic content

I'm trying to implement a UIScrollView, but every tutorial out there deals with a preset number of items.
What I have are multiple UITextField's, but the number of textfields vary. Basically, as soon as one textField contains text, another empty one appears below it, allowing the user to fill in an unlimited number of textfields.
My code creates a new textfield as soon as the user types something into a previous one. The x-coordinatesof this is the same as the previous one, but the y-coordinatesto the new one equals the height of the previous + 5px.
I'm using storyboards, and I have placed my original textField within a UIScrollView. I have connected this scrollView to my code, and I add a new textfield this way: [self.scrollView addSubview:newTextField];
However, when the amount of textFields exceeds the scrollView, I cannot scroll to reveal the new one that's been added.
How would I go about doing this? I don't think I completely get the setContentSize thing, so it might have something to do with that. Here are some pictures and code to explain my problem:
Code to add new textfield:
UITextField *newTextField = [[UITextField alloc]initWithFrame:CGRectMake(textField.frame.origin.x, textField.frame.origin.y + textField.frame.size.height+5, textField.frame.size.width, textField.frame.size.height)];
newTextField.placeholder = #"Add more text";
newTextField.borderStyle = UITextBorderStyleNone;
newTextField.font = [UIFont systemFontOfSize:14];
newTextField.autocorrectionType = UITextAutocorrectionTypeYes;
newTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
newTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
newTextField.returnKeyType = UIReturnKeyDone;
[newTextField setTag:textFieldTag];
newTextField.delegate = self;
[self.scrollView addSubview:newTextField];
Storyboard:
Here you can see how I have placed the original textfield within my scrollview
How it looks in the simulator:
When you enter text in the textfield, this happens:
An empty textfield appears below the previous one.
However, when you exceed the ScrollView, this happens
You can no longer see the new textField because it is below the scrollView's boundaries. You can not scroll to reveal it either.
Does anyone know how to solve this? And if you have time, how would you make it so the scrollview automatically scrolls down to reveal the new textfield that's been added?
Any help is greatly appreciated! Thanks!
The contentSize needs to be the size of content contained within the scroll view.
If the contentSize is wider than the bounds.size, then you can scroll left and right. If the contentSize is taller than the bounds.size, then you can scroll up and down.
You need to set the contentSize to be the entire area you wish to contain within your scroll view.
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(textField.frame.origin.x, textField.frame.origin.y + textField.frame.size.height+5, textField.frame.size.width, textField.frame.size.height)];
textField.placeholder = #"Add more text";
textField.borderStyle = UITextBorderStyleNone;
textField.font = [UIFont systemFontOfSize:14];
textField.autocorrectionType = UITextAutocorrectionTypeYes;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
textField.returnKeyType = UIReturnKeyDone;
textField.tag = textFieldTag;
textField.delegate = self;
[self.scrollView addSubview:textField];
// Update the contentSize to include the new text field.
CGFloat width = self.scrollView.bounds.size.width;
CGFloat height = CGRectGetMaxY(textField.frame);
self.scrollView.contentSize = CGSizeMake(width, height);
NOTES:
Don't start variables or methods with new. It has special meaning and you will confuse other Objective-C developers and/or the compiler.
textField.tag = … is the same as [textfield setTag:…]; You seem to like the dot syntax in other places, so I switched to that.
I'm assuming you don't want the scroll view to pan left and right, so I pinned the content width to the scroll view's width.

multiple auto-resizable UILabels in table cell

I'm trying to put three UILabel in a cell of a table in iOS6. The first one is a number and is on the left, the second one is the title and is next to the first one, and the third one is a date placed on the right side of the cell.
The date and the title resize themselves correctly according to the length of the text, but when the title is a long one it should be truncated before the date, instead it appears also over the date.
How do I get the title to truncate before the date? I have also tried to set its frame width and using sizeToFit, but with no effect.
just use this condition for the expansion of your TitleLabel:
titleLabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 10, 20)];
dateLabel=[[UILabel alloc]initWithFrame:CGRectMake(160,0, 160, 20)];
[self.view addSubview:titleLabel];
[self.view addSubview:dateLabel];
titleLabel.text=#"sjlkfdsfjdfkdlfjlkdsjflkdfjkldsfkdjfkljdslkjflkdslkf";
dateLabel.text=#"fmldf";
[titleLabel sizeToFit];
if(titleLabel.frame.origin.x+titleLabel.frame.size.width>dateLabel.frame.origin.x)
{
titleLabel.frame=CGRectMake(titleLabel.frame.origin.x, titleLabel.frame.origin.y,
dateLabel.frame.origin.x-titleLabel.frame.origin.x-5, 20);
}
else
{
[titleLabel sizeToFit];
}
try this:
myLabel.adjustsFontSizeToFitWidth = YES;
EDIT:
cell.YOURLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin;
OPTION 2
[YOURLabel sizeToFit];
Just set the title label to the maximum allowable width in Interface Builder and set the Line Breaks option to the desired truncation mode. Or are you wanting the maximum allowable width to vary based on the width of the date label?

how to make horizontal scrolling menu in iOS

I would like to make a menu which will have horizontal scrolling.
The menu contains total 16 categories. So I am planning to take 8 on first part and rest 8 on another part.
Can some-one give me insight of what needs to be done?
I believe I need to use below.
UIScrollView
Add buttons in this scrollview
That's it?
What I want is on first screen 8 buttons where first screen will have two rows with 4 buttons set on each row.
Menu sample can be seen at http://www.shoutem.com/
If all you're doing is adding buttons to a horizontal scroll view you would do something like follows...
- (void)createScrollMenu
{
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 100)];
int x = 0;
for (int i = 0; i < 8; i++) {
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(x, 0, 100, 100)];
[button setTitle:[NSString stringWithFormat:#"Button %d", i] forState:UIControlStateNormal];
[scrollView addSubview:button];
x += button.frame.size.width;
}
scrollView.contentSize = CGSizeMake(x, scrollView.frame.size.height);
scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:scrollView];
}
This will create a scrollview with a height of 100, width as big as its parent, and add 8 buttons to it.
You can accomplish you're goal using a UIScrollView and your UIButton objects, it would involve setting each button's frame / layout properties depending on what iOS version you're targeting. (As in Eric's answer).
However, if you're targeting iOS 6 and above, using a UICollectionView where your items/cells are the buttons, then you can get the horizontal scrolling "menu bar" for free. There are plenty of SO posts on this, but the main idea is to use a flow layout where the item size has a height such that there will only be one row of items (just make the item height the same as the collection view's height).
EDIT:
I should say, this might seem like overkill (and maybe it is), but you will end up with a much more flexible component in case requirements change in the future. It also doesn't result in much extra code and abstracts away tedious layout details.

iOS: Adding a third label to UITableViewCell without creating a Custom cell?

I've worked with custom cells before but I just wondered for adding a third label (nothing else!) is there a simpler solution? All I want to do is show the title, content and date. I've set the first two to the textLabels and detailTextLabels but I of course need a third for date.
So, is there a simpler solution without making a custom cell?
Thanks
See A Closer Look at Table-View Cells, section called Programmatically Adding Subviews to a Cell’s Content View.
mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 220.0, 15.0)] autorelease];
mainLabel.tag = MAINLABEL_TAG;
mainLabel.font = [UIFont systemFontOfSize:14.0];
mainLabel.textAlignment = UITextAlignmentRight;
mainLabel.textColor = [UIColor blackColor];
[cell.contentView addSubview:mainLabel];
Try setting into cellForRowAtIndexPath (each time you create a new cell) modifying the textLabel and detailTextLabel Frame and adding to cell.contentView a new Label for the date...
But i think the correct way is to subclass the UItableViewCell class and create a custom cell

Resources