Force a UITableViewCell last cell to the top of the view - objective-c

We have a UITableViewCell with a list of rows that work like an accordion list.
When a user clicks on an accordion tableview cell, it will expand the tableview and is meant to push the cell right to the top, regardless of which one it is.
We use:
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES]
This will scroll a cell to the top, and it works for the first few cells, but the closer you get to the bottom the less likely a UITableViewCell will bubble up to the top of the view.
The very last 2 or 3 cells will not go to the top of the tableview.
I believe this is a content inset issue and have tried;
myTableView.contentOffset = CGPointZero;
I have also tried
[tableView scrollRectToVisible:CGRectMake(0, 0, tappedCell.bounds.size.width, tappedCell.bounds.size.height) animated:YES];
But these do not make the bottom few cells bubble to the top.
I am wondering, is it possible to force a given UITableViewCell to the top of the tableview, and make sure the content offset forces padding underneath it to ensure it has the padding to force it to fill the entire tableview area.
Thanks now.

UITableView's content height equals to total height of all the cells it contains. UITableView inherits UIScrollView and scrolling is limited by its content size. You can try to set table's content size explicitly via it's contentSize property, e.g:
tableView.contentSize = CGSizeMake(tableView.frame.size.width, cellsCount * cellHeight + someNumber);).
If that doesn't help then you can change table's contentInset, e.g:
tableView.contentInset = UIEdgeInset(0, 0, someNumber, 0);

Related

How to center a cell with the content offset in a UICollectionView with scrollToItemAtIndexPath

I am implementing a UICollectionView which shows only a single line of cells. It is like an image cover flow. This means I have subclassed UICollectionViewFlowLayout. My implementation works fine when I use my finger for scrolling, meaning that the following delegate method is called and I center the cell;
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
However when the view loads I want the view to automatically scroll to a cell. For this automatic scroll I use the following;
[self.CollectionView scrollToItemAtIndexPath:_selectedIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
The problem is that targetContentOffsetForProposedContentOffset is not called and thus when the automatic scroll is complete the cell is off the centre.
So how can I programmatically scroll my collection view so that it will also centre on the cell being scrolled to?
Solved this issue myself.
According to the book "iOS UICollectionView The Complete Guide" (Listing 6.7) scrollToItemAtIndexPath: cannot be used in this cover flow type layout as it will not centre the cell.
I have posted below the way it is suggested in the book. Based on the indexPath you want to have you need to calculate the offset of the collection view yourself, and then use the targetContentOffsetForProposedContentOffset: to automatically centre it for you.
CGPoint proposedOffset = CGPointMake(0, 0);
proposedOffset.x = _selectedIndexPath.item * (flow.itemSize.width + flow.minimumLineSpacing);
CGPoint contentOffset = [flow targetContentOffsetForProposedContentOffset:proposedOffset withScrollingVelocity:CGPointMake(0, 0)];
[self.statCollectionView setContentOffset:contentOffset animated:YES];

Accessory View Is Showing Up Half Off of the Cell

I cant figure out how to get my accessory view to fit into my cell. Also, When I add a subview it adds it to the right of the first subview added. I want the sub views to be added from right to left.
I have this for my accessory view
UIView *myAccessoryView = [[UIView alloc] initWithFrame:cell.accessoryView.frame];
And anytime I add a sub view I just write this
[myAccessoryView addSubview:greenCircle];
And as soon as it adds another subview it is placed to the right of the previous sub view which is even further off my cell. How do I reverse the way it adds subview? How can I format the accessory view to stay on the cell?
You are trying to init myAccessoryView with the frame of accessoryView that doesn't yet exist. It will be created after cell creation (and adding to tableView) if you specify cell.accessoryType property, or if you create and set accessoryView yourself like:
[cell setAccessoryView:myAccessoryView];
So if You do this:
UIView *myAccessoryView = [[UIView alloc] initWithFrame:cell.accessoryView.frame];
[cell setAccessoryView:myAccessoryView];
You will have accessoryView with zero size and coordinates. After the cell is set to tableView, accessoryView will get standart origin point in the right side of the cell. But it still have zero size. And all subviews You add to accessoryView will be set to that origin point.
Method "addSubview" cant change subviews frame, it just places one view to another view.
Have no ideas why new subviews are placed to the rigtht of the previous.
To put your subviews to the right place, You have to set their frames manually. For example:
UIView *greenCircle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[myAccessoryView addSubview:greenCircle];
Hope that helps.

UITableView accessory added to additional cells when added to index 0

I'm having a hard time understanding some of the logic behind the UITableView. I am populating my table from a MPMediaItemCollection as a queue of songs. What I am trying to achieve is to have a now playing indicator as the accessory view of the cell at the index path that matches the currently playing song.
I originally tried this with the following:
if (indexPath.row == [mutArray indexOfObject:[mainViewController.musicPlayer.nowPlayingItem valueForProperty:MPMediaItemPropertyTitle]]) {
UIImageView *playButtonView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"PlayButton.png"]];
[cell setAccessoryView:playButtonView];
}
This works fine for the now playing item, which is always actually objectAtIndex:0. But what I don't understand is why my table seems to define this index once every height of combined visible cells.
Let me try to explain this more clearly. Lets say that my table is 600px tall, and its content height is 1800px. This causes the indicator to be added roughly every 600px down the content height.
Now my first thought was that this was something wrong with the code for judging the index based off the name of the song, so I tried changing it to:
if (indexPath.row == 0)
But this produces the same result!
This screenshot should help explain what I'm talking about.
So, is there anything I can do to make the table treat indexPath0 as only the first cell in reference to the entire table instead of in reference to the currently visible cells?
You have to state explicitly also when the accessory should not be there:
if (indexPath.row==0) {
UIImageView *playButtonView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"PlayButton.png"]];
[cell setAccessoryView:playButtonView];
}
else {
[cell setAccessoryView:nil];
}
The reason is that when cell 0 gets dequeued (i.e. reused) on a different row it still has the accessory view in it.
Actually, this is a nice case study for understanding how dequeueing table view cells actually works ;-).
That's how tableview reuse cells: when cell scrolls out of screen it's added to reuse pool, so once you've added your accessory view to cell and that cell is reused - you'll see it in random places while scrolling.
You can check your cells index in -willDisplayCell:forIndexPath and add (if it's not added), hide (if it's there, but not your desired index) or show (if it's there and it's your index), or add accessory view to all cells and show/hide as needed.

