Can not get uitoolbar in expandable cell to hide - iphone

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];
}

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.

iOS 6: UITableView Edit and Autoresizing

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];

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!

When click on button (button in cell) that particular cell should be changed?

There are 1 table on uiview and I want to change the cell height when button pressed other cell's height remain same
Pass the button press event to the view controller through delegate methods and reload the table view as follows.
[self.tableView reloadData];
In view controller (ie., datasource for the table view), implement heightForRowAtIndexPath method and return the height as required.
You can change the cell height in the delegate method
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.row == clickedRow)
return newHeitht;
return cellHeight;
}
you can set some condition in button click and reload the tableview using [tableView reloadData]. this function will be called. return a new height for the particular cell.
-(void)buttonClick {
[self.tableview reloadData];
selectedRow = //do something here
}
and in your UITableview Datasource
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
if(indexPath.row == selectedRow)
return selectedRowHeight;
else
return defaultHeight;
}
1) Create a custom UITableViewCell class.
2) Populate you cell however you see fit. I use a 'hydrateWithArray' type function myself.
3) Once the data has been populated, resize and reposition elements using 'sizeToFit' functions to force labels to conform to the size of whatever you put into them. protip: by setting the frame of the label first, and setting the numer of lines to 0... when you fill the text and sizetofit, it will stretch the label vertically only and force the width to stay the same.
4) Create a seperate function (mine is called calculatedHeight) that returns a float and returns the height that you would like the cell to be in the table (based on the repositioned objects from step 3).
- (float)calculatedHeight {
return textLabel.frame.origin.ytextLabel.frame.size.height5;
}
5) In your UITableView class, you'll need to import your tableViewCell class and create a dummy cell object. You're going to use this class to calculate how tall each cell needs to be. Then in the heightOfRowAtIndex method....
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
float height;
if ( !dummyCell ) dummyCell = [[CustomCell alloc] initWithFrame:CGRectMake(0,0,0,0) reuseIdentifier:#"myCell"];
[dummyCell hydrateWithTweet:[tableArray objectAtIndex:indexPath.row]];
height = [dummyCell calculatedHeight];
if ( height == 0 ) height = 50;
return height;
}
This is a pretty simple example so you may need to go crazy with the error checking in your particular use, but this should at least point you in the right direction. Enjoy!
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (isSearching && indexPath.row == selectedIndex) {
return 110;
}
else {
return rowHeight;
}
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:toReloadRows withRowAnimation: UITableViewRowAnimationNone];
[self.tableView endUpdates];
then
[self.tableView beginUpdates];
[self.tableView endUpdates];

Problem modifying UITableViewCell accessoryType in tableView:didSelectRowAtIndexPath:

I have a transparent table view (UIViewController with subview UIImageView, and another subview UITableView on top of the UIImageView sibling with background = clearColor, UITableViewCells background = clearColor). I also want taps on the cells to toggle the cell's accessoryType between checkmark and none. If I modify the UITableViewCell's accessoryType in tableView:didSelectRowAtIndexPath:, sometimes (30-50% of the time, both on the ios4.1 simulator and on a 3GS iphone running os4.1) when toggling from accessoryType None to accessoryType checkmark the checkmark image is painted against an opaque white background instead of a transparent background. If instead I reload the table (where the accessoryType is also set appropriately for each cell) the transparency works correctly 100% of the time.
Is this a bug? Or is modifying a cell in tableView:didSelectRowAtIndexPath: not the right thing to do, and that row should be reloaded instead? Or is there something else I'm missing?
edit: Here's my didSelectRowAtIndexPath code that shows the undesirable behavior:
edit 2: One more detail of what's happening. It's the very tail end of the deselect animation where the problem happens. The checkmark appears and is displayed properly & transparently while the deselect animation is running and the blue selection is gradually fading out. After the deselect animation finishes and the blue is all gone, maybe 1/10 of a second after the selection color is completely gone, is when the checkmark accessory "automagically" turns opaque with no further user input.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ( self.editing )
{
}
else
{
[self.myTableView deselectRowAtIndexPath:indexPath animated:YES];
UITableViewCell *cell = [self.myTableView cellForRowAtIndexPath:indexPath];
// toggle the selection status of the selected row
//
NSNumber *rowObj = [NSNumber numberWithUnsignedInt:indexPath.row];
if ( [self.selectedRows containsObject:rowObj] )
{
// currently selected, now de-select
//
cell.accessoryType = UITableViewCellAccessoryNone;
[self.selectedRows removeObject:rowObj];
}
else
{
// currently unselected, now select
//
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.selectedRows addObject:rowObj];
}
}
}
I think it's cleaner if you move the toogle selection piece of code to
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
and on didSelectRowAtIndexPath call to
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
This way you will reload only the selected row as soon as it is selected, and no need for calling reloadData.
Hope this helps!
This post hasn't been updated in 4 months but I figured I would submit my solution as it seems to work and could help somebody else with a similar problem.
Everything happens in the didSelectRowAtIndexPath method. The self.view I call is a tableView (so replace it with your tableView's name, e.g. self.tableView)
// let's go through all the cells to update them as I only want one cell at a time to have the checkmark next to it
for (int i=0; i<[self.detailsArray count]; i++) {
// whenever we reach the cell we have selected, let's change its accessoryType and its colour
if (i == indexPath.row) {
// that's the row we have selected, let's update its
UITableViewCell *cell = [self.view cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
cell.textLabel.textColor = [UIColor colorWithRed:51.0f/255.0f green:102.0f/255.0f blue:153.0f/255.0f alpha:1.0f];
}
// if it isn't the cell we have selected, let's change it back to boring dark colour and no accessoryType
else {
UITableViewCell *cell = [self.view cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.textColor = [UIColor darkTextColor];
}
}
// don't forget to deselect the row
[self.view deselectRowAtIndexPath:indexPath animated:YES];
this UITableViewDelegate method:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
is called right before displaying a cell. Modifying your accessory view there should work.
In debugging another problem in an unrelated project with a custom table row selection animation, I found that if the cell selection style is not UITableViewCellSelectionStyleNone, then any changes to the cell performed in didSelectRowAtIndexPath are subject to glitches and other desirable results (the changes made to cell N do not show up until cell != N is selected later, and animations performed on the cell never show up at all). When I changed the selection style to UITableViewCellSelectionStyleNone, then all visual cell changes made in didSelectRowAtIndexPath show up right away without problems.