Anchor button to bottom of screen above tabbar ios - ios

we have a couple screens where there is one button with one action to take, but the rest of the screen scrolls (full of info). So I want anchor the button to the bottom of the screen. This app has a tabbar, so the button is actually anchored 49pts above the base of the screen. This works just fine until someone goes to type into a text box. At this point the button that appears anchored at the bottom of the screen is just hanging out 49pts above the keyboard.
How do I fix this?
Here are a couple screen shots of what I'm talking about.

Figured it out. Here is the code I was using incase anyone has a similar problem. Since the keyboard takes up half the screen I only moved the button and label half the distance of the toolbar.
- (void) keyboardDidShow: (NSNotification *)notif {
_lblContinueBG.center = CGPointMake(_lblContinueBG.center.x, _lblContinueBG.center.y + 25);
_btnContinue.center = CGPointMake(_btnContinue.center.x, _btnContinue.center.y + 25);
}
- (void) keyboardDidHide: (NSNotification *)notif {
_lblContinueBG.center = CGPointMake(_lblContinueBG.center.x, _lblContinueBG.center.y - 25);
_btnContinue.center = CGPointMake(_btnContinue.center.x, _btnContinue.center.y - 25);
}
This page helped out a bunch too - similar post. Creating object programmatically and changing that object's position

Related

iOS UITextField Outside of SuperView not Responding to Touches

I'm building an iOS 8 app that makes use of the new hidesBarsOnSwipe property on UINavgitationController to hide the nav bar while scrolling. At the same time that the nav bar hides, I'm also programmatically hiding the tab bar. On top of the tab bar, there is a text field which lets users comment on a post (much like Facebook). When the tab bar is hidden (by moving it downward and off the screen), the text field is moved down as well, so that it now sits at the bottom of the screen and so that there's no gap between the bottom of the screen and the text field.
So, things look great. But, turns out that the text field doesn't respond to touch events when it moves to the bottom of the screen. I did some digging and it appears that the reason is because the text field is outside of its superview (the view controller's view), and so touch events will not be sent to the text field.
So I think I've figured out why the issue is occurring, but I haven't yet figured out how to fix it. I've tried messing with hitTest:withEvent: and pointInside:withEvent: but didn't have any luck. Anyone have any solutions?
EDIT: Here is some code to make the question clearer (hopefully). When the nav controller's barHideOnSwipeGestureRecognizer is called, I am running the following code:
- (void)barHideSwipeGestureActivated:(UIPanGestureRecognizer*)gesture
{
[self animateTabBarUpOrDown:self.navigationController.navigationBar.frame.origin.y >= 0 completion:nil];
}
The method above is the following:
- (void)animateTabBarUpOrDown:(BOOL)up completion:(void (^)(void))completionBlock
{
if(!self.animatingTabBar && self.tabbarIsUp != up)
{
self.animatingTabBar = YES;
//to animate the tabbar up, reset the comments bottom constraint to 0 and set the tab bar frame to it's original place
//to animate the tabbar down, move its frame down by its height. set comments bottom constraint to the negative value of that height.
[UIView animateWithDuration:kTabBarAnimationDuration animations:^{
UITabBar *tabBar = self.tabBarController.tabBar;
if(up)
{
tabBar.frame = CGRectMake(tabBar.frame.origin.x, tabBar.frame.origin.y - tabBar.frame.size.height, tabBar.frame.size.width, tabBar.frame.size.height);
self.addCommentViewToBottomConstraint.constant = 0.0f;
}
else
{
tabBar.frame = CGRectMake(tabBar.frame.origin.x, tabBar.frame.origin.y + tabBar.frame.size.height, tabBar.frame.size.width, tabBar.frame.size.height);
self.addCommentViewToBottomConstraint.constant = -tabBar.frame.size.height;
}
} completion:^(BOOL finished) {
self.tabbarIsUp = up;
self.animatingTabBar = NO;
if(completionBlock)
{
completionBlock();
}
}];
}
}
Ok, finally found a solution for this one. I haphazardly messed around with changing the bounds of my view controller's view, but that was too hacky and ultimately didn't accomplish what I wanted it to.
What I ended up doing was changing my view controller's edgesForExtendedLayout property to be equal to UIRectEdgeAll which basically says that the view should take up the entire screen, and extend above top bars / below bottom bars.
I had to hack around a little bit with changing auto layout constraints on my text field so that it appeared in the right place at the right time, but overall, the solution was changing edgesForExtendedLayout to be UIRectEdgeAll - this makes the view take up the entire screen, so the text field is now still in the super view even when it animates downward, thus, allowing it to still receive touch events.

