繁体   English   中英

键盘出现时如何滚动查看?

[英]How to scroll view up when keyboard appears?

我知道这个问题一再被问到,但似乎没有什么对我有用。 大多数解决方案都已过时,其余的是非常庞大的代码块,比实际的项目编码大十倍。 我有几个UITextField垂直排列,但当键盘启动编辑一个时,它会覆盖文本字段。 我想知道是否有一种简单的初学者方式来滚动视图,然后在编辑开始和结束时退回?

谢谢。

我使用键盘通知和当前第一响应者的检测使用滚动和非滚动视图的解决方案,但有时我使用这个简单的解决方案:简单的方法是通过文本字段委托的textViewDidBeginEditing:检测打开键盘textViewDidBeginEditing:方法并移动整个视图。 最简单的方法是将self.view.bounds.origin.y更改为-100(或其他)。 使用相应的textViewShouldEndEditing:方法将其设置为相反的,在这种情况下为100。 改变bounds是一个相对的过程。 更改后,移动框架,但边界原点仍为零。

自从我发现它以来,我使用TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding

它工作得很好,而且很容易设置:

  • UIScrollView添加到视图控制器的xib中
  • 将滚动视图的类设置为TPKeyboardAvoidingScrollView (仍然在xib中,通过身份检查器)
  • 将所有控件放在该滚动视图中

如果需要,您还可以以编程方式创建它。


UITableViewController有一个相同需求的类; 只有在你支持4.3以下版本的iOS时才需要它。

@BenLu和其他面临功能问题的用户永远不会被调用是因为以下原因:由于委托inbufs函数返回void而不是BOOL,因此它应该如下所示:

 -(void)textFieldDidBeginEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.35f];
    CGRect frame = self.view.frame;
    frame.origin.y = -100;
    [self.view setFrame:frame];
    [UIView commitAnimations];
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.35f];
    CGRect frame = self.view.frame;
    frame.origin.y = 100;
    [self.view setFrame:frame];
    [UIView commitAnimations];
}

我花了一些时间来解决这个问题并收集了一些代码来创建一个最终解决方案。 我的问题与UITableView滚动和键盘打开/关闭有关。

您的单元类中需要两个部分方法:

    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();
    }

然后在你的视图控制器类中:

    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);
        }
    }  

如果您有UITableViewUIScrollView ,最好更改contentOffset值,而不是更改frame

Peter的答案上工作,将这个方法添加到你的班级很好地工作:

- (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];
}

就是这样,不需要添加textViewDidEndEditing方法。


我不需要这样说,但为了使其工作,您的UITextFieldUITextView 必须是您的控制器的委托

从Peter的回答开始,我在iOS 10.1下的Swift 3.0中开发了以下方法。 我正在为textView做这个,所以我已经实现了UITextViewDelegate函数textViewDidBeginEditing和textViewDidEndEditing,我调整了视图的边界。 如您所见,我将原点Y值设置为小的正数以向上滚动然后再返回到0以返回到原始位置。

这是我的ViewController的相关代码。 您不需要动画,但它增加了一个很好的触感。

func textViewDidBeginEditing(_ textView: UITextView)
{
    if UIScreen.main.bounds.height < 568 { 
        UIView.animate(withDuration: 0.75, animations: {
            self.view.bounds.origin.y = 60
        })
    }
}

func textViewDidEndEditing(_ textView: UITextView)
{
    if UIScreen.main.bounds.height < 568 {
        UIView.animate(withDuration: 0.75, animations: {
            self.view.bounds.origin.y = 0
        })
    }
}

我有一个scrollview和3个文本字段。 我有一个来自我自己的应用程序的简单代码:

.h文件是:

#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

.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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM