I created a subclass of UIImageView to pass some strings from and to it. I also created a custom class of UITableViewCell and put four of my UIStringImageView inside of it.
I did this for a gallery like thumbnail tableView.
Then I added an UITapGestureRecognizer to every single UIStringImageView to open the corresponding image.
Now I want to add an overlay onto the UIStringImageView (with opacity) ti indicate touches on the single imageViews.
Here my code (from the UIStringImageView's implementation):
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
overlay = [[UIView alloc] initWithFrame:self.frame];
[overlay setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.5]];
[self addSubview:overlay];
}
The code works fine. But my problem actually is, that the overlays are not on top of the imageViews, but have got an offset (from top and left). The top offset is the same for every view and the left offset increases per imageView (from left to right).
Screenshot with two overlays (the first and second imageView from left, bottom row):
Can anybody help me with this issue? Thanks a lot! Julian
For everyone running into something like the same problem:
Using self.bounds instead of self.frame solved the issue.
Related
I have many SubViews in my UIView, and many of them have UIButtons in them. One of the subviews- _bottomView (Coordinates- (0,519,320,49)) has an error. It does not recognise the click events on the buttons placed inside it.
I tried placing a UIButton covering the entire _bottomView and the click event from that Button (testButton) is not being recognised either.
I tried adding a tapRecogniser to the code and the tap from every point, EXCEPT the points within the _bottomView are recognised. TapRecogniser Code below
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[self.view addGestureRecognizer:gr];
_bottomView.userInteractionEnabled=true;
-(void)handleGesture:(UIGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.view];
NSLog(#"got a tap in the region i care about");
}
I tried [self.view addSubview:_bottomView]; and that didn't help either. What could be the issue?
If your view is not receiving touches
Make sure that your UIView has userInteractionEnabled set to YES
Make sure that the view is within the bounds of its superview, and the superview is within the bounds of window.You can print the frames of views using NSLog(#"%#",NSStringFromCGRect(view.frame));
Nothing helped. I had to delete the entire View Controller and redo the whole thing. That obviously solved the problem.
I am moving most of UIImageViews on view and keeping an UIImageview fixed. Everything is happening fine but problem is when moving imageviews are containing or intersecting the fixed imageview, they are just moving from under fixed imageview.
How to make UIImageviews to move over the fixed imageview.
Please Find the function StartMoving code which makes UIImageviews to move in screen and called on buttonClick event.
In code...
CGPoint pos1,Pos2,pos3;
UIImageView *ball1,*ball2,*ball3,*fixedball;
-(void)StartMoving
{
pos1=CGPointMake(5.0, 5.0);
pos2=CGPointMake(5.0, 8.0);
pos3=CGPointMake(8.0, 5.0);
ball1.center=CGPointMake(ball1.center.x+pos1.x, ball1.center.y+pos1.y);
ball2.center=CGPointMake(ball2.center.x+pos2.x, ball2.center.y+pos2.y);
ball3.center=CGPointMake(ball3.center.x+pos3.x, ball3.center.y+pos3.y);
if(ball1.center.x>320||ball1.center.x<0)
pos1.x=-pos1.x;
if(ball1.center.y>480||ball1.center.y<0)
pos1.y=-pos1.y;
if(ball2.center.x>320||ball2.center.x<0)
pos2.x=-pos2.x;
if(ball2.center.y>480||ball2.center.y<0)
pos2.y=-pos2.y;
if(ball3.center.x>320||ball3.center.x<0)
pos3.x=-pos3.x;
if(ball3.center.y>480||ball3.center.y<0)
pos3.y=-pos3.y;
}
...and have added all moving and fixed imageviews in stroyboard.
Thanks in advance
You need to bring that subview to the front of the other subviews:
UIView *viewContainingBalls; // most likely ball1.superview
[viewContainingBalls bringSubviewToFront:ball1];
Use this method to bring the other balls to the front as needed.
Or if you always want the fixed ball to be behind all the other balls you could just send this to the back:
UIView *viewContainingBalls; // most likely fixedball.superview
[viewContainingBalls sendSubviewToBack:fixedball];
There are other methods such as exchangeSubviewAtIndex:withSubviewAtIndex: that also accomplish similar a thing.
So i have a UIView setup on the Ipad for a small project i am working on. I will be displaying an image or a view on that page. I wanted to know if is it possible to create an invisible border (say 1") around the view that will be unclickable ?
I was thinking of adding a button and disabling it, but i think that would not allow the image to be shown full screen.
I have already setup a recognizer, because i want a three finger swipe to go to the next image. What would be the best approach for this ?
Use a custom UIView class and override hitTest:withEvent:.
- UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
CGRect frame = CGRectInset(self.bounds, 25, 25);
return CGRectContainsPoint(frame, point) ? self : nil;
}
Adjust the inset to meet your needs.
It may seem like duplicate, but I can't actually find any good answer to my concrete situation.
I have some button with background image (1pt-wide, streched), icon-like image inside along with the text label. It's height is 33pt, I need to make it's hittest area 44pt-high.
I saw two solutions, but neither of them works for me.
First solution is to enlarge frame and adjust image so it would have some padding. But that is not acceptable for me, because I have both background image and image inside the button.
Second solution is to subclass UIButton (which is absolutely acceptable) and override - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event. I did that, when I put some breakpoints in this method and tried to tap in desired area nothing happened (breakpoints worked when tapped inside the button frame).
Are there any other solutions? What could be possibly wrong with the second solution?
If you create the view programmatically, you can instantiate a UIView that is 44px high, add a tap gesture recognizer to it, and add your UIButton as a subview inside this view:
CGRect bigFrame = CGRectMake(0,0,100,44);
UIView *big = [[UIView alloc] initWithFrame:bigFrame];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doPress)];
[big addGestureRecognizer:tapRecognizer];
UIButton *yourButton = ...
[big addSubview:yourButton];
[self.view addSubview:big];
Then implement the selector as:
- (void)doPress {
[yourButton sendActionsForControlEvents:UIControlEventTouchUpInside];
}
In that way, the outer view taps will be interpreted as button presses for your button.
When I add a subview to a MKMapView or to any of it's descendent views, touches will pass right through and affect the map.
This question is ultimately used to explain a bug that was fixed for my custom callout which adds a view to an annotation view. The callout is not to be dismissed when the callout is touched and this question is in reference to that. But for the case brevity I'll use a smaller example that demonstrates the problem.
Setting exclusiveTouch and userInteractionEnabled doesn't do anything. BTW.
Let's take a UIView and attach it to the mapView
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]
view.backgroundColor = [UIColor blackColor];
[mapView addSubview:view];
And let's add a gesture to the map as well
[mapView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)]];
And just have handleLongPress print something NSLog(#"longpress"); Now run the program and observe how long pressing the black uiview will cause the longPress to be triggered. If we add an annotation that shows a callout and select it, touching the black uiview will dismiss it. And if we scroll the map so that the annotation is under the black uiview, we'll be able to select the annotation. Now here's my solution. We tag the view that we're going to add to mapview with SOME_TAG and overwrite the hitTest method for MKMapView
#interface MKMapView(HackySolution)
#end
#implementation MKMapView(HackySolution)
- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
// block touch propagation
if(view.tag == SOME_TAG){
view = nil;
}
return view;
}
#end
Now here's the deal, I may have solved my problem, but I really don't know why touches from the UIView are being passed right through onto the map. It doesn't make sense for a touch to a subview to be passed onto it's parentView. Maybe I'm not understanding how touches work. I mean if I place a button on a normal UIView and place another uiview on top of it, completely obscuring it, the button wouldn't get the touch right? I'm starting to second guess myself. :/
I can only guess that MKMapView is wired to do this, but I'm unsure. I thought there was a scroll view somewhere within MKMapView, but I ran through all the subviews and all the descendents and didn't find anything.
Is there a better way to solve this problem or is this the best it gets?
Any insight into the situation would be greatly appreciated.