iOS 7 custom keyboard UIView touch down event delayed in bottom row

here's an odd one..
I've got a UIView xib file that looks like this:
I've connected every UIButton touchDown and touchUpInside events to two IBAction methods:
- (IBAction)touchUpInside:(id)sender
{
NSLog(#"touch up inside");
if (((UIButton *)sender == _enter) | ((UIButton *)sender == _back)) {
[(UIButton *)sender setBackgroundColor:_color2];
}
else {
[(UIButton *)sender setBackgroundColor:_color1];
}
}
- (IBAction)touchDown:(id)sender
{
NSLog(#"touch down");
[(UIButton *)sender setBackgroundColor:_color2];
}
Everything works except for the bottom-most row of UIButton's, that's the odd part:
The touch down event is fired, but the button must be held for 0.5 second for it to change background color, whereas it is instantaneous for the other buttons.
It ONLY happens for the bottom-most row of UIButton's, as I've tried to switch buttons 7, 8, 9 with buttons #back, 0, #enter like this:
I've checked in Interface Builder all the UIButton attributes are the same, and I've tried moving the UIButton's objects order around as you can see on the left side of the picture, and I'm about out of ideas already. Basically what's odd is the UIControl behavior differs based on its position on the parent view...
UPDATE: I made the parent UIView height value large enough that there is 50 free pixels below the last row and the UIButton's work fine now. The only reason I can think of now is that there is a UITabBar there 2 view controllers level underneath. Even so it doesn't make sense.
The document says:
Expect users to swipe up from the bottom of the screen to reveal
Control Center. If iOS determines that a touch that begins at the
bottom of the screen should reveal Control Center, it doesn’t deliver
the gesture to the currently running app. If iOS determines that the
touch should not reveal Control Center, the touch may be slightly
delayed before it reaches the app.
One solution is here:
UIButton fails to properly register touch in bottom region of iPhone screen
But, in your case, I think you should use inputView in UIResponder.
See: https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/InputViews/InputViews.html
The inputView is not affected by that problem.

How can I assign a pointer to the keyboard before I have assigned first responder

I am trying to create a user interface enabling users to switch between the keyboard and other menus when using a chat application.
On a click of the textField bar I want to raise either the keyboard or a collection view.
The problem occurs when I click the 'menu' button. I want the textField bar to raise revealing my menu view. Then, on a click on the keyboard button, instantly switch to the keyboard, rather than having it slide up from the bottom. This means I need to have the keyboard already loaded and hidden but in the background of the app.
Currently though the earliest I am managing to assign a variable to the keyboard is in the keyboardDidShow function.
-(void) keyboardDidShow: (NSNotification *) notification {
// Get the window the keyboard is a subview of
_window = [UIApplication sharedApplication].windows.lastObject;
_keyboard = _window.subviews[0];
}
This means that after it has been loaded once I can hide and reveal it, but I don't want it visible when it is loading this first time.
To achieve this using alternate means I have tried adding my extra views as subviews of the UIWindow the keyboard is created in:
[_window addSubview:_menuView];
[_window addSubview:_gamesView];
[_window addSubview:_stickerView];
[self hideSpecificView];
Unfortunately I keep coming across the same problem, until I have loaded the keyboard once it needs to fully load before I can get a pointer to it to hide it.
Here is a picture of my toolBar incase I am not being clear:
On clicking the menu icon or the stickers icon I want the bar to raise with a collection view. If I then click the textfield, with these views visible, I want to hide the visible view to immediately show the keyboard behind.
I have also tried experimenting with keyboardWillShow but as the window hasn't been loaded in front our screen I can't get a pointer to the keyboard to hide it before it loads.
An example of what I am after can be found many chat apps (facebook messenger, LINE, Kakao Talk)
Any help would be greatly appreciated
Although the way I came up with isn't perfect it works almost perfectly so hopefully this might help people in the future. If anyone else has solved it differently please post as it would be interesting to know how you did it.
I started by adding a class variable to a UIWindow in my header file and then setting off a timer to ping just after the keyboard will show method finishes. After this method has finished the keyboard has been created, just, and so I allocate it and hide it.
-(void) keyboardWillShow: (NSNotification *) notification {
// More keyboard code
_window = [UIApplication sharedApplication].windows.lastObject;
[NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:#selector(allocateKeyboard)
userInfo:nil
repeats:NO];
}
- (void)allocateKeyboard {
if (!_keyboard) {
_keyboard = _window.subviews[0];
}
_keyboard.hidden = YES;
[self setViewForButtonType];
}
I have already previously added my other views, hidden them and constrained them to the bottom of the main view, this means that when the keyboard rises they do too.
- (void)viewDidLoad {
[self.view addSubview:_menuView];
[self.view addSubview:_gamesView];
[self.view addSubview:_stickerView];
}
...
- (void)hideViews {
_keyboard.hidden = YES;
_menuView.hidden = YES;
_gamesView.hidden = YES;
_stickerView.hidden = YES;
}
When buttons get pressed I simple then unhide the view that I want to see and hide the rest of the views.
When I say that this method doesn't work perfectly it is because if you load view main view and then click a button before the keyboard has loaded for the first time then you get a quick glimpse of the keyboard before the view appears over the top. This though only happens the first time and only if they don't click in the text field first.
Anyway, I found this was the best way of making views look like they are in front of the keyboard. Obviously my code was a lot longer and more complex (too long for here) but this is the gist of the method I used to solve it. Comment if you have any queries and I hope this helps.

Funny UIScrollView when using presentViewController

Summary:
I have a UIScrollView with zoomable content. If the content is NOT zoomed and I presentViewController, everything is fine when I dismiss that ViewController. But, if I have zoomed the content and then presentViewController, the content and the UIScrollView are all wacky when I dismiss the ViewController. Any help is welcome, this is an awful bug... Thank you!
Test Project:
A simple test can be found here...
http://twostatesaway.com/ModalWithScrollViewTEST.zip
or here
https://drive.google.com/file/d/0B0pG5vRVzBTzdkVzdEtkdmVjdDA/edit?usp=sharing
Screen Shots:
Screen 1: Everything fine. I can show the modal a million times and the content will work as expected after dismissing the modal
Screen 2: Zoom in on content.
Screen 3: When I click the button to presentViewController, the content shifts to the right as the ViewController (in black) is coming up.
Screen 4: Modal is on screen.
Screen 5: When I dismiss the ViewConroller, the content is funny, the bright green view seems to go back to normal, but the button stays in its zoom position, still shifted to the right.
Screen 6: Another funny things is that now I can zoom out more than before. The min zoom is set at 1.0, but now it seems like that is not working.
Try this way...
1) Remove the code from - (IBAction)openModal:(id)sender & make it blank.
2) In story board make the secondViewController class as ModalViewController as below.
3) Drag the line from button to second view & use segue as modal as shown below.
Updated answer
1) clear the viewDidLoad method.
2) Write following code in ViewWillAppear method.
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.scrollView.delegate = self;
self.scrollView.minimumZoomScale = 1.0;
self.scrollView.maximumZoomScale = 5.0;
//self.scrollView.contentSize=CGSizeMake(320, 200);
[self.scrollView setZoomScale:self.scrollView.minimumZoomScale];
}
The accepted work around here is to capture the zoom and contentOffset when the modal is coming up, and then set the properties when view is appearing again...
//// Capture values
-(void)viewWillDisappear:(BOOL)animated
{
zoomedScale = self.scrollView.zoomScale;
contentOffsetTemp = self.scrollView.contentOffset;
}
//// This prevents the content from getting messed up (thanks user1673099)
-(void)viewDidDisappear:(BOOL)animated
{
[self.scrollView setZoomScale:self.scrollView.minimumZoomScale];
}
//// Then reassign them values
-(void)viewWillAppear:(BOOL)animated
{
self.scrollView.zoomScale = zoomedScale;
self.scrollView.contentOffset = contentOffsetTemp;
}

UIScrollView - Showing user more content is available on scroll

I have a similar problem as this post
I have a scrollview where more data is visible to the user if the user scrolls to the left or scrolls to the bottom. But I am unable to find a way to tell the user that more content is available on scroll. It is not intuitive and only by experimenting, the user will find out about the scroll option.
Is there any way I can show/tell the user that scrolling is available.
Using [scrollView flashScrollIndicators] is not exactly useful as it just flashes the indicators and it is so quick that the user would surely fail to see it.
It would be great if someone can help me with this.
This is the way I did it...
I put an image on my scroll view ( for example an arrow pointing left). So using the function mentioned below, whenever the user loads the view, the image would show (telling that more content is there in the right). When the user comes to the right most of the scrollview, the image would disappear and when he scrolls again to the left, it would reappear...
- (void)scrollViewDidScroll:(UIScrollView *)scrollView1 {
if (scrollView1.contentOffset.x == scrollView1.contentSize.width - scrollView1.frame.size.width)
{
// reached the bottom
NSLog(#"reached right");
self.imageView.hidden = YES;
}
else
{
self.imageView.hidden = NO;
}
}
i not sure but may be u can set a timer to flash indicators so that it stays there.......

Resources