UITableViewCell Align all subviews

I have a custom UITableViewCell which has some subviews. i.e. some labels, some images. I want all these subviews to be right aligned in the UITable. How do i do that?
I have tried these approaches -
1.In InterfaceBuilder when I select the UITableViewCell, I can set the "indentaion" section. It's by default 0, I made it 100 but I see no change in the device.
2.I have tried this in the code too. Override the default method...
(NSInteger)tableView:(UITableView *)tableView
indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}
The above code also does not work. How do I align all my subviews in my UITableViewCell to right?
Basically, I want to display one cell left aligned (which is default) & some cells right aligned. As shown in the picture.
There is automatic way everything will align to right. You will have to lay the view appropriately. For UITextField and UILabel objects you can set the textAlignment property to UITextAlignmentRight.
label.textAlignment = UITextAlignmentRight;
If necessary you must also adjust the autoresizingMask of the views to set it such that it has a UIViewAutoresizingFlexibleLeftMargin mask set so that they stick to the right on view resize.
use interface builder for alignment.

How to position view relative to parent?

I have a UIViewController with an MKMapView in it. In viewDidLoad of this controller, I add the MKMapView:
[self.view addSubview:mapView];
I want to display this map in a tableview cell. In the tableview controller's cellForRowAtIndexPath:, I do this:
[cell addSubview:mapView.view];
where cell is a UITableViewCell. I've set the mapview frame to
mapView.frame = CGRectMake(0, 0, 200, 100);
The mapview appears to the bottom left of the cell. Meaning, it is partially in the cell and also out of it. The map overlaps much of the cell but I want it to fill the cell and be bounded by it. How can that be done?
There isn't an associated xib for these controllers.
--- EDIT ------
The tableview is styled as grouped. It looks as though I just need to do some trial and error offsetting to get the map matched up correctly.
did you try setting the clipbounds property on the mapview?