keyboard not show at first time(iOS) - ios

My code like this:
- (void)setupSubViews {
[self addSubview:self.textView];
[self addSubview:self.sendButton];
[self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(5);
make.bottom.equalTo(-5);
make.leading.equalTo(9);
}];
[self.sendButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self);
make.trailing.equalTo(-9);
make.leading.equalTo(self.textView.mas_trailing).offset(7);
make.width.equalTo(60);
make.height.equalTo(40);
}];
}
The show function to make the textView becomeFirstResponder
- (void)show {
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
[keyWindow addSubview:self];
[self mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.trailing.equalTo(0);
make.bottom.equalTo(InputHeight);
}];
[self.textView becomeFirstResponder];
}
This view add to the keyWindow at the bottom of mainScreen, it's translate will changing follow the keyboard when the keyboard's frame changed.
- (void)keyboardWillChangeFrame:(NSNotification *)noti {
if (!self.textView.isFirstResponder) {
return;
}
NSValue *endFrame = noti.userInfo[#"UIKeyboardFrameEndUserInfoKey"];
CGFloat endY = [endFrame CGRectValue].origin.y;
BOOL isBackToBottom = endY == UI_SCREEN_HEIGHT;
CGFloat needOffset = endY - (UI_SCREEN_HEIGHT + InputHeight);
if (isBackToBottom) {
[UIView animateWithDuration:0.25 animations:^{
self.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
} else {
[UIView animateWithDuration:0.25 animations:^{
self.transform = CGAffineTransformMakeTranslation(0, needOffset);
}];
}
}
Use Case:
viewController has a button, button click action like this:
- (void)beginChat {
[self.inputView show];
}
self.inputView is the above customView,
- (LiveChatInputView *)inputView {
if (!_inputView) {
_inputView = [LiveChatInputView new];
_inputView.sendBlock = ^(NSString *string) {
....
};
}
return _inputView;
}
Now my question is that when we call show function at the first time after application launched, the keyboard will not show, but call show function in second time, every thing is fine.
How to deal with this question, THX.

Calling this method is not a guarantee that the object will become the first responder.
As per Apple,
A responder object only becomes the first responder if the current
responder can resign first-responder status (canResignFirstResponder)
and the new responder can become first responder.
Try calling becomeFirstResponder like below,
[self.textView performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0];

I made a mistake, call [self removeFromSuperview] in the function of keyboardWillChangeFrame:.
I thought UIKeyboardWillChangeFrameNotification could only post it once at the keyboard show or hide, so i put the implementation of back action in keyboardWillChangeFrame:, and controlled by endFrame.origin.y == UI_SCREEN_HEIGHT
In practice, the fact is that:
when the keyboard show, NSNotificationCenter will post UIKeyboardWillChangeFrameNotification three times:
first
second
third
Tips:
only first time show the keyboard after application launched, the first UIKeyboardWillChangeFrameNotification of above three, the endFrame.origin.y is equal to UI_SCREEN_HEIGHT
My solution:
Observer the UIKeyboardWillHideNotification, and do back action in this callback.
Thanks for all answers of this question.

Related

Hiding and showing UITableview with slide down and slide up animation

is it possible to put animation to UITableView?
I currently have this:
- (IBAction)mPesoAccount:(id)sender {
if (accountBalanceTableView.isHidden) {
accountBalanceTableView.hidden = NO;
} else {
accountBalanceTableView.hidden = YES;
}
}
it hides or show the uitableview whenever i click a button, i would like to add an animation when i'm hiding and showing the uitableview
it would similar like a dropdown item, where it slides up into the button and collapses down when the button clicked again.
Simply animating your UITableView frame if you are using non constraints approach, or making the bottom constraint IBOutlet and changing the constant value
- (void)viewDidLayoutSubViews
{
[super viewDidLayoutSubViews];
self.originalTableViewFrame = accountBalanceTableView.frame;
}
- (IBAction)mPesoAccount:(id)sender {
if (accountBalanceTableView.isHidden)
{
[UIView animateWithDuration:.3 animations:^{
accountBalanceTableView.frame = self.originalTableViewFrame;
}completion:^(BOOL finished) {
accountBalanceTableView.hidden = NO;
}];
}
else
{
[UIView animateWithDuration:0.3 animations:^{
accountBalanceTableView.frame = CGRectMake(originalTableViewFrame.origin.x, originalTableViewFrame.origin.y + originalTableViewFrame.size.height, originalTableViewFrame.size.width, 0);
} completion:^(BOOL finished) {
accountBalanceTableView.hidden = YES;
}];
}
}

Send button is not working when keyboard opened in iOS

I am stuck in very simple functionality in iOS.
I am trying to send the data from a textField which is inside the subview of a scroll view. Button is firing the action when I hit the button, when keyboard is closed as soon as I try to write something and keyboard opened button stop responding.
VideoViewController:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
controller.videoID = videoID;
controller.channelID = channelID;
controller.view.frame = self.commentView.bounds;
[self.commentView addSubview:controller.view];
// [self.scrollView addSubview:controller.sendBtn];
[self addChildViewController:controller];
[controller didMoveToParentViewController:self];
}
CommentViewController:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
controller.videoID = videoID;
controller.channelID = channelID;
controller.view.frame = self.commentView.bounds;
[self.commentView addSubview:controller.view];
// [self.scrollView addSubview:controller.sendBtn];
[self addChildViewController:controller];
[controller didMoveToParentViewController:self];
}
-(void)keyboardWillShow:(NSNotification *)notification
{
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
[UIView animateWithDuration:0.3 animations:^{
CGRect f = self.view.frame;
f.origin.y = -keyboardSize.height+100;
self.sendView.frame = f;
}];
_sendBtn.userInteractionEnabled = YES;
}
-(void)keyboardWillHide:(NSNotification *)notification
{
[UIView animateWithDuration:0.3 animations:^{
CGRect f = self.view.frame;
f.origin.y = 0.0f;
self.sendView.frame = f;
}];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[commentTextField resignFirstResponder];
return YES;
}
- (BOOL)touchesShouldCancelInContentView:(UIView *)view
{
return ![view isKindOfClass:[UIButton class]];
}
Please suggest something on this.
Thank you.
I faced this problem, too
It took me 2 days to find the solution. You need to set the cancel touches flag to false for ScrollVIew/View.
Actually, scrollview touch is enable and it is not allowing the button to interact.
This is the only reason send button is not working.

How to animate deletion of a label?

I have a view controller that have a scroll view that bounce horizontally , and in this scroll view I have a label.
I can now hold the label and scroll it down, and if I release it will bounce up back.
What I want is that: When I scroll the view y coordinate (using myScrollView.contentOffset.y) to some value, lets say -33 and under I can release my fine and the label will animate to the bottom of the screen and disappear, and now I can set the label to be a new value, and It will animate from top to the label original position.
Here a photo of how the view controller looks like:
And this is the relevant method I already implemented (powered by #rebello95):
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.myScrollView.contentOffset.y <= -73) {
[UIView animateWithDuration:0.3 animations:^{
self.homeLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self.homeLabel removeFromSuperview];
self.homeLabel = nil;
}];
}
NSLog(#"%f", self.myScrollView.contentOffset.y);
}
Now I want it to slide to the bottom of the page and fade.
thanks!
EDIT: The animation now moves the label to the bottom of the view controller then fades it out.
You can use an animation block to move the label, then put another block inside the completion block to fade out the label, then remove it after the animation completes.
Example:
[UIView animateWithDuration:0.3 animations:^{
[self.myLabel setFrame:CGRectMake(self.myLabel.frame.origin.x, self.view.frame.size.height - self.myLabel.frame.size.height, self.myLabel.frame.size.width, self.myLabel.frame.size.height)];
self.labelRemoving = YES;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self.myLabel removeFromSuperview];
self.myLabel = nil;
self.labelRemoving = NO;
}];
}];
Sidenote: You should probably be using <= instead of == in your if statement to achieve your desired results. In addition, you may want to set a flag to indicate that your label is being removed (since that method will inevitably be called multiple times). Something like this:
//.h
#property (nonatomic, assign) BOOL labelRemoving;
//.m
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (self.myScrollView.contentOffset.y <= -33 && !self.labelRemoving) {
[UIView animateWithDuration:0.3 animations:^{
[self.myLabel setFrame:CGRectMake(self.myLabel.frame.origin.x, self.view.frame.size.height - self.myLabel.frame.size.height, self.myLabel.frame.size.width, self.myLabel.frame.size.height)];
self.labelRemoving = YES;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
self.myLabel.alpha = 0.0;
} completion:^(BOOL finished) {
[self.myLabel removeFromSuperview];
self.myLabel = nil;
self.labelRemoving = NO;
}];
}];
}
NSLog(#"%f", self.myScrollView.contentOffset.y);
}

