UITextField cursor animated top to down then text also being animated - ios

I am working registration form in iOS application. There several textfields such as name,email,city etc. when the textfield started editing cursor appearing like animated. Cursor slowly coming from top to down after typing the letter its moving from left to right slowly.I need to stop this unwanted animation. I am using TPKeyboardAvoiding scrollview to scroll the view when keyboard popup. I checked it without TPKeyboardAvoiding but same thing happening.

I encountered same issue, after debugging I found that this weird animation is happening because of
- (void)TPKeyboardAvoiding_keyboardWillShow:(NSNotification*)notification {
//...
[self layoutIfNeeded];
//...
}
- (void)TPKeyboardAvoiding_keyboardWillHide:(NSNotification*)notification {
//...
[self layoutIfNeeded];
//...
}
I am able to fix this issue by removing [self layoutIfNeeded]; method call. I don't know if this solution affects anything else.

I suspect the animation comes from the TPKeyboardAvoiding library. I also have the same screen in my app (Registration) and use the same library. However I put my textfields inside a custom UITableViewCell and have a UITableView for the registration. This way there is less code and its cleaner. I disable scrolling on the UITableView so that the UIScrollView will receive the touches correctly.
I'd suggest doing it that way.

Call superview.layoutIfNeeded() (or self.view.layoutIfNeeded(), depending on your code context) before you begin changing any animatable properties in the view. This allows the superview to finish its own layout changes (if any) before you make your own layout changes and commit your animations. (This may be difficult to track down if an external library is applying its own animations.)

Related

UIGestureRecognizer not called after setting UIViews frame inside UIScrollView

i am having some very strange issue. Basically i am implementing a drag and drop view with a snap to the horizontal 1D grid. Well, so when i drag a view and its center coordinate X is bigger or smaller then a different view, the non-dragged view should be animated to the left or right of its original position.
This works fine most of the time. But in some special cases its not working. In some situations specific situations the view does not receive any gesture callbacks anymore. I can reproduce this issue and have found out that when i remove the code that applies the animation, everything its working fine.
Basically this is the code that is called when the dragged view is at a position where the view below should be moved to the left or right
/**
* Animate element to its saved position
*/
- (void)switchElement:(unsigned int)draggedIndex with:(unsigned int)otherIndex
{
// first animate
UIView *view = views[draggedIndex];
UIView *otherView = views[otherIndex];
// IF I COMMENT THIS OUT, EVERYTHING WORKS FINE
otherView.frame = [self getImageRectForIndex:draggedIndex];
// now switch internally
if(draggedIndex != otherIndex)
{
// switch views
views[draggedIndex] = otherView;
views[otherIndex] = view;
}
}
Any idea if there is something to have in mind if i animate UIViews and have gesture recognizers attached to them?
If somebody is willing, i can paste the whole class here to test it.
SOLUTION
I am having some "highlight" views in my design. And i have moved the relevant views behind those transparent background views by accident. So now i am not using addSubview: but insertSubview:atIndex: instead.
But marking #Anthonin C. answers as the right one. Because it pointed me in the correct direction (I found it out by overriding the hitTest: method)
Would you please track the otherView.bounds property to verify that your touch isn't out of bounds. I faced this issue recently and Apple documentation provide solution here : Delivering touch events to a view outside the bounds of its parent view
Sorry, I don't have enough reputation to comment your answer.

Issue with overlapping text: iOS7

I normally post source code and examples of UI but I think its more related to an iOS7 change and I cant see it being a code bug (yet). I would have to post so much code and UI that it would be counter productive. So here is my best non-visual description:
Since upgrading a project to iOS7 I am finding that if I put call to change a UILabel or calling setText of a UIButton in a ViewDidAppear or ViewWillAppear it puts the new text right on top of the old text.
Since developing for iOS I have never had to do anything different. If I do this:
lblMyHours.text = #"12";
It shouldnt just throw that on top of my existing label.
This especially happens inside of a UITableView where I have created an iVar for a UILabel thats in a UITableViewCell. If a user makes an adjustment to a value after clicking on a cell (it takes them to a detail screen to edit), when I pop back I have it recalculate in ViewDidAppear. In that recalculating I am resetting a label like the above. But it doesnt clear out the old.
You might be adding a new label every time you return a new cell.
You should just replace the text of the current label instead.
There are two way to achieve this, one you are already doing and as #Guilherme rightly pointed out. The other way is to create a custom tableview cell and put the UILabel property in there. As for the viewDidAppear scenario, you can create a uilabel in ther .h file (in the #interface declaration) and then initialize it in ViewDidLoad method and simple use in ViewDidAppear method without having to declare it again.
I would suggest that you follow the way I described for ViewDidAppear issue, and for the UITableView issue, search for UILabels in subview of the cell everytime cellForRowAtIndex method is called and remove it from the subview, something like this before adding a new label
for(UIView *view in cell.subviews)
{
if([view isKindOfClass:[UILabel class]])
{
[view removeFromSuperview];
}
}
Hope this helps.

Stop UIView being dragged around screen

