ScrollView in Custom Cell on TableView iOS - ios

I have custom cell on my table view which I've created with nib file. I have there 2 horizontal scrollViews. Target platform is iOS 7.
On Cell XIB file I've created "constrants" for every tableView (because I'm using autolayout).
On my Custom cell implementation file I have such code:
-(void)layoutSubviews
{
self.SwitchPageSV.contentSize = CGSizeMake(960, 240);
self.SwitchPageSV.scrollEnabled = YES;
self.SwitchPageSV.delegate = self;
self.ButtonsSV.contentSize = CGSizeMake(400, 40);
self.SwitchPageSV.scrollEnabled = YES;
}
And it is working like a charm. But when I go from this table view to other View Controller and go back, scroll view does not work anymore. I have to scroll my tableView to recreate cell and than it is working again.
Reloading data doesn't help:
I was trying to define those values on:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
on my viewController, where I'm putting all data to this cell. But from there, my settings for scroll view are not working at all. I have no idea what to do with that thing. Any help?

This is because layoutSubviews method in your code only invokes after initialization. But you need to execute the code inside this method even after coming back. For this you have to call setNeedsLayout
[self setNeedsLayout ];

Related

Image on cells not all the way to the left

I am learning about UITableview on iOS and following a course online. I get the table showing fine, but the images on my cells are not all the way to the left (whereas the instructor's ones are). Here is a screenshot of the cells in question:
I don't want that gap, I want the images to be positioned right at the beggining of the cell, all the way to the left. I have done some research and it seems Apple has changed the default look of the cells between ios6 and ios7 so that now the images in cells show a little gap at the left. To get rid of it, I have tried UIEdgeInsets:
[tableView setSeparatorInset:UIEdgeInsetsZero];
and that's not working. I also have tried this approach:
cell.imageView.frame = CGRectMake( 0, 0, 50, 55 );
Nothing happens. So how would I go about it? Thanks
edit-------------------------------------------------------------------------------------------------------------------------------
Still not have found the answer to this. The solutions posted here don't work. I found this piece of code:
self.tableView.contentInset = UIEdgeInsetsMake(0, -50, 0, 0);
Which besides completely puzzling me (as the parameter affected should be the y?) I thought solved the issue by making the image on the cell appear all the way to the left, until I realised it only moved the whole view to the left (as I should have expected I guess) leaving an equal gap on the other side of the screen. All I want is for my images in the cells to appear all the way to the left of the cell as it used to be the case on previous ios. Thanks
It happens because default table content offset from left is 15, you should change it with 0.
See this once, you get idea Remove empty space before cells in UITableView
If you create custom cells. UITableViewCell have owner imageView. Change title of image in your cell.
If you use default cell, use custom cell with constraint Leading space = 0.
It is better not use default imageView of the cell. Drag and drop UIImageView from objective library, create a custom table view cell (Child class of UITableViewCell) then create and outlet of the image view just dragged.
The spacing in the UITableViewCell is because of the default TRUE returned by shouldIndentWhileEditingRowAtIndexPath method of UITableViewDelegate.
I was able to reproduce your problem by the below scenario:
UITableView is in editable mode:
self.tableView.editing = true
And you have implemented:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleNone;
}
To correct your code:
If you do not want to set Editing Style then you can turn off the editing mode by
self.tableView.editing = false
and remove editingStyleForRowAtIndexPath.
Else if you need editing mode then set the appropiate Editing style(UITableViewCellEditingStyleDeleteor UITableViewCellEditingStyleInsert) or simply turn the indentation off.
- (BOOL)tableView:(UITableView *)tableView
shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return FALSE;
}
You must create a custom cell, by adding a new class as a subclass of UITableViewCell. then you can design cell with autolayout and constraints which will resolve the issue.
there is a another concrete way to achieve this by creating subclass uitableviewcell (custom class).
steps to follow
create a class subclass of UITableViewCell.
in .h file create properties and outlets of UI components.
go to storyboard and add table view cell inside the tableview.
now add UI components like: imageview or button etc and set the x, y values according to.
make class of custom cell your className using identity inspector see image.
connect all outlets of UI components.
use below code uitableview
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *MyIdentifier = #"uniqueIdentifire";
yourCustomClassForCell *cell = (yourCustomClassForCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil){
cell = [[yourCustomClassForCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier];
}
cell.imageView.image = [imageAry objectAtIndex:indexPath.row];
}
Dont forget to give identifire by selecting your cell using storyboard Attribute inspector uniqueIdentifire to identifire property see image.
Also you can give some vertical space between cells by just to add this below code (Method only) inside customeCellClass.
- (void)setFrame:(CGRect)frame { // method to insert gap between table view cell
frame.origin.y += 6;
frame.size.height -= 2 * 6;
[super setFrame:frame];
}
You can not really change the frame of the inbuilt subviews of uitableviewcell like imageview, accessoryview. But if you create a custom tableviewcell class(even if you do not add any other subelement to it), you can change the frame of the inbuilt imageview by overriding the layoutSubviews method inside the UITableViewCell. I have tried it and it works.
#import "TableViewCell.h"
#implementation TableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(void) layoutSubviews{
[super layoutSubviews];
CGRect frame = self.imageView.frame;
frame.origin.x = 0;
self.imageView.frame = frame;
}
#end