Improve tabBar animation when hidden

I've think about how to make the tabBar 's hidden animation more elegant and smoothly:
Here is how I implement:
So I just want to improve the animation, while the tabBar is suddenly, you know, disappear and hidden.
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
[self.tabBarController.tabBar setHidden:YES];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self.tabBarController.tabBar setHidden:NO];
}
Any suggestion?
Try adding this method:
- (void)setTabBarHidden:(BOOL)tabBarHidden animated:(BOOL)animated
{
if (tabBarHidden == _isTabBarHidden)
return;
CGFloat offset = tabBarHidden ? self.tabBarController.tabBar.frame.size.height : -self.tabBarController.tabBar.frame.size.height;
[UIView animateWithDuration:animated ? 0.6 : 0.0
delay:0
usingSpringWithDamping:0.7
initialSpringVelocity:0.5
options:UIViewAnimationOptionCurveEaseIn|UIViewAnimationOptionLayoutSubviews
animations:^{
self.tabBarController.tabBar.center = CGPointMake(self.tabBarController.tabBar.center.x,
self.tabBarController.tabBar.center.y + offset);
}
completion:nil];
_isTabBarHidden = tabBarHidden;
}
Then you can call it like [self setTabBarHidden:YES animated:YES] and [self setTabBarHidden:NO animated:YES] to hide and show your bar, this will move it in and out of the screen instead of just make it instantly dissapear.
Don't forget to add a new bool property isTabBarHidden and also you can play with the values of the animation.