We are integrating a third party offer wall into our iOS phonegap app.
When we show the offerwall it gets added to the standard phonegap viewcontroller and shows over the top of our webview.
The problem with it is that people can drag the view all over the place so instead of just scrolling up and down in place. Which gives the effect show in the screenshot below:
What we want to achieve is being able to anchor this view so it can't be dragged around the app and can only be scrolled vertically.
In the integration code we have access to a UIView for the offerwall and the ViewController of the main app.
The offerwall is provided as a library so I don't have access to any of its code and can only deal with the UIView returned and the UIViewController I add it to. Other apps have managed to implement the view without horizontal scrolling
We are looking for code to apply to either the UIView or ViewController to prevent this.
Thanks
The offerwall view probably contains a UIScrollView that holds the actual content. You could try looping through all subviews and turn off scrolling on the first scroll view it finds:
for (UIView *view in offerwall.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView*)view;
scrollView.scrollEnabled = NO;
return;
}
}
This is definitely hacky, but if you don't have access to anything else from their code it might be your only option.
In the end the solution was quite simple. Turns out the offerwall was a UIWebView and in testing mode the offerwall page was rendering some elements that were overflowing the page hence the horizontal scrolling. In production mode the problem goes away

Custom input views: how to prevent them from fading during orientation change?

I am having trouble with assigning a UIControl subclass I made as a text field's inputView.
It shows - as expected - when the text field becomes firstResponder and hides when it resigns it firstResponder status.
However, the thing I am having trouble with is handling different orientations:
I set an autoresizingMask to the control's subviews so that there is a smooth transition when changing its width.
The thing is, they appear to be ignored as soon as I set it as the inputView.
When enabling the simulator slow-motion animations via triple-hitting shift, you can see very clearly that the view fades between the two states.
This is not what I want. Firstly it looks odd, and secondly this does not fit my needs.
Since the inputView contains a UIScrollView-like element, it would stop its deceleration animation during the fade.
Now my question is: Is there a way to prevent the fade from happening?
I would really like to use the inputView property since it saves me from writing lots of lines of code.
Also, is it possible to specify different heights for different orientations?
Here are two demo projects showing how it is and how I want it to be.
Thanks in advance.
You can create a method to your DatePicker class, that changes the geometry and layout of the view for different orientations and the implement the method
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
in your view controller and call the method on your view to align it.
Until today I have found no way to prevent them from fading.

How to react to UIControl resize when its data changes

I've built a UIControl subclass to display a 1-month calendar view on
an iPhone. Most months require 5 weeks to display the dates, but
some months need 6, so I've built the control to dynamically resize
itself as needed. I'm using UIView animation to change the frame of
the control here.
The problem is, I now need the other controls on the screen to
move/resize when the calendar changes size. And I really need that
to happen with the animation of the calendar control changing size.
Ideally, I'd do this without coding a bunch of details in my calendar
control about other controls on the screen.
What's the best strategy here? I was hoping I could somehow anchor
the other controls to the frame of the calendar control and have the
platform adjust their location/size as it animates the frame change.
But, thus far, I can't find any combination of struts and springs to
make that happen.
Do I just need to bite the bullet and add my other on-screen controls
to the animation happening inside my calendar control?
I'll be interested to see if there are better answers to this.
At this point, all I know to do is override setFrame on your calendar view and when it changes, send setNeedsLayout to its superview.
But I'm not sure if standard views will autoresize this correctly. Generally geometry flows down the view tree, not up, and you want it to do both.
You may have to implement layoutSubviews on the containing view.
Move the animation logic out of the specific view and into a view controller that manages all of the controls. The view can still figure out its own proper size, and let the view controller ask. For instance:
[self.calendarView setDate:date];
CGSize calendarSize = [self.calendarView sizeForDate:date];
[UIView animateWithDuration:...
animations:^{
... re-layout everything, including the calendarView ...
}];
Another, similar approach:
[self.calendarView setDate:date];
[UIView animateWithDuration:...
animations:^{
[self.calendarView sizeToFit];
... re-layout everything else ...
}];
There are lots of similar approaches based on your preferences. But the key is to move the logic out of the specific view. Usually a view controller is the best solution. If the controls make a logical collection that could go into a single UIView, then you could have that "collection" UIView manage the same thing in its layoutSubviews, but it's more common that a view controller is a better solution here.
Thanks for the help. I tried both of these approaches with success. The override of setFrame and implementation of layoutSubviews worked, but the other controls jumped to their new locations rather than animating to those locations as the calendar control grew.
The approach of moving the other controls during the animation is what I had to go with. However, I wanted to keep the logic of the control pretty self-contained for re-use, so I left the animation in the control but added a delegate to react to size change, and put the delegate call inside the animation block. In full disclosure, I am also animating the new month's calendar onto the control while I'm growing the control, and this way I could do both of those things in the animation block.
So, the end code looks something like this:
// inside the calendar control:
[UIView animateWithDuration:0.5 animations:^{
self.frame = newOverallFrame; // animate the growth of the control
_offScreenCalendar.frame = newOnScreenFrame; // animate new month on screen
_onScreenCalendar.frame = newOffScreenFrame; // animate old month off screen
if (self.delegate)
{
[self.delegate handleCalendarControlSizeChange:newOverallFrame]; // animate other controls per the delegate
}
}];

Resources