Using XCode, I am trying to figure out how to display a different image when someone clicks or presses down on one of my buttons before being taken to a second screen. For example, I have a contact icon on my home screen. When a user clicks the icon, it should change to a darker version on tap before going to the contact screen. Any help is appreciated.
-(IBAction) ButtonPressed :(id)sender
{
UIButton *tempButton = (UIButton *) sender;
int tag = tempButton.tag;
NSString *viewName;
switch (tag)
{
case 1:
[FlurryAnalytics logEvent:#"Contact-Screen"];
viewName = #"ContactScreen";
if( self.appDelegate.sound)
[Click play];
[self.appDelegate moveToView:viewName];
break;
}
}
Simple, you just have to set a different image for the buttons selected state:
[myButton setImage:[UIImage imageNamed:#"mySelectedImage"] forState:UIControlStateSelected];
Or in interface builder:
Additional UIControlState's include:
enum {
UIControlStateNormal = 0,
UIControlStateHighlighted = 1 << 0,
UIControlStateDisabled = 1 << 1,
UIControlStateSelected = 1 << 2,
UIControlStateApplication = 0x00FF0000,
UIControlStateReserved = 0xFF000000
};
The state of a control; a control can have more than one state at a
time. States are recognized differently depending on the control. For
example, a UIButton instance may be configured (using the
setImage:forState: method) to display one image when it is in its
normal state and a different image when it is highlighted.
As far as I've ever noticed in Xcode, whenever you decide to implement a customized button and don't specify a second image for use in the UIControlStateSelected state, Xcode automatically darkens the button for you when the user taps the buttons to show that they were, in fact, tapped.
The 0x7f answer is almost correct (the correct state value is 'Highlighted' and not 'Selected'). For Swift users, it would be
myButton.setBackgroundImage(UIImage(named: "myButtonImagePressed.png"), forState: .Highlighted)
Related
Since there's no UISwitch in tvOS, I'm using a UIButton to implement a simple On/Off toggle. I've set the button title text for UIControlStateNormal and UIControlStateSelected to indicate the button's on/off state, but the new UIControlStateFocused now interferes with this by setting the title text to be the same as the default state whenever the button is in focus. This means that when the button is "On", whenever it gets focus its title changes to "Off".
The only way I've found to get around it is to explicitly set the title for the focused state in the button handler as shown below.
- (void)viewDidLoad
{
[super viewDidLoad];
// in reality these strings are setup in the storyboard
[self.enabledButton setTitle:#"Off" forState:UIControlStateNormal];
[self.enabledButton setTitle:#"On" forState:UIControlStateSelected];
// ensure the text shows up in focused state
[self.enabledButton setTitleColor:[UIColor blackColor] forState:UIControlStateFocused];
}
- (IBAction)toggleStateForEnabledButton:(id)sender
{
UIButton *button = (UIButton *)sender;
button.selected = !button.selected;
if (button.selected)
{
[button setTitle:[button titleForState:UIControlStateSelected] forState:UIControlStateFocused];
}
else
{
[button setTitle:[button titleForState:UIControlStateNormal] forState:UIControlStateFocused];
}
}
This feels very hackish to me, esp. since there might be lot of this going on in UISwitch's absence. Is there a better way?
Have you tried setting a title for UIControlStateFocused | UIControlStateSelected ? It's a bit field, so should be possible to combine them.
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;
}
}
I have programmed a Quiz in Xcode where I've created UIButtons programmatically displaying the answer to a question. When the user clicks the button the next question is loaded and the buttons position i shuffled to not make the right answer in the same place for each question (the right answer is however under the same UIButton for every question.)
This is how I create my buttons:
if (self.buttonRightAnswer == nil)
{
self.buttonRightAnswer = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[self.buttonRightAnswer addTarget:self action:#selector(rightAnswer) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:self.buttonRightAnswer];
}
self.buttonRightAnswer.frame = CGRectMake(20.0, [[randomPositionArray objectAtIndex:0] floatValue], 280.0, 40.0);
[self.buttonRightAnswer setTitle:[[self.quiz.arrayWithQuestions objectAtIndex:questionNr - 1]valueForKey:#"RightAnswer"] forState:UIControlStateNormal];
When the user clicks the right an answer the next question loads. Here it's a problem. The next question loads with the same method only shuffled positions and the animation of the press-down of the button is drawn after the buttons been moved resulting in the user seeing where the right answer is now.
How can I wait for the animation before moving the buttons?
I could solve this by having the buttons stay in one place, shuffling out the questions over the buttons and comparing the users answer with the right answer.. but this requires a hell of a lot more code.
You can use some of shit-code and insert some kind of 'sleep' before next shuffling buttons
Before you create the buttons againg (after a question was answered), you can add something like (if you use differen images for button states)
-(void)waitUntilButtonDeselected
{
bool selected = YES;
while (selected)
{
bool selected = (self.buttonRightAnswer.currentBackgroundImage == UIImageOfNotSelectedButton);
}
}
The idea here is to check if the image of the button corresponds to not selected button.
Typically when using a UIButton, events are triggered on UIControlEventTouchUpInside, or at the end of the touch.
You're triggering it on the touch down which is causing issues with the animation you want to happen.
It might be simpler for you to switch to using UIControlEventTouchUpInside instead of UIControlEventTouchDown since this should solve your problem and be more consistent with other iPhone apps.
I have two PNGs I want to use as a button. How can I animate a UIButton by switching rapidly between these two images?
You can use animationImages property of your button's imageView:
myButton.imageView.animationImages =
[NSArray arrayWithObjects:[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
nil];
myButton.imageView.animationDuration = 0.5; //whatever you want (in seconds)
[myButton.imageView startAnimating];
Your button will switch between your two images.
EDIT: As #tidbeck pointed the button needs to have an image assigned to create the imageview property.
Normally for a button you can set three "live" states:
- Normal
- Highlighted
- Selected
I don't know if this can help, but if you set one image to "Normal" and the other image to "Highlighted" you can see the two images while pushing the button.
I don't know if this effect is enough for you.
This small example shows how to set a UIButton to show an indefinite animation of a heart beating.
I have added 8 images into the Assets.xcassets, and named them like this: heart1, heart2, ..., heart8.
private func showHeartedAnimation() {
var images = [UIImage]()
for i in 1...8 { images.append(UIImage(named: "heart\(i)")!) }
self.heartButton.setImage(UIImage.animatedImage(with: images, duration: 0.2), for: .normal)
}
If you want to disable the animation at some point, just assign a simple UIImage to the same button.
In one of my iPhone projects, I have three views that you can move around by touching and dragging. However, I want to stop the user from moving two views at the same time, by using two fingers. I have therefore tried to experiment with UIView.exclusiveTouch, without any success.
To understand how the property works, I created a brand new project, with the following code in the view controller:
- (void)loadView {
self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
UIButton* a = [UIButton buttonWithType:UIButtonTypeInfoDark];
[a addTarget:self action:#selector(hej:) forControlEvents:UIControlEventTouchUpInside];
a.center = CGPointMake(50, 50);
a.multipleTouchEnabled = YES;
UIButton* b = [UIButton buttonWithType:UIButtonTypeInfoDark];
[b addTarget:self action:#selector(hej:) forControlEvents:UIControlEventTouchUpInside];
b.center = CGPointMake(200, 50);
b.multipleTouchEnabled = YES;
a.exclusiveTouch = YES;
[self.view addSubview:a];
[self.view addSubview:b];
}
- (void)hej:(id)sender
{
NSLog(#"hej: %#", sender);
}
When running this, hej: gets called, with different senders, when pressing any of the buttons - even though one of them has exclusiveTouch set to YES. I've tried commenting the multipleTouchEnabled-lines, to no avail. Can somebody explain to me what I'm missing here?
Thanks,
Eli
From The iPhone OS Programming Guide:
Restricting event delivery to a single view:
By default, a view’s exclusiveTouch property is set to NO. If you set
the property to YES, you mark the view so that, if it is tracking
touches, it is the only view in the window that is tracking touches.
Other views in the window cannot receive those touches. However, a
view that is marked “exclusive touch” does not receive touches that
are associated with other views in the same window. If a finger
contacts an exclusive-touch view, then that touch is delivered only if
that view is the only view tracking a finger in that window. If a
finger touches a non-exclusive view, then that touch is delivered only
if there is not another finger tracking in an exclusive-touch view.
It states that the exclusive touch property does NOT affect touches outside the frame of the view.
To handle this in the past, I use the main view to track ALL TOUCHES on screen instead of letting each subview track touches. The best way is to do:
if(CGRectContainsPoint(thesubviewIcareAbout.frame, theLocationOfTheTouch)){
//the subview has been touched, do what you want
}
I was encountering an issue like this where taps on my UIButtons were getting passed through to a tap gesture recognizer that I had attached to self.view, even though I was setting isExclusiveTouch to true on my UIButtons. Upon reviewing the materials here so far, I decided to put some code in my tap gesture code that checks if the tap location is contained in any UIButton frame and if that frame is also visible on the screen at the same time. If both of those conditions are true, then the UIButton will already have handled the tap, and the event triggered in my gesture recognizer can then be ignored as a pass through of the event. My logic allows me to loop over all subviews, checking if they are of type UIButton, and then checking if the tap was in that view and the view is visible.
#objc func singleTapped(tap: UITapGestureRecognizer)
{
anyControlsBreakpoint()
let tapPoint = tap.location(in: self.view)
// Prevent taps inside of buttons from passing through to singleTapped logic
for subview in self.view.subviews
{
if subview is UIButton {
if pointIsInFrameAndThatFrameIsVisible(view: subview, point: tapPoint)
{
return // Completely ignores pass through events that were already handled by a UIButton
}
}
}
Below is the code that checks if point was inside a visible button. Note that I hide my buttons by setting their alpha to zero. If you are using the isHidden property, your logic might need to look for that.
func pointIsInFrameAndThatFrameIsVisible(view : UIView, point : CGPoint) -> Bool
{
return view.frame.contains(point) && view.alpha == 1
}