How do I move a child view controller, while hiding the status bar using Auto Layout instead of frames?

I have a view controller with multiple child view controllers in it (set up using Storyboards), and I move the one on top to the right (with the status bar as well) to display the underlying sidebar view controller.
This works perfectly with frames, as shown below:
- (void)displaySidebar {
self.fullScreenSnapshotOverlay = [self takeFullScreenSnapshot];
[self.postsView addSubview:self.fullScreenSnapshotOverlay];
[self hideStatusBar];
[UIView animateWithDuration:0.4 animations:^{
CGRect newFrame = self.postsView.frame;
newFrame.origin.x += 200.0;
self.postsView.frame = newFrame;
}];
}
(hideStatusBar simply called the UIApplication method and layoutIfNeeded.)
Giving me this (perfect) result:
However, if in the Storyboard I go to the container view controller and make a constraint from its leading space to the left of the view controller it's embedded in, and then adjust that constant, it really messes up the navigation bar, I assume due to hiding the status bar and taking a screenshot. I'm using this code:
- (void)displaySidebar {
self.fullScreenSnapshotOverlay = [self takeFullScreenSnapshot];
[self.postsViewController.view addSubview:self.fullScreenSnapshotOverlay];
[self hideStatusBar];
[UIView animateWithDuration:0.4 animations:^{
self.postsViewControllerDistanceFromLeftSideConstraint.constant = 270.0;
[self.view layoutIfNeeded];
}];
}
Giving me this messed up result:
Now I know the simple thing to do would be to just continue with frames, but I'd like to learn how do it properly with Auto Layout. What am I doing wrong here?
I'm not sure how what I did is any different from what you're doing. I modified the code I posted to your other question (Why does hiding my status bar completely break my simple animation?) to what's below, and it worked fine.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self performSelector:#selector(displaySidebar) withObject:nil afterDelay:1];
}
-(void)displaySidebar {
self.snapshotView = [self takeSnapshot];
[self.PostsView addSubview:self.snapshotView];
[self hideStatusBar];
self.leftCon.constant = 270;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
}
-(void)moveOutMenu { // called from a button in the menu controller
self.leftCon.constant = 0;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[[UIApplication sharedApplication] setStatusBarHidden:NO];
[self.snapshotView performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:0.01];
}];
}
-(UIView *)takeSnapshot {
UIView *v = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
return v;
}
-(void)hideStatusBar {
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self.view layoutIfNeeded];
}
What are all the constraints you have on the container view that you're moving? Maybe there's something different there (I have top, leading, bottom and width constraints on mine -- leftCon is the outlet to the leading constraint).

Resources