NSButtonCell created programmatically doesn't highlight when clicked - objective-c

I wanted to have a button appear in a table view as the first element on the last row instead of the normal data, so I created a subclass of NSTableView and overwrote the preparedCellAtColumn:row: method to generate the desired behaviour on the last row.
- (NSCell *)preparedCellAtColumn:(NSInteger)column row:(NSInteger)row {
if(row < [self numberOfRows]-1) {
return [super preparedCellAtColumn:column row:row];
} else {
// if we're on the last row, we're going to add the button instead of data
if(column == 0) {
NSButtonCell *button = [[NSButtonCell alloc] initTextCell:self.buttonTitle];
[button setEditable:YES];
[button setSelectable:YES];
[button setBezelStyle:NSTexturedSquareBezelStyle];
[button setGradientType:NSGradientConvexWeak];
[button setButtonType:NSMomentaryPushInButton];
[button setHighlightsBy:NSBackgroundStyleLowered];
[button setAction:#selector(openAddDialog)];
[button setControlView:self];
return button;
} else {
NSTextFieldCell *emptyCell = [[NSTextFieldCell alloc] initTextCell:#""];
[emptyCell setEditable:NO];
[emptyCell setSelectable:NO];
return emptyCell;
}
}
}
Fortunately, the functionality works--the button appears on the last row, and it calls the openAddDialog selector when it is clicked. There are two visual problems, however:
1. The button doesn't highlight (press down) when it's clicked.
2. The table selects the row with the button on it when it is clicked.
I'm still pretty new to Objective C and Cocoa, so I'm not really sure where to look for the solutions to these. Why isn't the button's setHighlighted method getting called when it is clicked? What method is called just before the NSTableView selects a row so I can override it and tell it not to select the last row?
I ended up solving my second question by overriding the selectRowIndexes:byExtendingSelection: function in my table subclass and simply not passing the last row index on to the super function.

I'm pretty sure you have to make the column editable in order to activate a UI element inside of it.
BTW, it's usually a bad idea to put some kind of control at the end of a table, especially one that affects the entire table. Tables should be composed of logical repeating units. Putting something unique in a table causes user confusion and can hide functionality. You most likely want to move the button outside the table itself.

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.

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

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.

iOS how to identify which image (button) is pressed?

I've three randomly generated images( actually UIButton) and when application runs it asks the user to choose one random image among the three(say a.png).after user select the image app will do some thing based on correct image was selected or not.
Now the question is that how can i identify that user select right image? I'm trying to get name of image that user select and then check it, but really no idea how to do that.
I've searched google for this but can't find something useful.
Can anyone help?
Thanks
When you really want to store the name of the image into the button, instead of using the tagproperty, you could set it to the title and hide the titleLabel (apple reference says: Although this property is read-only, its own properties are read/write. Use these properties to configure the appearance of the button label.):
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:#"a.png"] forState:UIControlStateNormal];
button.titleLabel.hidden = true;
[button setTitle:#"a.png" forState:UIControlStateNormal];
then you can access to the imagename with button.currentTitle.
While generating your UIButtons you can fill the tag property.
Then you can check if your sender.tag equals the value you filled in.
When you only want to check if the correct image is selected, you can set only this one to 1 and the other buttons to 0.
To know which button clicked u need to add tag say from 0, 1, 2
[yourButton setTag:0]; //set tag 1 and 2 also to other button
Now add same selector or method to all buttons:
[yourButton setTarget:#selector(buttonClicked:) forState:UIControlTouchUPInside];
// setTarget to other buttons too
method would be this:
-(void)buttonClicked:(id)sender
{
if([sender tag] == 0)
{
//button 1 clicked
}
else if([sender tag] == 1)
{
//button 2 clicked
}
else if([sender tag] == 2)
{
//button 3 clicked
}
}
Well if you are using UIButtons for this purpose, you could set Target Selector on each button and determine the UIButton using their tag values.
There's also one more method to help. But only of you use 'backgroundImage'.This action is should be linked with your buttons:
-(IBAction)photoIconClicked:(id)sender{
if ([sender isKindOfClass:[UIButton class]]){
UIButton *button = (UIButton*)sender;
_currentImage = button.currentBackgroundImage;
}
}

Best way to create dynamic list of links/buttons in iOS5 view controller

I want to create a dynamic set of links/buttons in an iOS5 view controller and am trying to figure out what might be the best way to do this.
For eg:
Item 1
Item 2
Item 3
:
:
Item N
Each of the Items is a link/button that is clickable and will do some action, like load another screen etc based on the link.
I don't know ahead of time how many items there might be so if all the items don't fit on the screen, I need to be able to scroll to view.
My question:
1. What is a better way of doing this? I could just create the labels and buttons dynamically but this seems rather cumbersome and I'm not entirely sure how I would differentiate between the different buttons (essentially I'd need some index to find out which Item was clicked).
2. Alternatively, I was wondering if I can just render this page as HTML and just have links? I've never done this and not sure how I'd associate a button with a link.
Any suggestions?
AK
You can try to use the tag property to store the index value you need when you create the button. Then evaluate it in the button tap handler by accessing using button.tag.
Maybe you can try Cordova for an HTML based approach. I'm not too familiar with it though, so I can't say for sure.
Hope it helps.
(1) You can assign UIButton tag property based on the button index. If any events were to trigger, you could recognize which button the event belongs to by checking the tag.
Sample :
// Initializing some buttons
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.tag = 1;
[button1 addTarget:self
action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
UIButton *button2 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button2.tag = 2;
[button2 addTarget:self
action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
Selector for button events :
- (void)buttonPushed:(id)sender {
...
if ([sender tag] == 1) {
// do something after button1 event
} else if () {
// do something after button2 event
}
...
}
(2) If you choose to do it in HTML, you could check out CMHTMLView

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.