How to disable/enable a UIPanGestureRecognizer with two separate UIBarButtonItems? - ios

I am trying to turn off a UIPanGestureRecognizer with the click of a "Save" button. Then, I am trying to turn back on this UIPanGestureRecognizer with the click of an "Edit" button. I can figure out how to turn them off with the following code like this:
- (IBAction)saveButton:(id)sender {
buttonCount ++;
if (buttonCount > 0) {
for (_buttonField in self.view.subviews) {
_buttonField.gestureRecognizers = nil;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
}
}
}
Yet, I have two problems. First of all, this is turning off all of the gesture recognizers, which I do not want to do. Secondly, I cannot figure out how to turn them back on. For this I have tried the following:
- (IBAction)editButton:(id)sender {
buttonCount ++;
if (buttonCount > 0) {
if ([[UIColor colorWithCGColor:_buttonField.layer.borderColor] isEqual:[UIColor whiteColor]]) {
for (_buttonField in self.view.subviews) {
_buttonField.gestureRecognizers = YES;
}
}
}
}
However, I receive an error on the line of code that is set to YES.
Here is my complete set of code for reference:
#implementation FieldGoalChartViewController
{
}
-(void)viewDidLoad{
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGRect buttonRect = self.buttonField.frame;
CGPoint point = [aTouch locationInView:self.buttonField.superview];
if (!CGRectContainsPoint(buttonRect, point)) {
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_draggedView.layer.borderColor = [UIColor blackColor].CGColor;
for (_buttonField in self.view.subviews) {
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
}
}
}
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateBegan ) {
gesture.view.layer.borderColor = [UIColor whiteColor].CGColor;
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Would you like to delete the selected rep(s)?"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* deleteButton = [UIAlertAction
actionWithTitle:#"Delete"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
for (_buttonField in self.view.subviews) {
if ([[UIColor colorWithCGColor:_buttonField.layer.borderColor] isEqual:[UIColor whiteColor]]) {
[_buttonField removeFromSuperview];
}
}
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:deleteButton];
[alert addAction:cancelButton];
[self presentViewController:alert animated:YES completion:nil];
}
}
- (void)panWasRecognized:(UIPanGestureRecognizer *)panner {
{
panner.view.layer.borderColor = [UIColor whiteColor].CGColor;
_draggedView = panner.view;
CGPoint offset = [panner translationInView:_draggedView.superview];
CGPoint center = _draggedView.center;
_draggedView.center = CGPointMake(center.x + offset.x, center.y + offset.y);
_draggedView.layer.masksToBounds =YES;
_buttonField.layer.borderWidth = 3.0f;
// Reset translation to zero so on the next `panWasRecognized:` message, the
// translation will just be the additional movement of the touch since now.
[panner setTranslation:CGPointZero inView:_draggedView.superview];
}
}
-(void)buttonTouched:(UIButton*)sender forEvent:(id)tap {
NSSet *touches = [tap allTouches];
UITouch *touch = [touches anyObject];
UITouchPhase *phase = touch.phase;
touch.view.layer.borderColor = [UIColor whiteColor
].CGColor;
}
-(void)doubleTapped:(UIButton*)sender forEvent:(id)twoTaps {
NSSet *touches = [twoTaps allTouches];
UITouch *touch = [touches anyObject];
UITouchPhase *phase = touch.phase;
touch.view.layer.borderColor = [UIColor blackColor].CGColor;
}
- (IBAction)saveButton:(id)sender {
buttonCount ++;
if (buttonCount > 0) {
for (_buttonField in self.view.subviews) {
_buttonField.gestureRecognizers = nil;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
}
}
}
- (IBAction)editButton:(id)sender {
buttonCount ++;
if (buttonCount > 0) {
if ([[UIColor colorWithCGColor:_buttonField.layer.borderColor] isEqual:[UIColor whiteColor]]) {
for (_buttonField in self.view.subviews) {
_buttonField.gestureRecognizers = YES;
}
}
}
}
- (IBAction)addRepButton:(UIBarButtonItem *)newRep {
self.labelCounter++;
buttonCount ++;
if (buttonCount > 0 )
{
_buttonField = [[UIButton alloc]initWithFrame:CGRectMake(300, 300, 28, 28)];
[_buttonField setTitle:[NSString stringWithFormat:#"%i", self.labelCounter]forState:UIControlStateNormal];
[_buttonField setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_buttonField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
_buttonField.userInteractionEnabled = YES;
_buttonField.layer.cornerRadius = 14;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_buttonField.layer.borderWidth = 3.0f;
_buttonField.titleLabel.font = [UIFont boldSystemFontOfSize:13];
[_buttonField setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_buttonField.layer.backgroundColor = [UIColor blackColor].CGColor;
_buttonField.layer.masksToBounds = YES;
//Pan gesture declared in button
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panWasRecognized:)];
[_buttonField addGestureRecognizer:panner];
//Long Press gesture declared in button
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[self.buttonField addGestureRecognizer:longPress];
//Touch down inside declared in button
[self.buttonField addTarget:self action:#selector(buttonTouched:forEvent:) forControlEvents:UIControlEventTouchDown];
//Double Tap inside declared in button
[self.buttonField addTarget:self action:#selector(doubleTapped:forEvent:) forControlEvents:UIControlEventTouchDownRepeat];
[self.view addSubview:(_buttonField)];
}
}
#end
I want to know how to specifically turn off the UIPanGestureRecognizer with the click of my "Save" UIBarButton, and then turn the UIPanGestureRecognizer with the click of my "Edit" UIBarButton.

If you added Pan gesture in IB then you can create outlet and use the enabled property on the instance of the gesture to enable and disable the gesture, simple.
panGestureRecognizer.enabled = NO; (or)
panGestureRecognizer.enabled = YES;

Related

How to change border of UIButton if touched outside of UIButton?

Currently I am trying to create a stereotypical "selected" action of an object. That is, when I click on the object, its border changes to a different color, and when I click outside the object, the border changes back to its normal color. I can figure out how to change the border of the object when I touch the inside of the object(in this case, a UIButton) however, I cannot figure out how to change the border of the UIButton back to its original state when I touch outside of the UIButton. Here is my code so far:
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateBegan ) {
gesture.view.layer.borderColor = [UIColor lightGrayColor].CGColor;
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Would you like to delete this rep?"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* deleteButton = [UIAlertAction
actionWithTitle:#"Delete"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[gesture.view removeFromSuperview];
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
gesture.view.layer.borderColor = [UIColor blackColor].CGColor;
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:deleteButton];
[alert addAction:cancelButton];
[self presentViewController:alert animated:YES completion:nil];
}
}
- (void)panWasRecognized:(UIPanGestureRecognizer *)panner {
{
panner.view.layer.borderColor = [UIColor lightGrayColor].CGColor;
_draggedView = panner.view;
CGPoint offset = [panner translationInView:_draggedView.superview];
CGPoint center = _draggedView.center;
_draggedView.center = CGPointMake(center.x + offset.x, center.y + offset.y);
_buttonField.layer.borderWidth = 4.0f;
// Reset translation to zero so on the next `panWasRecognized:` message, the
// translation will just be the additional movement of the touch since now.
[panner setTranslation:CGPointZero inView:_draggedView.superview];
}
}
-(void)buttonTouched:(UIButton*)sender forEvent:(id)tap {
NSSet *touches = [tap allTouches];
UITouch *touch = [touches anyObject];
UITouchPhase *phase = touch.phase;
touch.view.layer.borderColor = [UIColor lightGrayColor].CGColor;
}
-(void)doubleTapped:(UIButton*)sender forEvent:(id)twoTaps {
NSSet *touches = [twoTaps allTouches];
UITouch *touch = [touches anyObject];
UITouchPhase *phase = touch.phase;
touch.view.layer.borderColor = [UIColor blackColor].CGColor;
}
- (IBAction)addRepButton:(UIBarButtonItem *)newRep {
self.labelCounter++;
buttonCount ++;
if (buttonCount > 0 )
{
_buttonField = [[UIButton alloc]initWithFrame:CGRectMake(300, 300, 28, 28)];
[_buttonField setTitle:[NSString stringWithFormat:#"%i", self.labelCounter]forState:UIControlStateNormal];
[_buttonField setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_buttonField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
_buttonField.userInteractionEnabled = YES;
_buttonField.layer.cornerRadius = 14;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_buttonField.layer.borderWidth = 4.0f;
_buttonField.titleLabel.font = [UIFont systemFontOfSize: 18];
[_buttonField setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_buttonField.layer.backgroundColor = [UIColor blackColor].CGColor;
//Pan gesture declared in button
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panWasRecognized:)];
[_buttonField addGestureRecognizer:panner];
//Long Press gesture declared in button
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[self.buttonField addGestureRecognizer:longPress];
//Touch down inside declared in button
[self.buttonField addTarget:self action:#selector(buttonTouched:forEvent:) forControlEvents:UIControlEventTouchDown];
//Double Tap inside declared in button
[self.buttonField addTarget:self action:#selector(doubleTapped:forEvent:) forControlEvents:UIControlEventTouchDownRepeat];
[self.view addSubview:_buttonField];
}
}
#end
I need to find out how to change the border of the UIButton back to normal when touching outside of the UIButton in order to get the true "select/deselect" feel.
It seems like the problem isn't that you can't change the border back as much as it is you can't trigger the action when the user touches outside of the button.
I would suggest approaching this problem from the perspective of Setting the button as unselected anytime the user does not touch that button. There are a couple ways to do that.
One option, if all of your other buttons and touch areas disable that button, you could add the action to deselect that button when any other button is touched.
UISegmentedController is designed to only allow one item to be selected a time so this could be an option as well if your design allows for it.
You could look at all touch events on the screen and for any touch with the state UIGestureRecognizerStateBegan that is outside of your button you could set your button to be unselected.
This would look like this:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGPoint point = [aTouch locationInView:self.myButton.superView];
if (!CGRectContainsPoint(self.myButton, point)) {
// deselect button
}
}
There are definitely more ways to try to solve the problem, but I find these three generally cover most any situation.

Saving Placement of a Draggable Button within the UIView into Core Data

I would like to be able to save the placement of the draggable button within the UIView created by a user on the click of the add button (in the navigation bar )into core data so that when the user saves the data and calls upon it from the tableview cell created by the core data that it is in the same place where the user saved it. I already have my core data set up i just want to know what si the best way to go about this whether I should use NSKeyedArchiver or something else. Here is my code and here are some pictures for better understanding.
Chart .m
#interface ChartViewController ()
#end
#implementation ChartViewController
-(void)viewDidLoad{
[super viewDidLoad];
self.title = #"Chart";
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGRect buttonRect = self.buttonField.frame;
CGPoint point = [aTouch locationInView:self.buttonField.superview];
if (!CGRectContainsPoint(buttonRect, point)) {
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_draggedView.layer.borderColor = [UIColor blackColor].CGColor;
for (_buttonField in self.view.subviews) {
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
}
}
}
- (void)longPress:(UILongPressGestureRecognizer*)gesture {
if ( gesture.state == UIGestureRecognizerStateBegan ) {
gesture.view.layer.borderColor = [UIColor whiteColor].CGColor;
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Would you like to delete the selected rep(s)?"
message:nil
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* deleteButton = [UIAlertAction
actionWithTitle:#"Delete"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
for (_buttonField in self.view.subviews) {
if ([[UIColor colorWithCGColor:_buttonField.layer.borderColor] isEqual:[UIColor whiteColor]]) {
[_buttonField removeFromSuperview];
}
}
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction* cancelButton = [UIAlertAction
actionWithTitle:#"Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:deleteButton];
[alert addAction:cancelButton];
[self presentViewController:alert animated:YES completion:nil];
}
}
- (void)panWasRecognized:(UIPanGestureRecognizer *)panner {
{
panner.view.layer.borderColor = [UIColor whiteColor].CGColor;
_draggedView = panner.view;
CGPoint offset = [panner translationInView:_draggedView.superview];
CGPoint center = _draggedView.center;
_draggedView.center = CGPointMake(center.x + offset.x, center.y + offset.y);
_draggedView.layer.masksToBounds =YES;
_buttonField.layer.borderWidth = 3.0f;
// Reset translation to zero so on the next `panWasRecognized:` message, the
// translation will just be the additional movement of the touch since now.
[panner setTranslation:CGPointZero inView:_draggedView.superview];
}
}
-(void)buttonTouched:(UIButton*)sender forEvent:(id)tap {
NSSet *touches = [tap allTouches];
UITouch *touch = [touches anyObject];
touch.view.layer.borderColor = [UIColor whiteColor
].CGColor;
}
-(void)doubleTapped:(UIButton*)sender forEvent:(id)twoTaps {
NSSet *touches = [twoTaps allTouches];
UITouch *touch = [touches anyObject];
touch.view.layer.borderColor = [UIColor blackColor].CGColor;
}
- (IBAction)saveButton:(UIBarButtonItem*)saveRep {
saveCount ++;
if (saveCount == 1) {
self.title = #"Chart";
for (_buttonField in self.view.subviews) {
_buttonField.userInteractionEnabled = NO;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
saveCount = 0;
}
}
}
- (IBAction)editButton:(UIBarButtonItem*)editRep {
editCount ++;
if (editCount == 1) {
self.title = #"Edit Mode";
for (_buttonField in self.view.subviews) {
_buttonField.userInteractionEnabled = YES;
editCount = 0;
}
}
}
- (IBAction)addRepButton:(UIBarButtonItem *)newRep {
self.labelCounter++;
buttonCount ++;
if (buttonCount > 0 )
{
_buttonField = [[UIButton alloc]initWithFrame:CGRectMake(300, 300, 28, 28)];
[_buttonField setTitle:[NSString stringWithFormat:#"%i", self.labelCounter]forState:UIControlStateNormal];
_buttonField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
_buttonField.userInteractionEnabled = YES;
_buttonField.layer.cornerRadius = 14;
_buttonField.layer.borderColor = [UIColor blackColor].CGColor;
_buttonField.layer.borderWidth = 3.0f;
_buttonField.titleLabel.font = [UIFont boldSystemFontOfSize:13];
[_buttonField setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
_buttonField.layer.backgroundColor = [UIColor blackColor].CGColor;
_buttonField.layer.masksToBounds = YES;
//Pan gesture declared in button
UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panWasRecognized:)];
[_buttonField addGestureRecognizer:panner];
//Long Press gesture declared in button
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[self.buttonField addGestureRecognizer:longPress];
//Touch down inside declared in button
[self.buttonField addTarget:self action:#selector(buttonTouched:forEvent:) forControlEvents:UIControlEventTouchDown];
//Double Tap inside declared in button
[self.buttonField addTarget:self action:#selector(doubleTapped:forEvent:) forControlEvents:UIControlEventTouchDownRepeat];
[self.view addSubview:(_buttonField)];
}
}
- (void) saveData {
NSMutableDictionary *dataDict = [[NSMutableDictionary alloc] initWithCapacity:3];
if (_buttonField != nil) {
[dataDict setObject:_buttonField forKey:#"placement"]; // save the placement array
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:#"Rep"];
[NSKeyedArchiver archiveRootObject:dataDict toFile:filePath];
}
Picture of ViewController
When the user presses done I want to save it from there into the core data. Thank you!!
For CGRect there is also an easy way out by using a string which is already a standard data type in Core Data.
// Swift and Objective-C
object.rect = NSStringFromCGRect(frame)
view.frame = CGRectFromString(object.rect)
While NSValue is also a good option, this is also eminently readable.
In your data model add a transformable called something like boundingRect. Then when your user finishes dragging the button say something like:
managedObject.boundingRect = [NSValue valueWithCGRect:button.frame];
Then when you want to read it out of the database say:
UIButton *button = [[UIButton alloc]initWithFrame: [managedObject.boundingRect CGRectValue]];

Converting Pan UIGesture to a Swipe Gesture

When the user pans their finger over the specific cell, the cell changes color depending on the x-axis of the user. How would I go about changing from a pan gesture to a swipe. I would like to build it so that instead of panning, swiping on the cell reveals the color behind it. The cell should then snap back into place when the user lifts their finger. Any tips?
#synthesize _panRecognizer;
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if (self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier])
{
NSInteger emoteY = floor((self.frame.size.height - 32) / 2);
_panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(respondToPanGesture:)];
[_panRecognizer setDelegate:self];
[_panRecognizer setMinimumNumberOfTouches:1];
[_panRecognizer setMaximumNumberOfTouches:1];
[self addGestureRecognizer:_panRecognizer];
// [[self textLabel] setFont:[UIFont boldSystemFontOfSize:18.0]];
[[self textLabel] setFont:[UIFont systemFontOfSize:24.0]];
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
_border = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, self.frame.size.height)];
[self addSubview:_border];
_rightEmote = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 42, emoteY, 32, 32)];
[self addSubview:_rightEmote];
_leftEmote = [[UIImageView alloc] initWithFrame:CGRectMake(-32, emoteY, 32, 32)];
[self addSubview:_leftEmote];
}
return self;
}
- (void)setFrame:(CGRect)frame
{
[super setFrame:frame];
CGRect borderFrame = _border.frame,
rightEmoteFrame = _rightEmote.frame,
leftEmoteFrame = _leftEmote.frame;
NSInteger emoteY = floor((self.frame.size.height - 32) / 2);
borderFrame.size.height = self.frame.size.height;
rightEmoteFrame.origin.y = emoteY;
leftEmoteFrame.origin.y = emoteY;
[_border setFrame:borderFrame];
[_rightEmote setFrame:rightEmoteFrame];
[_leftEmote setFrame:leftEmoteFrame];
}
- (DDFactor *)factor
{
return _factor;
}
- (void)setFactor:(DDFactor *)factor
{
_factor = factor;
}
- (void)respondToPanGesture:(UIGestureRecognizer *)recognizer
{
// NSLog(#"%lu", [recognizer state]);
NSInteger rstate = [recognizer state];
CGFloat touchX = 0.0;
if ([recognizer numberOfTouches] == 1)
{
touchX = [recognizer locationOfTouch:0 inView:self].x;
if (rstate == UIGestureRecognizerStateBegan)
{
/*
animate to color under touch
*/
CGRect labelFrame = [self textLabel].frame;
labelFrame.origin.x += 42;
CGRect rightEmoteFrame = _rightEmote.frame;
rightEmoteFrame.origin.x += 42;
CGRect leftEmoteFrame = _leftEmote.frame;
leftEmoteFrame.origin.x += 42;
[UIView animateWithDuration:0.3 animations:^{
[_border setAlpha:0.0];
[[self textLabel] setTextColor:[UIColor whiteColor]];
[[self textLabel] setFrame:labelFrame];
[_rightEmote setFrame:rightEmoteFrame];
[_leftEmote setFrame:leftEmoteFrame];
}];
[self animateEmoticonsWithColor:NO duration:0.3];
}
else if (rstate == UIGestureRecognizerStateChanged)
{
/*
alter color
trigger emote animation if necessary
*/
if ([self responseForTouchPosition:touchX] != _responseValue)
{
[self setResponseValue:[self responseForTouchPosition:touchX]];
[_border setBackgroundColor:[UIColor colorForResponse:_responseValue]];
[self animateToBackgroundColor:[UIColor colorForResponse:_responseValue]];
[self animateEmoticonsWithColor:NO duration:0.2];
}
}
}
else if (([recognizer numberOfTouches] == 0) && (rstate == 3))
{
CGRect labelFrame = [self textLabel].frame;
labelFrame.origin.x -= 42;
CGRect rightEmoteFrame = _rightEmote.frame;
rightEmoteFrame.origin.x -= 42;
CGRect leftEmoteFrame = _leftEmote.frame;
leftEmoteFrame.origin.x -= 42;
[UIView animateWithDuration:0.3 animations:^{
[_border setAlpha:1.0];
[_rightEmote setFrame:rightEmoteFrame];
[_leftEmote setFrame:leftEmoteFrame];
[[self textLabel] setFrame:labelFrame];
[[self textLabel] setTextColor:[UIColor colorForResponse:_responseValue]];
[self setBackgroundColor:[[UIColor colorForResponse:_responseValue] colorWithAlphaComponent:0.1]];
}];
[self animateEmoticonsWithColor:YES duration:0.3];
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (DDResponseValue)responseForTouchPosition:(CGFloat)x
{
DDResponseValue response;
if (x <= 70) response = DDResponseGrin;
else if (x <= 120) response = DDResponseSmile;
else if (x <= 170) response = DDResponseSad;
else if (x <= 220) response = DDResponseNervous;
else if (x <= 270) response = DDResponseRefusal;
else response = DDResponseNeutral;
return response;
}
You can use the UISwipeGestureRecognizer state and can do as what you want. Have a look on the following code,
- (void)swipeGestureMethod:(UISwipeGestureRecognizer *)recognizer {
CGPoint point = [recognizer locationInView:[recognizer view]];
if (recognizer.state == UIGestureRecognizerStateBegan) {
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
}
}

Imitating button click with UIGestureRecognized

Having added a UITapGestureRecognized to a UIView, how do I parse the view for ie. changing the background color during the tap? The purpose of this is to imitate a button click.
UIView *locationView = [[UIView alloc] init];
locationView.tag = 11;
locationView.backgroundColor = [UIColor clearColor];
locationView.userInteractionEnabled = YES;
[locationView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(promptForLocation)]];
Let's say I want locationView.backgroundColor = [UIColor blueColor] right after the tap gesture. Would you just implement it in the target action or is there a specific implementation for this?
Update:
This is my final code inspired by #0x7fffffff
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDetectedLocation:)];
longPress.allowableMovement = 50.0f;
longPress.minimumPressDuration = 0.05;
UILongPressGestureRecognizer *longPress2 = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDetectedPhoto:)];
longPress2.allowableMovement = 50.0f;
longPress2.minimumPressDuration = 0.05;
[leftView addGestureRecognizer:longPress];
[rightView addGestureRecognizer:longPress2];
// ...
}
- (BOOL)longPressDetected:(UILongPressGestureRecognizer *)sender {
if ([self.view hasFirstResponder]) {
return NO;
}
if (sender.state == UIGestureRecognizerStateBegan) {
[sender.view setBackgroundColor:[UIColor colorWithRed:(4/255.0) green:(129/255.0) blue:(241/255.0) alpha:1]];
} else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed) {
[sender.view setBackgroundColor:[UIColor clearColor]];
}
CGPoint location = [sender locationInView:sender.view];
return sender.state == UIGestureRecognizerStateEnded && location.x > 0 && location.x < sender.view.frame.size.width && location.y > 0 && location.y < sender.view.frame.size.height;
}
- (void)longPressDetectedLocation:(UILongPressGestureRecognizer *)sender {
if ([self longPressDetected:sender]) {
[self promptForLocation];
}
}
- (void)longPressDetectedPhoto:(UILongPressGestureRecognizer *)sender {
if ([self longPressDetected:sender]) {
[self promptForPhoto];
}
}
Considering you're trying to imitate a button click, I'm assuming you'd want the view to revert to its original state after the touch ends. To do this, you'll want to use a UILongPressGestureRecognizer instead of a UITapGestureRecognizer.
With a tap gesture, the recognizer isn't detected until the touch ends, so you'd effectively be highlighting the view as soon as you lift your finger. To get around this, use the long press gesture its minimumPressDuration property set to 0.0. Then in its selector, check the state of the sending gesture; If it has just begun, change the background color, and if it has ended revert back to the original color.
Here's an example:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 100.0f, 100.0f, 100.0f)];
[myView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:myView];
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressDetected:)];
[longPress setAllowableMovement:50.0f];
[longPress setMinimumPressDuration:0.0];
[myView addGestureRecognizer:longPress];
}
- (void)longPressDetected:(UILongPressGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
[sender.view setBackgroundColor:[UIColor blueColor]];
}else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed) {
[sender.view setBackgroundColor:[UIColor redColor]];
}
NSLog(#"%d",sender.state);
}
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tappedMethod:)];
[locationView addGestureRecognizer:gr];
This is method
-(void)tappedMethod:(UIGestureRecognizer *)ge
{
// write relavent code here;
locationView.backgroundColor = [UIColor blueColor];
}

