How to add an image in UITableView's content view while we reodering cells? - objective-c

I have a tableview where I provide the option to reoder the cells. But, I don't want to show the delete icon when the user doing rearranging cells. So I did like this to remove the delete button.
In normal mode..
After edit mode (That is, non deletable but rearrangable mode)..
Here, two things are happening. One is the accessoryview of each cell has a image(that represents rearrangement). Second thing is, all strings are moved some points from the left screen. This gap is actually for the deletion symbol. Since I hide the delete button, an empty space appears.
Ok, here is the problem comes. I now want to add some custom button with an image in each cell's content view.
So, I added the following code in my tableView: cellForRowAtIndexPath:
if (isEditable)
{
selectionButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *img = [UIImage imageNamed:#"blue_button.png"];
selectionButton.frame = CGRectMake(-25, 10, img.size.width, img.size.height);
[selectionButton setBackgroundImage:img forState:UIControlStateNormal];
[selectionButton addTarget:self action:#selector(buttonClickAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:selectionButton];
}
The blue button was 24*24 pixels.
The reason why I used -25 as "x" value:
If I give a positive value or zero, the button will overlapped with cell text. Below image represents when the x value is 0.
But for x=-25,
What I need:
Since I added the button with negative x value, the whole image width (24 pixels) will be hiden in the x value (25 pixels). So the button action buttonClickAction: was not called. I want to change the image when the user tapping on it(switching between selected/unselected mode).
Is there any way to call the button's action method? Or should I create a custom cell?
Just confused..

Add this to your Table View Controller
- (BOOL) tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
It will remove empty space.

Related

UIButton not clickable after UITableView scrolled

I have a UITableView which is populated with some cells. I have created a UIButton using the following snippet, it is placed next to one of the section headers.
UIButton *addButton = [UIButton buttonWithType:UIButtonTypeCustom];
[addButton addTarget:self action:#selector(addButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[addButton setBackgroundImage:[UIImage imageNamed:#"add.png"] forState:UIControlStateNormal];
addButton.backgroundColor = [UIColor clearColor];
addButton.frame = CGRectMake(270, 150, 29, 29);
The button is placed and works correctly. However, after the view is scrolled (even slightly - like 1 pixel), the button works once and then ceases to respond. When it fails to respond the action for when it is clicked is not triggered and the button doesn't give the 'depressed' shadow. The rest of the application runs as normal and it does not crash.
This seems odd because after I scroll the button is clickable once more before it stops working. The button is used to insert rows into the table, so after it is pressed there is an extra row, possibly this is breaking the bounds or something?
Button pressed function:
- (void)addButtonPressed {
self.addClientTable.editing = YES;
// First figure out how many sections there are
NSInteger lastSectionIndex = [self numberOfSectionsInTableView:self.addClientTable] - 1;
// Then grab the number of rows in the last section
NSInteger lastRowIndex = [self.addClientTable numberOfRowsInSection:lastSectionIndex];
[self.addClientTable insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:lastRowIndex inSection:lastSectionIndex]] withRowAnimation:UITableViewRowAnimationRight];
self.addClientTable.editing = NO;
}
Where addClientTable is the UITableView.
What could cause a UIButton to stop responding to clicks and where in my scenario would this be caused by?
I am almost sure that your problem is that your button is out of it superview, and you are not using the clip subviews option in your view that contains the button, or in one of it superviews.
Set to true all the views property clip subviews and see if it appears your button. (We expect that the button disappear)
If you provide more code I can try to help you to solve this problem.
-
Reading again your question, another probable problem to it is that you have one view in front of your button. You can test it changing the background of your view, or something like that.

Height of UIScrollView get changed?

I am adding UITableView and UIButton in UIScrollView. button is placed below tableview.
Well, when i select any row from table it add a button on that row and every thing is ok till now, but when i click that row second time it remove button added on it but the problem is that along with removing that button it also scroll my table up and button bellow the table reside on its place ie. it leaves gap between table and button.
my table is reloaded every time when a row is clicked.
code for add UIButtonbelow the UITableView
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
mainTable.frame = CGRectMake(mainTable.frame.origin.x, mainTable.frame.origin.y,
mainTable.frame.size.width,
([menuItemsArray count] * 60) + 380);
[scrollView setContentSize:CGSizeMake(320,([menuItemsArray count] * 60) + 80 + 350)];
reserverBtnBottom = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[reserverBtnBottom setFrame:CGRectMake(20.0f,mainTable.frame.size.height,280, 40)];
[reserverBtnBottom addTarget:self action:#selector(reserveBtnAction) forControlEvents:UIControlEventTouchUpInside];
[reserverBtnBottom setBackgroundImage:[UIImage imageNamed:#"normal.png"] forState:UIControlStateNormal];
[reserverBtnBottom setAlpha:1];
[reserverBtnBottom setTitle:#"Reserve this table" forState:UIControlStateNormal];
[reserverBtnBottom setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[scrollView addSubview:reserverBtnBottom];
rest thing goes here
}
What am i missing?
Thanks in advance.
heightForRowAtIndexPath is a bad place for such calculation, as you are changing a single row state this method might be called once to calculate the new height. When it is called the cell still has an old height value, so does the table.
The button position calculation should be moved to layoutSubviews: method of the table and button superview which is a scrollView in your example. The way it should work is that the superview recalculates all the subviews frames once any of them changes it's frame.
Sometimes instead of overriding the layoutSubviews: the frame calculation is handled with the viewController , that's what you were trying to do but you did it in a wrong way. You'll need to find a better place for the frame calculation if you don't want to override scrollView layoutSubviews:.
If you only need the scrollView to add the button below the table, it would be better from my experience to get rid of the scroll view (at least because you do have scroll view in another scroll view which is Never a good practice) and add the button to the table footerView. The footer view is displayed below the table and scrolls together with it.
After long time i resolve my problem. put this code in viewWillAppear instead heightForRowAtIndexPath-
mainTable.frame = CGRectMake(mainTable.frame.origin.x, mainTable.frame.origin.y,
mainTable.frame.size.width,
([menuItemsArray count] * 60) + 380);
[scrollView setContentSize:CGSizeMake(320,([menuItemsArray count] * 60) + 80 + 350)];
and move my reserveBtnBottom to footer of UITableView.
Thanks to A-Live for his great help.

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.

iOS increase edit mode indentation for custom UITableViewCell

I've got a UITableView with the ability to delete the rows using edit mode etc. As standard, when you tap the 'edit' button, you go into edit mode and the content of the cells gets moved to the right. If you do a 'swipe to delete', the cell content stays where it is.
What I want to do is increase the indentation when you enter edit mode. I've tried the UITableView delegate method indentationLevelForRowAtIndexPath but that doesn't seem to work when I'm using a UITableViewCell subclass.
In the end I used the layoutSubviews method in my UITableViewCell subclass. Below is my code:
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect b = [self bounds];
if(self.editing && !self.showingDeleteConfirmation){
b.origin.x = 42;
}
[self.contentView setFrame:b];
}
This indents the cell content further when you enter edit mode and thanks to the "!self.showingDeleteConfirmation", when you do a 'swipe to delete', it doesn't indent it.
However, when you tap the 'edit' button, then tap one of the circle delete buttons, the cell content slides back to the original 0 x axis position. This is because the showingDeleteConfirmation is now set to true.
I've tried to fix this by checking what the current origin.x value is, but every time I check, it's set to 0.
Is there a way I can achieve what I want?

Adding a button (UIButton) to a custom tableview cell drawn with drawRect:

I am currently working a on project where I have lots of custom table view cells. Part of the requirements is that the cells be able to expand if their default size can not hold all of the content. If they need to be able to expand I have to add a UIButton to the cell and when it is tapped redraw it in a bigger view where all the data fits. Currently in draw rect I essentially do this:
if([self needsExpansion]) {
[self addExpansionButton];
}
-(void)addExpansionButton {
self.accessoryButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.accessoryButton setShowsTouchWhenHighlighted:YES];
UIImage *buttonImage = [UIImage imageNamed:#"blue_arrow_collaps_icon.png"];
[self.accessoryButton setFrame:CGRectMake(280, 82, buttonImage.size.width, buttonImage.size.height)];
[self.accessoryButton setImage:buttonImage forState:UIControlStateNormal];
[self.accessoryButton addTarget:self action:#selector(toggleExpanded) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.accessoryButton];
}
This works fine, except for when I click anywhere else in the cell the button flickers and disappears. Anyone know how to propertly do this?
From the UITableViewCell Class Reference:
You have two ways of extending the
standard UITableViewCell object beyond
the given styles. To create cells with
multiple, variously formatted and
sized strings and images for content,
you can get the cell's content view
(through its contentView property) and
add subviews to it.
Instead of adding the accessory button as a subview of the UITableViewCell, you should add it as a subview of the contentView:
[[self contentView] addSubview:self.accessoryButton];
Have you worked out the following problem in your design approach?: Let's say one of your cells (let's call it A) determines it needs expansion, so you add a button to it. What happens when the user scrolls through the UITableView? For performance reasons, your UITableView delegate should be using dequeueReusableCellWithIdentifier in tableView:cellForRowAtIndexPath:. So you'll be reusing A to display a different row of the table. Do you really want A to have an accessory button? Probably not, since it's now representing a different object.
You're probably better off doing the cell customization at the UITextViewDelegate. In tableView:cellForRowAtIndexPath:, you can determine if the object being displayed at the row specified needs a button, and if it does add it as a subview to the contentView.
Then again, if your table size is always relatively small (say < 50), you can use this approach Jeremy Hunt Schoenherr suggests.