I'm not seeing what's wrong here. When user taps and hold, I add a view, when touch finishes the view gets removed. This does NOT work and I do see the UIGestureRecognizerStateEnded being sent.
However, if I call [tmpView removeFromSuperview]; outside of that state it gets removed without any issues.
Any idea what's causing this?
-(void)longTapped:(UILongPressGestureRecognizer*)recognizer {
UIView *tmpView = [[UIView alloc] init];
tmpView.backgroundColor = [UIColor greenColor];
// Position the menu so it fits properly
tmpView.frame = CGRectMake(0, 100, 320, 250);
// Add the menu to our view and remove when touches have ended
if (recognizer.state == UIGestureRecognizerStateBegan) {
[self.view addSubview:tmpView];
}
else if(recognizer.state == UIGestureRecognizerStateEnded){
[tmpView removeFromSuperview];
}
}
The second time your -longTapped: method is called it is instantiating a new instance of UIView in the tmpView variable, and trying to remove that from its superview. You need to store a reference to your added view on the controller when the long press starts, and when it ends you need to remove that object from its superview.
#interface myVC ()
#property (nonatomic, weak) UIView *tmpView;
#end
-(void)longTapped:(UILongPressGestureRecognizer*)recognizer {
if (recognizer.state == UIGestureRecognizerStateBegan) {
// Add the menu to our view and remove when touches have ended
self.tmpView = [[UIView alloc] init];
self.tmpView.backgroundColor = [UIColor greenColor];
// Position the menu so it fits properly
self.tmpView.frame = CGRectMake(0, 100, 320, 250);
[self.view addSubview:self.tmpView];
}
else if(recognizer.state == UIGestureRecognizerStateEnded){
[self.tmpView removeFromSuperview];
self.tmpView = nil;
}
}
Related
I have a View which is the subView of the main view in iphone app I want that when subView is shown and user taps on part of the screen except the subView then subView should hide.
Here is the code which I got but it does not hide it :
UITapGestureRecognizer *tapGR;
tapGR = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)] autorelease];
tapGR.numberOfTapsRequired = 1;
[self.View addGestureRecognizer:tapGR];
// Add a delegate method to handle the tap and do something with it.
-(void)handleTap:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded) {
// handling code
[myViewSheet removeFromSuperView];
}
}
implement UIGestureRecognizerDelegate protocol:
.h:
#interface YourView : UIView<UIGestureRecognizerDelegate>
.m:
#implementation YourView{
UIView * subview;
}
...
subview = [[UIView alloc]initWithFrame:CGRectMake(0, 200, 320, 200)];
[self addSubview:subview];
UITapGestureRecognizer *tapGR;
tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapGR.numberOfTapsRequired = 1;
tapGR.delegate = self;
[self addGestureRecognizer:tapGR];
...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view == subView)
{
return NO;
}
else
{
return YES;
}
}
You probably need to set userInteractionEnabled = YES on your main view (The one to which you are attaching the gesture recognizer.)
I am trying to create a custom look of my UINavigationBar. When the user puts the app in landscape, the navigationBar should be covered with an Image. When rotated back to portrait I want the View(Image) removed. Everything works fine with the code below except removing it. I can remove the View if I put the code in the same if-statement, but nothing happens if I put it in the else if-statement. Have I missed something ? / Regards
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
UIView *v = [[UIView alloc]init];
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
v.frame = CGRectMake(0,0,480,44);
v.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"navbar25g.png"]];
[self.view addSubview:v];
//[v removeFromSuperview]; <----- works if I put it here
NSLog(#"LANDSCAPE");//load the landscape view
}
else if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[v removeFromSuperview]; <----- Not working
NSLog(#"PORTRAIT"); //load the portrait view
}
}
the reason that you cannot remove it is every time you go into the method you create a new instance of the UIView *v.
Create an instance variable then assign the view to that. Once it is assigned you can then remove or add as needed.
If you do not want to use an instance variable then you can give the view a tag i.e.
UIView *v = nil;
v = [self.view viewForTag:1000];
if (!v) {
v = [[UIView alloc] init];
v.tag = 1000;
v.frame = CGRectMake(0, 0, 480, 44);
v.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"navbar25g.png"]];
}
Now you can do your adding and removing for it.
Have you tried UIAppearance?
[[UINavigationBar appearance] setBackgroundImage:nil barMetrics:UIBarMetricsDefault];
[[UINavigationBar appearance] setBackgroundImage:image barMetrics:UIBarMetricsLandscapePhone];
I am trying to navigate from a UIScrollView's content view to another view by using a UIButton. I do not want to display this other view modally, and pushing the view on the stack is not working for me.
Example:
My Viewcontroller contains a Scrollview that has 2 content views. Within these content views I would like to push another view onto the stack.
Is what I am trying to do possible?
Ok let's see if I understood well enough your problem.
#interface MyViewController ()
#property (nonatomic, strong) UIScrollView *scrollView;
#property (nonatomic, strong) UIView *firstPlayerView;
#property (nonatomic, strong) UIView *secondPlayerView;
#end
#implementation MyViewController
-(UIView *)firstPlayerView
{
if (!_firstPlayerView) {
_firstPlayerView = [[UIView alloc] initWithFrame:self.view.bounds];
// set up your view as you like and place the button to go to the second player
// view when you need to.
// let's suppose that you called that button "goToSecondPlayerViewButton"
[goToSecondPlayerViewButton addTarget:self
action:#selector(switchPlayer)
forControlEvents:UIControlEventTouchUpInside];
}
return _firstPlayerView;
}
-(UIView *)secondPlayerView
{
if (!_secondPlayerView) {
_secondPlayerView = [[UIView alloc] initWithFrame:CGRectOffset(self.view.bounds, self.view.bounds.size.width, 0)];
// set up your view as you like and place the button to go to the first player
// view when you need to.
// let's suppose that you called that button "goToFirstPlayerViewButton"
[goToFirstPlayerViewButton addTarget:self
action:#selector(switchPlayer)
forControlEvents:UIControlEventTouchUpInside];
}
return _secondPlayerView;
}
-(UIScrollView *)scrollView
{
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingNone;
[_scrollView addSubview:self.firstPlayerView];
[_scrollView addSubview:self.secondPlayerView];
_scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height);
_scrollView.pagingEnabled = YES;
_scrollView.scrollEnabled = NO;
_scrollView.bounces = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
}
return _scrollView;
}
-(void)switchPlayer
{
if(self.scrollView.contentOffset.x == 0) {
[self.scrollView scrollRectToVisible:CGRectMake(self.scrollView.bounds.size.width, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height) animated:YES];
self.title = #"Second Player";
} else {
[self.scrollView scrollRectToVisible:self.scrollView.bounds animated:YES];
self.title = #"First Player";
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view addSubview:self.scrollView];
self.title = #"First Player";
}
#end
I hope that solves your problem! I haven't tested the code so if you encounter problems just comment and I'll try to help.
Edited : To add a view you just enlarge the scroll view contentSize and add that view as its subview
-(UIView *)thirdView
{
if (!_thirdView) {
_thirdView = [[UIView alloc] initWithFrame:CGRectOffset(self.view.bounds * 2, self.view.bounds.size.width, 0)];
// set up your view as you like
}
return _thirdView;
}
-(void)addThirdView
{
self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width * 3, self.scrollView.bounds.size.height);
[self.scrollView addSubview:self.thirdView];
[self.scrollView scrollRectToVisible:CGRectMake(self.scrollView.bounds.size.width * 2, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height) animated:YES];
}
You can generalize this and set your content size first then have a single method that takes an index as an argument.
-(void)scrollToViewAtIndex:(NSInteger)index
{
[self.scrollView scrollRectToVisible:CGRectMake(self.scrollView.bounds.size.width * index, 0, self.scrollView.bounds.size.width, self.scrollView.bounds.size.height)
animated:YES];
}
I am adding a badge to a UIBarButtonItem... which works fine. But I cannot remove it. Any help is appreciated.
Thanks.
Code:
MKNumberBadgeView *badge = [[MKNumberBadgeView alloc] initWithFrame:CGRectMake(45, -10, 30,30)];
badge.value = #"!";
badge.layer.cornerRadius = 10;
badge.layer.masksToBounds = YES;
badge.tag = 42;
if ([self.chatCount isEqualToString:#"1"]) {
[chatButton addSubview:badge];
} else {
for (UIView *view in [self.view subviews] ) { if (view.tag == 42 ) { [view removeFromSuperview]; } }
[badge release];
}
UIBarButtonItem *chat = [[UIBarButtonItem alloc] initWithCustomView:chatButton];
self.navigationItem.rightBarButtonItem = chat;
[chat release];
You're adding your badge as a subview to chatButton not self.view. Your for loop is iterating over self.view.subviews and badge is not a subview of self.view but a subview of chatbutton. You will either have to iterate over chatButton.subviews or create a recursive method that iterates over all subviews. Alternatively, you can use viewWithTag which I think searches the entire hierarchy.
I would just hold an instance variable to badge and call [self.badge removeFromSuperview] or self.badge.hidden = YES;
my problem might be simple to some of you but i can't find a solution. I have a method where a create my views automatically (text fields, labels and text views). It's like a registration form. The problem is that when i change the screen to landscape mode, i want to change the views width. To do that i used [self.view removeFromSuperview] and created the views again. The problem is that the views won't get recreated with the landscape width. I can't use IB to autosize the views at orientation change. The views are created in viewDidLoad and removed and recreated in - (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation {} I don't know why they don't get recreated after being removed. If there was another solution that you could share with me i would appreciate it.
Here's how i create the views:
-(void)createViews:(int)width
{
for(int i = 0; i < numberOfTextfields; i++) {
textfieldPadding = textfieldPadding+40;//set some space between the text fields
labelPadding = labelPadding+40;//set some space between the labels
UITextField *field = [[UITextField alloc] initWithFrame:
CGRectMake(10,i*textfieldHeight+textfieldPadding+firstTextfieldHeight+10,width, textfieldHeight)];
field.autoresizingMask = UIViewAutoresizingFlexibleWidth;
//field.backgroundColor= [UIColor cyanColor];
field.placeholder = [labels objectAtIndex:i];
field.borderStyle=UITextBorderStyleRoundedRect;
field.returnKeyType = UIReturnKeyDone;
[field addTarget:self action:#selector(doneButton:)
forControlEvents:UIControlEventEditingDidEndOnExit];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, i*labelHeight+firstLabelHeight+labelPadding-20, width, labelHeight)];
label.text = [labels objectAtIndex:i];
//label.backgroundColor = [UIColor brownColor];
[scrollView addSubview:field];
[scrollView addSubview:label];
[textfields addObject:field];
[labels addObject:label];
[field release];
[label release];
}
}
Here's where i wanted to remove them and recreate them:
- (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation
{
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
[self.view removeFromSuperview];
[self createViews:landscapeWidth];
}
else if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[self.view removeFromSuperview];
[self createViews:portraitWidth];
}
}
Thanks in advance!
Instead of removing, resizing and then re-adding as you currently are why not just set the appropriate autoresizingMask (link) when you create the view initially?
UITextField *myTextField = [[UITextField alloc] initWithFrame:someRect];
// the following will automatically resize the width on orientation change
myTextField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[myView addSubview:myTextField];
[myTextField release];