iCarousel View in a table cell view does not scroll at all

I put the iCarousel View in a table View and try to scroll the iCarousel, but the problem is it's not scrollable at all.
I can see iCarousel in the cell like following:
and I put iCarousel datasource and delegate in the tableView Controller, create a customer function to set the iCarousel datasource and delegate.
In the CustomTableViewCell I just define the setting delegate function:
- (void) setICarouselDataSourceDelegate: (id<iCarouselDelegate,iCarouselDataSource>)dataSourceDelegate {
self.carousel.dataSource = dataSourceDelegate;
self.carousel.delegate = dataSourceDelegate;
[self.carousel reloadData];
}
and in the MainTableView, I call the DataSourceDelegate in the
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
First of all iCarousel is not any standarad View ... you should put link of the control that you're using
Second it seems like iCarousel is uses UIScrollView and UITableView is also derived from UIScrollView It's never a good idea to put a scrollview inside another scrollview.
This might be the reason why your table view is not scrolling.... BTW are you talking about horizontal scrollign or vertical scrolling ?
Currently I am using the iCarousel in Table View cell and it scrolls easily.
Just add standard view to cell in Storyboard.
In IB mark the class of that view to iCarousel.
Furthermore !ENABLE! user interaction on that view. (Maybe because of that you can't scroll the content inside the cell)
Implement separate datasource & delegate for every cell. (It is more clear which data are loading in the cell and also the cell itself can handle the data. You just pass the data to cell and it handles it accordingly.) - But it depends on you if you want to let one class to handle two separate control datasources & delegates :-)

iOS 8 Auto cell height - didSelectRowAtIndexPath causes UItableview to jump to top

