iOS 6: UITableView Edit and Autoresizing - iphone

Hi Could someone please help me to understand how to layout table cell's components automatically while editing in iOS 6.0? I have set AutoLayout FALSE for UITableViewCell Autosizing option set to top right in Attributes Inspector! Cell's right side imageviews are overlapping by delete buttons. Please refer attached image. Following is the code for this. Is there anyway I can fix this issue?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PlayerCell *cell = (PlayerCell *)[tableView dequeueReusableCellWithIdentifier:#"PlayerCell"];
Player *player = [self.players objectAtIndex:indexPath.row];
cell.nameLabel.text = player.name;
cell.gameLabel.text = player.game;
cell.ratingImageView.image = [self imageForRating:player.rating];
return cell;
}
- (UIImage *)imageForRating:(int)rating
{
switch (rating)
{
case 1: return [UIImage imageNamed:#"1StarSmall.png"];
case 2: return [UIImage imageNamed:#"2StarsSmall.png"];
case 3: return [UIImage imageNamed:#"3StarsSmall.png"];
case 4: return [UIImage imageNamed:#"4StarsSmall.png"];
case 5: return [UIImage imageNamed:#"5StarsSmall.png"];
}
return nil;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.players removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
I have added following delegate methods and it works fine when I swipe the cell.
-(void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
PlayerCell *cell = (PlayerCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.ratingImageView.hidden = YES;
}
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
PlayerCell *cell = (PlayerCell *)[tableView cellForRowAtIndexPath:indexPath];
cell.ratingImageView.hidden = NO;
}
...but this methods doesn't get invoked when I press editButtonItem Button! That's strange! I am missing something. I have added following method that gets invoked when Edit/Done button pressed but there is no way to detect the cell that will be selected for editing!
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
[super setEditing:editing animated:animate];
if(editing)
{
NSLog(#"editMode on");
}
else
{
NSLog(#"Done leave editmode");
}
}
When user clicks left round button, is there anyway to add selector on that button click and get the cell index?

Your ratingImageView uses autoresizing masks to resize and position itself when you are not using AutoLayout. By default this means that the distance to the left and top is fixed and the size won't change.
When you toggle a cell to edit the contentView moved and resizes but your ratingImageView stays fixed to the top and left. You can visualize this by temporarily (for learning purposes) set a background color to the cells contentView and see how it resizes as you edit and delete the cell.
What you want is for your rating view to stay a fixed distance from the right edge instead of the left. You can either change this in InterfaceBuilder (where you do your XIBs or Storyboard) or in code by setting the autoresizingMask property of the ratingImageView.
Go to this tab
Change the autosizing like this
Or do it in code
// in code you specify what should be flexible instead of what should be fixed...
[ratingImageView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];

Related

UITableView loads with cells in the middle of the TableView. Why?

Context
Building for iOS 7
Two UITableViews on a viewcontroller
Using constraints so tableview resize like I'd like for between 3.5inch and 4inch screen sizes.
What I've tried
Read UITableView documentation
Search stackoverflow
tried this code: [self.bottomTableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop animated:NO];
Result
The content in the bottom tableView loads in the middle of the tableview. I can scroll those cells upwards towards the top of the table view, but they "snap" back to the middle. How do I avoid this?
Update
This is how the tableview looks on load. The green background shows all the white space that left on the top half of the bottom table view.
This is the code:
#pragma mark - Table View Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.topTableView) {
return [self.array count];
}
else{
return [self.array count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (tableView == self.topTableView) {
cell.textLabel.text = #"60";
return cell;
}
else{
cell.textLabel.text = #"60";
return cell;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
Everything is fine with your code. It seems to be a bug with Xcode and iOS 7 unless I missed something in the WWDC documentation.
He applies the height of the navbar to the first element in the subviews array. It doesn't matter if the element is actually under the bar, he just blindly applies it. You can change the order in the storyboard, lets say you move the bottom tableview to the top, then the bottom view has the problem.
I see two options.
If you disable "Under Top Bars" on the ViewController everything is fine. Or you move the UILabel to the top. There is nothing he can adjust with the static label. Maybe Xcode 5.0.1 that was released with the Maverics GM will fix that. Still downloading that one. Will try as soon DL is done.

Grouped Style UITableView doesn't clip subviews

I have a design issue with grouped uitableview, I add uiviews to the leftmost side of each cell extending little over the cell bounds and I want them to be clipped. But neither setting clip subviews in IB nor setting clipsToBounds property in code didn't help.
So far I have set clipsToBounds (for both uitableview itself and individual uitabviewcells) in a number of places but none helped:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[cell setClipsToBounds:TRUE];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:defaultIdentifier];
if (cell == nil)
{
cell = [self reuseTableViewCellWithIdentifier:defaultIdentifier withIndexPath:indexPath];
}
...
[cell setClipsToBounds:TRUE];
...
return cell;
}
- (void)viewDidLoad
{
...
[mainTableView setClipsToBounds:TRUE];
}
Is it possible without changing tableview style to plain?
Update: My previous answer was wrong. Here is an answer that actually shows how to do what you're asking.
https://stackoverflow.com/a/401271/350467
.......
Previous Answer
If you're adding views to the cell's contentView (which you should be, unless you have a good reason), you'll want to set cell.contentView.clipsToBounds = YES;

Can not get uitoolbar in expandable cell to hide

Hello I am currently using Simon Lee's wonderful tutorial to expand my cells. Everything is working fine.
My cells are 100px, and when expanded the cell becomes 144px high. In the added 44px I have placed a toolbar with bar buttons. I've gotten the buttons to work but there is one problem.
When the cell is expanded I can tap any of the 100px and the cell closes, however when the cell is closed , tapping on the lower 44px of the cell causes the bar buttons to fulfill their actions. I'm assuming that it's still enabled if when hidden from site.
I have disabled user interaction in storyboard but can not get it to turn on when cell is selected and vice versa! If anyone could point me in the right direction that would work!
Simon said something about doing the following, but I'm not quite sure on where to exactly implement it! I've tried it everywhere!
for(NewsCell *cell in [self.tableView visibleCells]) {
BOOL cellIsSelected = [selectedIndexes objectForKey:indexPath];
[cell.detailToolbar setUserInteractionEnabled:cellIsSelected];
}
And here's some of my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// If our cell is selected, return double height
if([self cellIsSelected:indexPath]) {
return 144.0;
}
// Cell isn't selected so return single height
return 100.0;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Deselect
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
self.tableView.clipsToBounds = YES;
// Store cell 'selected' state keyed on indexPath
NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
[selectedIndexes setObject:selectedIndex forKey:indexPath];
// This is where magic happens...
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
The clipsToBounds for the tableView in the didSelectRowAtIndexPath looks a little strange to me
self.tableView.clipsToBounds = YES;
Did you set the clipoToBounds to YES for your cells?
I figured it out on my own. It turns out that all I had to do was set the user interaction in my cell to off. and switch it on for the selected cell.
for(NewsCell *cell in [self.tableView visibleCells]) {
BOOL cellIsSelected = isSelected;
[cell.detailToolbar setUserInteractionEnabled:cellIsSelected];
}

Enabling & Disabling UI Toolbar in Expanded Cell

I have a cell (videoCell) that when unselected is 100px in height, and when selected expands to 144px. In the expanded 44 pixels I have placed a toolbar (detailToolbar) through storyboard.
Now here is my problem. If user interaction is enabled for the toolbar, the bar buttons work, and to simply close the cell I can just tap any of the original 100px of the cell. However, the problem arises when I'm attempting to expand a cell. If I tap the bottom 44px of the unselected cell, nothing is triggered, but will only respond if the top 56 pixels are selected. I'm assuming that the detailToolbar behind the cell is preventing it from working.
Here's some my code. I'm using Simon Lee's tutorial to expand the cells.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// If our cell is selected, return double height
if([self cellIsSelected:indexPath]) {
return 144.0;
}
// Cell isn't selected so return single height
return 100.0;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Deselect
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
self.tableView.clipsToBounds = YES;
// Store cell 'selected' state keyed on indexPath
NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
[selectedIndexes setObject:selectedIndex forKey:indexPath];
// This is where magic happens...
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
I've answered it myself. I did the following in the Did Select Row method:
for(NewsCell *cell in [self.tableView visibleCells]) {
BOOL cellIsSelected = isSelected;
[cell.detailToolbar setUserInteractionEnabled:cellIsSelected];
}
It worked flawlessly!

Is it possible to configure a UITableView to allow multiple-selection?

For the iPhone, is it possible to configure a UITableView such that it will allow multiple-selection?
I've tried overriding -setSelected:animated: for each UITableViewCell, but trying to fudge the required behavior is tricky as it's difficult to separate the real unselections from the ones where the UITableView thinks I've unselected due to selection of another cell!
Hope someone can help!
Thanks,
Nick.
Following property should work fine if you are developing app for iOS5.0+
self.tableView.allowsMultipleSelection = YES;
The best way to do this would be to a checkmark per selected row.
You can do that by setting the accessoryType on the selected UITableViewCell instances to UITableViewCelAccessoryCheckmark.
To deselect the row, set it back to UITableViewCellAccessoryNone.
To enumerate which cells/rows were selected (say, upon clicking a button), simply iterate over the cells of the table looking for UITableViewCellAccessoryCheckmark. Or, manage some NSSet or the like in your table view delegate in the "did select" delegate methods.
Use the following code to set up the cell accesory types:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if (thisCell.accessoryType == UITableViewCellAccessoryNone) {
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
thisCell.accessoryType = UITableViewCellAccessoryNone;
}
}
- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
//add your own code to set the cell accesory type.
return UITableViewCellAccessoryNone;
}
Jeff Lamarche has a tutorial on how to do this here:
http://iphonedevelopment.blogspot.com/2008/10/table-view-multi-row-edit-mode.html
I've not tried the code but it's been on the back of my mind for a while, knowing the day will come when I need it.
I backported allowsMultipleSelectionDuringEditing and allowsMultipleSelection from iOS5 to older iOS. You can fork it at https://github.com/ud7/UDTableView-allowsMultipleSelection
It's drop in replacement and only thing you need to do is change UITableView to UDTableView (in code or interface builder)
From the HIG:
Table views provide feedback when users select list items. Specifically, when an item can be selected, the
row containing the item highlights briefly when a user selects it to show that the selection has been received.
Then, an immediate action occurs: Either a new view is revealed or the row displays a checkmark to indicate
that the item has been selected. The row never remains highlighted, because table views do not display a
persistent selected state.
You'll need to roll your own multiple selection style, either with something like Mail, or using the checkmark accessory on your cells.
Guys for multiple selection you just need
self.tableView.allowsMultipleSelection = YES;
on viewDidLoad and
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = NO;
// if you don't use custom image tableViewCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
tableViewCell.accessoryView.hidden = YES;
// if you don't use custom image tableViewCell.accessoryType = UITableViewCellAccessoryNone;
}
I was searching for the same issue and the answer of Bhavin Chitroda sovled it for me but with some addition to keep the check mark as it was while scrolling.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ( [array indexOfObject:indexPath] == NSNotFound ) {
[array addObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
[array removeObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
The addition:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
// Your code here
.
.
.
if ( [array indexOfObject:indexPath] == NSNotFound ) {
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
return cell;
}
If you're trying to do something like Mail's multiple-select (to delete mail, for example), then you're probably going to have to manage all the selection yourself. Multiple row selection isn't something that's standard on the iPhone. Mail solves this by using checkmarks to indicate which rows have been selected.
blue highlighted row as an indicator of whether a row is selected is actually discouraged according to the HIG page 121. Checkmarks will do the trick.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
int selectedRow = indexPath.row;
cout << "selected Row: " << selectedRow << endl;
UITableViewCell *indexPathForCell = [tableView cellForRowAtIndexPath:indexPath];
if (indexPathForCell.accessoryType == UITableViewCellAccessoryNone) {
indexPathForCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
indexPathForCell.accessoryType = UITableViewCellAccessoryNone;
}
}
then add your arraying or how ever you wish to store the data of which were selected.
Note: This does not work in iOS 4+. This is a private, undocumented constant. Do not use it.
If you are not planning to submit your app to the App Store, you can invoke multi-row edit mode by implementing the following method in your UITableViewController delegate:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return 3; // Undocumented constant
}
Tested with iOS4.3 - 6.0
-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
if ([controller.searchResultsTableView respondsToSelector:#selector(allowsMultipleSelectionDuringEditing)]) {
controller.searchResultsTableView.allowsMultipleSelectionDuringEditing = YES;
}
else {
controller.searchResultsTableView.allowsSelectionDuringEditing = YES;
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellAccessoryCheckmark;
}