Keyboard hides textfield in my UITableViewController, view not scrolling - interface

It's my first post, when i have a problem i always find the solution here, but now i'm really stuck.
I think that I've read all the posts related to this problem, but with no luck.
I have a table view controller which contains multiple custom cells, every cell have a textfield input inside. So the user start from the top, insert the first value, then hit "Apply" button on the keyboards custom toolbar, taking control of the next textbox.
The toolbar is showing but not working at the moment, but doesn't matter, because when i press enter on simulator, the next textbox becomes active.
The real problem is about the view that isn't scrolling! It scrolls when i select the firts textbox, then nothing.
I've searched everywhere, and unfortunately i'm working a lot and i don't have enough time to solve this problem by myself.
Maybe it's a stupid thing that i'm missing, i hope someone can help.
in the .h file :
#interface PaginaCalcoliController : UITableViewController <UITextFieldDelegate>
every textbox is delegated to PaginaCalcoliController which is the view class.
I'm sorry for my english, i hope we can find a solution!

I think, to do this is by setting "contentInset".
First replace your UITableviewController with UIViewController and add UITableview as subview and wire up the tableview,datasource and delegate
then,
do like the this,
put this in view didload method.
-(void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(keyboardDidDisappear:) name:UIKeyboardDidHideNotification object:nil];
}
-(void)keyboardDidShow:(NSNotification *)notification
{
NSDictionary *info=[notification userInfo];
NSValue *aValue=[info objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyBoardRect=[aValue CGRectValue];
keyBoardRect=[self.view convertRect:keyBoardRect fromView:nil];
CGFloat keyBoardTop=keyBoardRect.origin.y;
tableView.contentInset=UIEdgeInsetsMake(0, 0, keyBoardTop+50, 0);
}
-(void)keyboardDidDisappear:(NSNotification *)notification
{
tableView.contentInset=UIEdgeInsetsMake(10, 0, 10, 0);
}
Hope this will help... :)

Not a good idea to hardcode the animation time. The 0.25 is the default for the keyboard. Better to get the value as in:
NSNumber *rate = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];

Related

textFieldDidEndEditing moves the screen when not wanted

In my app, my UITextFields are placed below where the top of the keyboard would be, so I have to move my view up so that the text field is visible over the keyboard when I'm editing. In order to do this I use the UITextFieldDelegate method, textFieldDidBeginEditing:. Then in the method textFieldDidEndEditing:, I move the view back down.
The problem occurs when I try to switch between text fields. When I do, the delegate calls the method textFieldDidEndEditing: then immediately calls textFieldDidBeginEditing: for the other text field, which makes the view go down then immediately up, so it looks like the screen jolts. Is there any workaround for this effect?
I've just been having the exact same issue, and this is the solution that I came to.
Set up a separate method for handling when your textField's keyboard is resigned, and place your self.view.center realignment in there. This way, you can ensure that your textFieldDidEndEditing method is kept separate.
Here's an example if I haven't explained myself properly. Note that when the user taps on a textField, I place a DONE button in the navigation bar (due to it being a numerical keypad), although you can link this method to the DONE button on a normal keyboard:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
UIBarButtonItem *hideKeyboardButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(resignResponder:)];
[self.navigationItem setRightBarButtonItem:hideKeyboardButton animated:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
//Nothing needs to go here anymore
}
- (void)resignResponder:(id)sender {
[textField resignFirstResponder];
//Use core animation instead of the simple action below in order to reduce 'snapback'
self.view.center = CGRectMake(0, 0, 320, 480);
}
Just check in which text field you are (for example, give them tags). Then according to this information, move or don't move your view.
I think the best way to move the textfield is to register for the notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
Do the modification of textfield frame in keyboardWillShow: & keyboardWillHide:
I used a different approach to solve this problem:
When switching from one edit control to another (field1 -> field2) you receive the following messages:
textFieldShouldBeginEditing (field2)
textFieldShouldEndEditing (field1)
textFieldDidEndEditing (field1)
textFieldDidBeginEditing (field2)
What I do is to use a counter variable (x):
Add x+=1 in textFieldShouldBeginEditing
Add x-=1 in textFieldShouldEndEditing
Then:
in textFieldDidEndEditing stretch the controls to original position if x<0
in textFieldDidBeginEditing roll up the controls if x>0

