38 votes

Comment faire défiler la vue vers le haut lorsque le clavier apparaît?

Je sais que cette question a été posée maintes et maintes fois, mais rien ne semble fonctionner pour moi. La plupart des solutions sont à peu mis à jour, et le reste sont incroyablement énormes blocs de code qui sont dix fois plus de projets de codage. J'ai un peu de UITextFields alignés verticalement, mais lorsque le clavier lance à modifier l'un, il couvre le champ de texte. Je me demandais si il ya un simple débutant moyen pour faire défiler l'affichage, puis de retour vers le bas lors de l'édition commence et se termine?

Je vous remercie.

29voto

Peter DeWeese Points 10185

J'ai fait des solutions qui fonctionnent avec de défilement et de la non-défilement des vues à l'aide du clavier de notification et de détection de l'actuel premier intervenant, mais parfois, j'utilise cette solution triviale à la place: le moyen Le plus simple est de détecter l'ouverture du clavier via le champ de texte du délégué textViewDidBeginEditing: méthode, et de déplacer l'ensemble de la vue. La façon la plus simple de le faire est avec quelque chose le long des lignes de l'évolution self.view.bounds.origin.y à -100 (ou autre). Utilisez le raccourci textViewShouldEndEditing: méthode de le mettre à l'inverse, qui est de 100 dans ce cas. Évolution bounds est une procédure relative. Après l'avoir modifié le cadre est déplacé, mais les limites de l'origine est toujours égale à zéro.

25voto

Guillaume Points 11397

Depuis que j'ai trouvé, j'ai utiliser TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.

Il fonctionne très bien et est très facile à installer:

  • Ajouter un UIScrollView dans votre vue du contrôleur xib
  • Régler le défilement de la vue de la classe d' TPKeyboardAvoidingScrollView (toujours dans le xib, via l'identité de l'inspecteur)
  • Placez tous vos contrôles de l'intérieur que de défilement de la vue

Vous pouvez aussi créer par programmation, si vous le souhaitez.


Il y a une classe pour le même besoin à l'intérieur d'un UITableViewController ; il est seulement nécessaire dans le cas où vous soutenir une version de l'iOS 4.3 ci-dessous.

1voto

U. Ali Points 31

J'ai passé quelque temps sur ce problème et rassemblé du code de morceaux pour créer une solution finale. Mon problème était lié au défilement UITableView et à l'ouverture / fermeture du clavier.

Vous avez besoin de deux méthodes partielles dans votre classe de cellule:

     void EditingBegin(UITextField sender)
    {
        // Height of tallest cell, you can ignore this!
        float tableMargin = 70.0f;
        float tableHeight = _tableView.Frame.Size.Height;
        float keyBoardHeight = KeyboardHeight();

        NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows;
        RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section);
        RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section);
        float lastCellY = rectLast.Y - rectFirst.Y;
        if (lastCellY > tableHeight - keyBoardHeight)
        {
            float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight);
            this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
        }

        float cellPosition = this._tableView.RectForSection(this._section).Y;
        if (cellPosition > tableHeight - keyBoardHeight)
        {
            if (this._tableView.ContentInset.Bottom == 0.0f)
            {
                float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight);
                this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
            }
            else
            {
                this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true);
            }
        }
    }

    partial void EditingEnd(UITextField sender)
    {
        UIView.BeginAnimations(null);
        UIView.SetAnimationDuration(0.3f);
        this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f);
        UIView.CommitAnimations();
    }
 

puis dans votre classe de contrôleur de vue:

     public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
    {
        base.WillAnimateRotation(toInterfaceOrientation, duration);

        float bottom = this.TableView.ContentInset.Bottom;
        if (bottom > 0.0f)
        {
            if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown)
            {
                bottom = bottom * UIScreen.MainScreen.Bounds.Width / UIScreen.MainScreen.Bounds.Height;
            }
            else
            {
                bottom = bottom * UIScreen.MainScreen.Bounds.Height / UIScreen.MainScreen.Bounds.Width;
            }

            UIEdgeInsets insets = this.TableView.ContentInset;
            this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f);
        }
    }  
 

0voto

Sheharyar Points 2063

Si vous avez un UITableView ou UIScrollView il est préférable de changer les valeurs de contentOffset au lieu de faire des changements à l' frame.

De travail sur la Réponse de Pierre, l'ajout de cette méthode à votre classe fonctionne très bien:

- (void)textViewDidBeginEditing:(UITextField *)textField {
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.35f];
    CGPoint offset = self.tableView.contentOffset;
    offset.y += 200; // You can change this, but 200 doesn't create any problems
    [self.tableView setContentOffset:offset];
    [UIView commitAnimations];
}

C'est ça, pas besoin d'ajouter de l' textViewDidEndEditing méthode.


Je ne devrais pas besoin de le dire, mais pour que cela fonctionne, votre UITextField ou UITextView doit être un délégué de votre contrôleur.

-1voto

Rakesh Points 1285

j'ai un scrollview et 3 champs de texte dans cela. J'ai un code simple de ma propre application:

Le fichier .h est:

 #import <UIKit/UIKit.h>

@interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate>

@property (nonatomic, retain) NSDictionary *dict_contactDetail;

@property (nonatomic, retain) IBOutlet UILabel *lbl_name;
@property (nonatomic, retain) IBOutlet UITextField *txtField_tel;
@property (nonatomic, retain) IBOutlet UITextField *txtField_address;
@property (nonatomic, retain) IBOutlet UITextField *txtField_email;

@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;

@end
 

Fichier .m:

 #import "AddContactViewController.h"

@interface AddContactViewController ()

@end

@implementation AddContactViewController

@synthesize dict_contactDetail;

@synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil       
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

   // NSLog(@"dict_contactDetail : %@", dict_contactDetail);

    UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Add" style:UIBarButtonSystemItemDone target:self action:@selector(addEmergencyContact:)];
    self.navigationItem.rightBarButtonItem = rightButton;


    lbl_name.text = [NSString stringWithFormat:@"%@ %@", [dict_contactDetail  valueForKey:@"fname"], [dict_contactDetail  valueForKey:@"lname"]];

    txtField_tel.returnKeyType = UIReturnKeyDone;
    txtField_email.returnKeyType = UIReturnKeyDone;
    txtField_address.returnKeyType = UIReturnKeyDone;

}



-(void)addEmergencyContact:(id)sender
{
    scrollView.frame = CGRectMake(0, 0, 320, 460);
}

#pragma mark - text field delegates
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if([textField isEqual:txtField_tel])
    {
        [scrollView setContentOffset:CGPointMake(0, 70)];
        scrollView.frame = CGRectMake(0, 0, 320, 210);
    }
    if([textField isEqual:txtField_address])
    {
        [scrollView setContentOffset:CGPointMake(0, 140)];
        scrollView.frame = CGRectMake(0, 0, 320, 210);
    }
    if([textField isEqual:txtField_email])
    {
        [scrollView setContentOffset:CGPointMake(0, 210)];
        scrollView.frame = CGRectMake(0, 0, 320, 210);
    }
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    scrollView.frame = CGRectMake(0, 0, 320, 460);
    [textField resignFirstResponder];
    return YES;
}



@end
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X