matrix of buttons - iphone

I have a matrix of buttons, 4x3
And i have the following problems, or let's say i don't know where to begin
they are inited with a label from an array and they call the same function -(IBAction)buttonPressed:(id)sender
Buttons are made programatically, not sure the function needs IBAction. How do i detect in this function what button was pressed? i thought at something like sender.label but is not working. Here's how i call it:
[playButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
How do i detect the touch? i want to display an uiView somewhere when i touch a button, not when i release it.
What to use to create a mask with rounded corners over this buttons? The buttons stay on a rounded rectangle but the buttons itself are squared, so they look ugly in the corners of the matrix.

You can assign each button unique tag, e.g.
myNewButton.tag = myNewTag;
++myNewTag;
then in your IBAction method you can get sender's tag (via (UIButton*)sender.tag) and proceed accordingly.
there's UIControlEventTouchDown event. (you can see the complete event list in UIControl class reference in Control events section)
I usually just use images with rounded corners for buttons when needed (and set button type to custom)

Related

How to make UIButton respond only to touch, not drag

Take a look at this method:
[textButton addTarget:self action:#selector(articleModalWillAppear:) forControlEvents:UIControlEventTouchDown];
When the button is touched, it calls articleModalWillAppear:. That works well. The problem is the button also calls the action when it is dragged. (The button is big and contains a text paragraph)
I put six such buttons as subviews of UIScrollView (with UIPageControl). It works well when dragging UIScrollView horizontally. But it pops up modal views when dragging vertically because when a finger dragging across a button, the button considers it as a touch, and the touch calls articleModalWillAppear:.
If you still don't understand my problem, think about the New York Times iPad app. You can drag the pages horizontally. You can touch an article description to go to the full article view. But nothing happens when you drag vertically inside an article description. How to achieve this?
Use a different event e.g.:
[textButton addTarget:self action:#selector(articleModalWillAppear:) forControlEvents:UIControlEventTouchUpInside];
UIControlEventTouchUpInside is the most generally used in this case.
use forControlEvents:UIControlEventTouchUpInside
That only registers a click event when a user touches down inside the button and then touches up in the same button, and ignores drags.

several uibuttons to subclass

I have several custom uibuttons on my view. I want to create a toggle button which when pressed, it will loop through all the UIButtons and enable a background image for them.
What I have done is to use an image as a background, then created clickable parts of it using blank custom buttons. I want this toggle function to then show the buttons.
My plan is to create a subclassed UIButton for the "hidden" buttons. When the toggle button is pressed, the code should then set the background image for each of these buttons to a "reddot.png". That stays on the screen until the toggle button is pressed again - this then disables each sub classed uibuttons background image.
What's the best way to do this?
I would advise you to not subclass UIButton for two reasons. First, UIButton is actually a class-cluster, which makes subclassing rather difficult. Secondly, I don't think it is needed in your case.
Simply create all the buttons as custom buttons. You can customize their appearance using methods like [button setHidden:] and [button setBackgroundImage:forState:]. The toggle button could then simply by linked to an IBAction, which would apply the appropriate customizations to the other buttons.

slider gallery with touch recognition

HI
i was following this example to create a slider gallery
"http://lievendekeyser.net/index.php?module=messagebox&action=message&msg_id=1351"
But i stuck at one point. what i am trying to do is, when user double tap on current image, it should navigate to another view, like to view B.
But i am not able to navigate and detect double tap on current image.
suggestions needed.
regards
you can find the number of tap in touch event. and when count of tap == 2 then you should write code for further movements.
else put all these images in UIButton and provide the IBActions to all the buttons and perform the action.
use following code
[ScrollViewFavButton addTarget:self action:#selector(FavClickButton:) forControlEvents:UIControlEventTouchUpInside];
ScrollViewFavButton.tag = i;
[ScrlViewFavorite insertSubview:ScrollViewFavButton atIndex:i];
insert button in the scrollview and perform action in FacClickButton:.
I think now you'll get your answer.

iphone - getting the button id in a segmented control

I am trying to create something that uses the idea of the UIPopOverController, I mean, have that speech bubble anchor pointing to the button who triggered the method.
The problem is that I am using a UISegmentedControl...
How do I get the id of the button that was tapped on a UISegmentedControl, so I can determine its position and generate the anchor?
thanks for any help.
Look at SegmentViewController.{h,m} in the UICatalog sample project.
The sample code sets up the view using code.
This line
[segmentedControl addTarget:self action:#selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
is where the magic happens.
- (void)segmentAction:(id)sender
{
//NSLog(#"segmentAction: selected segment = %d", [sender selectedSegmentIndex]);
}
You can also do this in Interface Builder
Assuming that you have (IBAction)segmentAction:(id)sender declared in your ViewController and that the Files Owner is your ViewController, right-click on the UISegmentedControl and make the connection between the UIControlEventValueChanged event to the Files Owner segmentAction
UISegmentedControl acts like a "single" button. It is a single object placed in a single frame unlike the toolbar items which are an array of objects placed in their own frames. A typical usage pattern is to dispatch a message inside a switch statement in your segmentAction method.
I see two options.
Option A: Implement a custom view that contains an array of UIButton controls. The action for the UITouchUpInside event for the all of the buttons can point to the same method in your controller. Then implement a buttonPressed:(id)sender which you can ask the sender for it's frame and location to use to create your new view on top. --> Complicated
Option B: You can calculate the position of the new subview using an offset calculated from selectedSegmentedIndex, widthForSegmentAtIndex:, and contentOffsetForSegmentAtIndex:. Really not much different than calculating from the bounds of any view. --> Easier

UIButton delayed state change

I have a UIButton subview inside of a UITableViewCell.
When this button is touched, the user must hold the button for about a half second for the button's image to change to the UIControlStateHighlighted image.
This means that if the user just taps the button as is usually the case, the highlighted state is never shown.
Why does this occur and how can I fix it?
I just encountered this problem and saw that this issue hadn't been closed. After screwing around for a while I found a fix for it.
Now you can fix this by turning off delaysContentTouches or unchecking the "Delays content touches" box on the tableview.
The only negative side effect is that the user won't be able to tap down on a button and initiate a scrolling gesture. However, if the user tries to scroll starting from anywhere that doesn't itself accept touches, the behavior should be the same as before.
The problem is that your UIButton is inside a UITableView. This means that the table view has to determine whether your tap is going to be a swipe or if it's just a tap intended for the button. The table view has to delay sending a message to the UIButton until it knows that the user doesn't intend to swipe and therefore scroll the view instead of pressing the button.
If you don't need a table view, get rid of the UITableView.
Up for David Hodge's answer.
I just want to add a way to remove that "only negative side effect", already described by David: if you start scrolling inside a UIcontrol in a UIScrollView with delayContentTouches=NO, scrolling doesn't work.
SOLUTION
Subclass UIScrollView (or UITableView as the original question) and override:
-(BOOL) touchesShouldCancelInContentView:(UIView *)view {
return YES;
}
Your UIControls inside UIScrollView/UITableView will change their state immediately on tap and the scrollviews will be able to scroll even if the touch starts on some UIControl. Works like a charm.
I just change the image from within the target action method:
[sender setBackgroundImage:[UIImage imageNamed:#"highlighted-image.png"] forState:UIControlStateNormal];
It changes the background image instantly.
Edit: completely re-written following a misunderstanding of the question
One way of thinking of a UIButton is as a shorthand way of setting up an area of the screen that can respond to various instantaneous touch events the response it makes is defined by UIControl's Target-Action system for delivering messages to other objects.
UIControlEventTouchDown sounds like the one you need to respond to. It will be triggered as soon as someone touches inside your button - this is what the "Contact Info" button in SMS does.
UIButton* myButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect];
// SEt up title, frame etc
[myButton addTarget:self action:#selector(myButtonWasPressed) forControlEvents: UIControlEventTouchDown];
[myMainView addSubView:myButton];
Will send a -(void)myButtonWasPressed message to the object this code runs from (ideally you view controller). In myButtonWasPressed you can then add a new view or take any action you like. The SMS app pushes a view controller to display the contact info using a navigation controller.
If this still doesn't solve your problem, you're going to have to post some code in order to get more insight into what's going wrong.