How to check if a UIView is a subview of a parent view

I have an app which I add a subview to (and remove the same subview based on user interactions). I am looking for a way to check whether the subview is present or not at any given time.
For example:
In the current view (UIView *viewA) I add a subview (UIView *viewB). I then want a way of checking whether viewB is being displayed at any given time.
Sorry if this isn't very clear, it's quite hard to describe.
an UIView stores its superview and is accessible with the superview-property just try
if([viewB superview]!=nil)
NSLog(#"visible");
else
NSLog(#"not visible");
But the better approach is to use the hidden-property of UIView
I went through the same issue and consulted Apple Documentation and came up with this elegant solution:
if([self.childView isDescendantOfView:self.parentView])
{
// The childView is contained in the parentView.
}
I updated to Swift4, Thanks a lot to #Shinnyx and #thomas.
if viewB.superview != nil{
print("visible")
}
else{
print("not visible")
}
if selfView.isDescendant(of: self.parentView) {
print("visible")
}
else{
print("not visible")
}
func isDescendant(of: UIView)
Returns a Boolean value indicating whether the receiver is a subview of a given view or identical to that view.
Here's a method I put in the appDelegate so that I can display the entire subview hierarchy from any point.
// useful debugging method - send it a view and it will log all subviews
// can be called from the debugger
- (void) viewAllSubviews:(UIView *) topView Indent:(NSString *) indent {
for (UIView * theView in [topView subviews]){
NSLog(#"%#%#", indent, theView);
if ([theView subviews] != nil)
[self viewAllSubviews:theView Indent: [NSString stringWithFormat:#"%# ",indent]];
}
}
call it with a string with one character and it will indent for you. (i.e. [appDelegate viewAllSubviews:self.view Indent:#" "];)
I find it useful to clear the debug pane first, then call this from the debugger, and copy it into a text editor like BBEdit that will show the indents.
You can call it using the mainWindow's view and see everything on your screen.

how to use reload data in table view while working with two view?

I have two classes. In my first class i have table view which contains list of countries. And in my second view i have a picker which contain sorting by name. And i have button in my first class. On this button click i go on second class. In second class when i click on picker like sorting by name then the picker value store into NSMutableString. So i want that when i go back to my first view i want to show list according to the second class picker value. I use table reload in the viewWillAppear method of first view but its not working. Sometimes it crashes.
-(void)viewWillAppear:(BOOL)animated
{
if(secondClassObj.isActStrPicker>=0)
{
sortByResultStr=[[NSString alloc]init];
sortByResultStr=[secondClassObj pickerValueStr];
NSLog(#"picker class value of sorting string fetech %# if part sssssss",sortByResultStr);
}
else
{
//the else part is not working
NSLog(#"picker class value fetech %# else part sssssss",[cmpnyPickCheckObj isActStrPicker]);
}
[countrytableView reloadData];
}
And i want that table shows value according to isActStrPicker(string) when i come back on this first view.
Thanks for helping me
Try Call NSNotificationCenter
You can reload the tableView when you are not in that VIEW;
1. First
In FirstVC.m, register a NSNotificationCenter, like this
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reloadtableview)
name:#"ReloadTableView"
object:nil];
-(void)reloadtableview
{
//reload tableview
}
2*.Call this method to ask them to reload tableview:*
[[NSNotificationCenter defaultCenter] postNotificationName:#"ReloadTableView" object:nil];

textField should update as soon as a method is called

I am working on a project which deals with an examination paper. I display only 1 question at a time on the view. After the users answers the question a second question is displayed if the user swipes towards left hand side.
I have placed a textField to display the score at each point in time. I implemented it but my score gets updated only if the user navigates to the next question.
My requirement is that as soon as the question is answered the score should be updated in the textField.
scoreField.text=[NSString stringWithFormat:#"%d",currentScore];
Is there any technique to do so whenever a question is answered? My paper has 20 questions and has 20 submit buttons so I cannot place the above code at each and every submit button action method. It would be ugly and not effective programming.
Please help if there is any way to solve my case.
Thanks in advance
If you understand your problem correctly then you don't want to set scoreField.text in every submit button handler. I am assuming that you are setting this when navigating to next question. You only need to update this when currentScore is changed. So I think it's better to create a setter for currentScore and update scoreField.text from that. Something like this:
- (void)setCurrentScore:(NSInteger)newScore {
currentScore = newScore;
scoreField.text=[NSString stringWithFormat:#"%d",currentScore];
}
And call setCurrentScore whenever you need to change the score. Or even better, you can use a setter property and write your own setter implementation.
This can be made really simple, and elegant. With a few assumptions:
There is globally accessible model object that holds the score, for example +[Examination sharedExammination].
The model object has a KVO (Key-Value-Observing) compatible property like score.
You use a custom subclass of UILabel to display the score.
With these assumptions you can let your custom UILabel register for KVO changes to to the score property and update itself automatically. The implementation of the UILabel subclass would include something like this:
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[[Examination sharedExamination] addObserver:self
forKeyPath:#"currentScore"
options:0
context:NULL];
}
return self;
}
-(void)dealloc
{
[[Examination sharedExamination] removeObserver:self
forKeyPath:#"currentScore"];
[super dealloc];
}
-(void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context
{
if ([keyPath isEqualToString:#"currentScore"]) {
scoreField.text = [NSString stringWithFormat:
#"Score: %d", [object currentScore]];
} else {
[super observerValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}
Try this:
[self.view setNeedsDisplay];

How to dismiss keyboard when using DecimalPad

I have a UITableView with a custom cell that has a TextField. I have the DecimalPad comes up, and as we all know, there is no done key. I previously had resolved this type of issue when I had a "Decimal only" textfield on a normal UIView by handling the TouchesEnded event and then checking to see if the TextField was the first responder and if so, it would then resign, but if that technique could work now then I'm not able to figure out who's TouchesEnded I should be using (The UIView that everything is presented on, the UITableView, the Cell, the CellControler, the TextField.. I think I've tried everything).
I'm hoping there's another, cleaner way of dealing with this.
Anyone?
I think David has the best idea - here is some Monotouch code to get you started. You will need to put this in the View Controller where the decimal pad is being shown:
UIView dismiss;
public override UIView InputAccessoryView
{
get
{
if (dismiss == null)
{
dismiss = new UIView(new RectangleF(0,0,320,27));
dismiss.BackgroundColor = UIColor.FromPatternImage(new UIImage("Images/accessoryBG.png"));
UIButton dismissBtn = new UIButton(new RectangleF(255, 2, 58, 23));
dismissBtn.SetBackgroundImage(new UIImage("Images/dismissKeyboard.png"), UIControlState.Normal);
dismissBtn.TouchDown += delegate {
textField.ResignFirstResponder();
};
dismiss.AddSubview(dismissBtn);
}
return dismiss;
}
}
If you're targeting iOS 4.0 or greater you can create an inputAccessoryView containing a Done button to attach to the keyboard that will dismiss the keyboard when tapped. Here is an example from the documentation on creating a simple inputAccessoryView.
You could dismiss it when the user taps on the background; I think that's the most intuitive way.
In Interface Builder, change your View's class to UIControl. This is a subclass of UIView, so your program will work the same way, but you also get the standard touch events.
From here it's simple, create a method for the Touch Down event:
[numberField resignFirstResponder]
Of course it might be slightly different with MonoTouch -- unfortunately I don't know much about it, but wanted to help.
Hopefully you can use the concept, and modify your code accordingly.
Or you may just add some gesture to your main view.
For example:
//Just initialise the gesture you want with action that dismisses your num pad
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
UISwipeGestureRecognizer *swipeToHideNumPad = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(hideNumPad:)];
swipeToHideNumPad.delegate = self;
swipeToHideNumPad.direction = UISwipeGestureRecognizerDirectionDown;
[swipeToHideNumPad setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:swipeToHideNumPad];
}
//action
- (void)hideNumPad:(UIGestureRecognizer *)gestureRecognizer
{
[self.amountTextField resignFirstResponder];
}