I'm currently updating an app to iOS8, and am replacing my own cell height calculations. I have a tableview with a bunch of custom cells. Each cell when selected will present/push a new view onto the navigationController. When the tableview is populated with these cells, and the user selects one near the bottom of the table, the tableview jumps to the top right before the new view is presented. This is very distracting to the user. I'm trying using self sizing cells introduced in iOS 8 here (in the viewDidLoad):
self.tableView.estimatedRowHeight = 60.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
Here's the code for when a cell is selected
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController *selectedViewController = [[UIStoryboard storyboardWithName:#"Trip" bundle:nil] instantiateViewControllerWithIdentifier:#"TripDetail"];
DetailViewController *destViewController = (id)selectedViewController;
[destViewController setData:self.dataStore];
[self.navigationController pushViewController:selectedViewController animated:YES];
}
Does anyone know why this is happening? And how I can make it stop?
It's a known issue. The tableView is calling its delegate to get an estimated height for the rows, which is causing the table to scroll.
You can wait to see if it's fixed in the next update, or implement tableView:estimatedHeightForRowAtIndexPath: (as a workaround for now) and return a cached height. Since the estimate will be the actual height, the table won't jump.
This happen's when the table delegate was tapped "didSelectRowAtIndexPath:"
because the delegate method "numbersOfSectionsInTableView" && "numbersOfRowsInSection" will get called. its like reloading the table.
You can fix that jumping state with this method "heightForRowAtIndexPath:" however you'll have to disregard your auto sizing.

Is it possible to have a fixed uitableview Header while using sections?

This question should not be mixed up with this here.. These are two different things.
There is a good example how to use a UITableView Header on SO.
This all works fine and the main header is fixed on top as long as the style is set to plain.
But if I use sections, the main header no longer sticks to top and moves away while scrolling to the bottom.
In this method, I am returning the header for each section.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
In this method I am setting the height for the header section above:
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
In this method, I am setting the real table header.
- (void)viewWillAppear:(BOOL)animated {
...
self.recordTableView.tableHeaderView = headerView;
}
Is it even possible having a fixed table header, while using sections?
What is an alternative solution to this please?
If you want a UITableViewController (static cells/keyboard handling) and have a fixed header then you should use Containment. You can do this from a Storyboard by setting up a UIViewController with your fixed header and then using a Container View to embed the UITableViewController.
Once you have your containing view setup, you right-click drag from the Container View to the View Controller you want to embed - the UITableViewController in this case.
You can access and get a reference to the contained View Controller (the UITableViewController) from the Container View Controller by implementing the prepareForSegue:sender: method.
There’s no way to maintain the header of a tableView fixed, but
an useful approach when you need a unique header, is to use a UIViewController rather than a UITableViewController, and set the header (UIView) out from the tableView.
Something like this:
If you want to keep the class as a UITableViewController you can add your header as a subview to the tableview's superview. You will have to also push the tableview top inset down so your headerview doesnt hide the table.
Here is a sample code to put inside your tableViewController subclass (This example assumes your tableview controller is inside a navigation controller, so it pushes the view to below the navigation bar):
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.automaticallyAdjustsScrollViewInsets = NO;
}
-(void)addHeaderView{
CGFloat yPosition = self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height;
mainHeaderView = [[UIView alloc] init];
const CGFloat mainHeaderHeight = 44;
[mainHeaderView setFrame:CGRectMake(0, yPosition, self.view.frame.size.width, mainHeaderHeight)];
mainHeaderView.backgroundColor = [UIColor redColor];
[self.tableView.superview addSubview:mainHeaderView];
[self.tableView setContentInset:UIEdgeInsetsMake(yPosition + mainHeaderHeight, self.tableView.contentInset.left, self.tableView.contentInset.bottom, self.tableView.contentInset.right)];
}
I haven't done this, but the first thing I would think to try is to place my tableview in a UIView and make my own header there in that UIView. Seems a trivial matter to make that view appear to be the header of the table and it would certainly stay put.

Why is my UILabel in a UIView in a UITableCellView not updating after a correct database call, (it seems cell reuse related)?