animateWithDuration and touchesBegan don't work in pair

I need to handle touch on my object when it move across my screen. When touchesBegan called I need to hide my object.
this is my code in UIViewController:
- (void)win {
for (NSInteger i = 1; i <= 6; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"rocket_%d.png", i]]];
imageView.tag = 1000;
CGSize size = imageView.image.size;
[imageView setFrame:CGRectMake(200 + (i * 60), 500, size.width, size.height)];
[self.view addSubview:imageView];
[rockets addObject:imageView];
[imageView setUserInteractionEnabled:YES];
}
[self startRockets];
}
- (void)startRockets {
CGFloat timeInterval = 1.0;
for (UIImageView *imageView in rockets) {
[UIView animateWithDuration:5.0 delay:timeInterval options:UIViewAnimationOptionAllowUserInteraction animations:^{
[imageView setFrame:CGRectMake(imageView.frame.origin.x, 0, imageView.frame.size.width, imageView.frame.size.height)];
} completion:nil];
timeInterval += 1.0;
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
NSArray *views = [self.view subviews];
for (UIView *v in views) {
if (v.tag == 1000) {
if (CGRectContainsPoint(v.frame, touchLocation) == YES) {
[v setHidden:YES];
}
}
}
}
Maybe you are missing the AllowAnimatedContent. Try changing your
UIViewAnimationOptionAllowUserInteraction
to
UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionAllowAnimatedContent
...another way might be to use UITapGestureRecognizer :
- (void)createViews {
rockets = [[NSMutableArray alloc] init];
for (NSInteger i = 1; i <= 6; i++) {
UIView *view = [UIView new];
view.backgroundColor = [UIColor redColor];
view.frame = CGRectMake((i * 60), 100, 50, 50);
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(rocketTouched:)];
[view addGestureRecognizer:tap];
[self.view addSubview:view];
[rockets addObject:view];
}
[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(moveViews) userInfo:nil repeats:YES];
}
- (void)moveViews {
for (UIView * view in rockets) {
[UIView animateWithDuration:5.0 delay:0.0 options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionAllowAnimatedContent animations:^{
view.frame = CGRectMake(view.frame.origin.x -10, 0, view.frame.size.width, view.frame.size.height);
} completion:nil];
}
}
- (void)rocketTouched:(UITapGestureRecognizer*)tap {
tap.view.hidden = YES;
}
You need also check this if you need to detect intersection with object.
I have edited touchesBegan method and it works.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
for (UIImageView *imageView in rockets) {
CALayer *bbl1ObjPresentationLayer = (CALayer*)[imageView.layer presentationLayer];
if(CGRectIntersectsRect(bbl1ObjPresentationLayer.frame, CGRectMake(touchLocation.x, touchLocation.y, 1, 1))) {
NSLog(#"intersect");
//They are intersecting
}
}
}
if you do it using CALayer insted of UIImageView object this work correct. Check this answer link

Resources