I have a UITableview cell that gets a tally from a core data database. The tallyTable is in a view controller inside a UITab view. I have an NSLog statement that prints out the tally value whenever it gets updated. Another tab has a list to change the source (different day) for the tallies. I am using iOS5 with ARC targeting iOS 4.2.
Here's the problem. When I load the application, the correct tallies for whatever the last selected day show up in the table tab. If I then go to the day tab and change the day and return to the tally tab there is no change in the display. However, the viewWillAppear on the tally tab runs and as the table cycles through cellForIndexPath, my NSLog statement prints out all the correct new values. If I then scroll the top label off the screen and back the label updates to the new value.
I've tried setNeedsLayout and setNeedsDisplay on the UILabel, the UITableViewCell, the UITableView and the view controller loading the table. I tried changing the CellReuse identifier so that it would never reuse a cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
CollectionItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CollectionItemTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.collectionKeys objectAtIndex:row] valueForKey:#"collectionTitle"];
NSInteger test1 = indexPath.row + 150;
NSLog(#"tag = %i", test1);
cell.tallyButton.tag = test1;
NSNumber * questionID = [[self.collectionKeys objectAtIndex:row] valueForKey:#"answerID"];
cell.tallyLabel.text = [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]];
NSLog(#"Collection text should be = %#", [NSString stringWithFormat:#"%i",[self updatePointTotal:questionID]]);
[cell setNeedsLayout];
return cell;
}
I've read over a half dozen other similar questions. Got about three hours invested so far in trying to solve this.
EDIT: I thought I fixed it by using the navigation controller to repush the top level view controller on to the view again. I'll admit now this feels like a classically kludgy hack in every way. When the view is PUSHED everything updates and it is seamless. However, in order to have a fixed footer to make selection settings for the table buttons, I used a UIView with two subviews, a UITableView on top and a simple UIView with four buttons below.
The captions on the buttons need to change with the data source. Now when the view controller is pushed onto the view it obscures my fixed footer view. So, I inserted the fixed footer into the UITableview and everything appeared fine until I scrolled the UITableView and the footer scrolled up with it. The table is basically a tally sheet with buttons next to each item and in the footer is four buttons to note the color of the tallied item. Say the next item was a green lego, you would tap "green" in the footer and the button next to "lego" in the table. When I push the view controller with the two subviews the UITableview labels do not update. Thus the tableview needs to be pushed itself (as far as I can tell).
ANSWER: see comment below but ultimately I needed to reload both the visible UITableView data and the delegate UITableView controller data behind it.
I'll give it a shot. First, are you using ARC? If not, you need to add autorelease when you alloc/init a new cell. Otherwise, it's fine as is.
If I'm understanding your question correctly:
The tableView displays the correct data at app launch
You switch away from the tab with the tableView and change the tableView dataSource
You switch back to the tab with the tableView and you see (via NSLog) that the table cells are reloaded with the correct data yet the old data is still visible in the cells
If you scroll a cell off the display and back forcing it to refresh it contains the correct data
Some thoughts:
the tableView will not reload itself automatically when it's view appears. You need to call [tableView reloadData] whenever the dataSource changes. This is independent of whether the tableView is currently displayed or not. My guess is this alone will solve your problem.
You don't need to call setNeedsLayout on the cell unless you want the cell to relayout its subviews based on the data. You also don't need setNeedsDisplay.
I'm assuming there aren't other complicating factors (such as multiple tableViews displaying the same data) that could confuse things.
If you use prepare for reuse method, remember to over the original method with [super prepareForReuse];
Another method if the above way does not work is re setup cell as describe here.
I use the same method i applied for some of my collection view : we should remove/reset your subview where you create/add it to cell 's content. That mean we need set up data each cell completely for each row.
I move the code reset data value from prepare reuse to where i set value and I worked simply !
In my CustomCell.m :
- (void)configCellWith:(id)item At:(NSUInteger)row {
if (_scrollView) {
[[_scrollView subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
_scrollView = nil;
[_scrollView removeFromSuperview];
}
else {
CGFloat y = labelHeight+15;
float scrollHeight = _imgArray.count*200;
_scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(10, y,SCREEN_WIDTH-20, scrollHeight)];
_scrollView.scrollEnabled=YES;
_scrollView.userInteractionEnabled=YES;
_scrollView.layer.masksToBounds = YES;
[self.contentView addSubview:_scrollView]; } }
Remember to change your data source appropriately too.

Resources