การเลื่อน UITableView เมื่อเลือกฟิลด์ข้อความ


251

หลังจากการทดลองและข้อผิดพลาดมากมายฉันยอมแพ้และถามคำถาม ฉันเคยเห็นคนจำนวนมากที่มีปัญหาคล้ายกัน แต่ไม่สามารถหาคำตอบทั้งหมดให้ทำงานได้

ฉันมีUITableViewซึ่งประกอบด้วยเซลล์ที่กำหนดเอง เซลล์ที่ทำจาก 5 ช่องข้อความถัดจากแต่ละอื่น ๆ (เรียงลำดับของเช่นตาราง)

เมื่อฉันพยายามเลื่อนและแก้ไขเซลล์ที่ด้านล่างของUITableViewฉันไม่สามารถจัดการเพื่อให้เซลล์ของฉันอยู่ในตำแหน่งที่ถูกต้องเหนือคีย์บอร์ด

ฉันได้เห็นคำตอบมากมายที่พูดถึงการเปลี่ยนขนาดมุมมอง ฯลฯ ... แต่ไม่มีคำตอบใดที่ทำงานได้ดีนัก

ใครช่วยอธิบายวิธี "ถูกต้อง" ด้วยตัวอย่างรหัสที่เป็นรูปธรรม?


11
เอกสารประกอบของ Applle นี้แสดงขั้นตอนในการปรับใช้โซลูชันสำหรับคำถามนี้ http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
ChrisP

@ChrisP ลิงก์นั้นระบุว่ายังไม่ได้รับการอัปเดตสำหรับ iOS 4.0
Bae

รหัสนี้มีประโยชน์: gist.github.com/TimMedcalf/9505416
landonandrey

ติดตามด้านล่าง URL จะใช้งานได้: stackoverflow.com/questions/48922266/…
Venkatesh G

คำตอบ:


126

ถ้าคุณใช้ UITableViewController แทน UIViewController มันจะทำเช่นนั้นโดยอัตโนมัติ


13
คุณลองแล้วพบว่าไม่ทำงานใช่ไหม หรือวิธีการแก้ปัญหาง่ายเกินไปสำหรับคุณที่จะเชื่อ? เพียงแค่ขยาย UITableViewController แทน UIViewController และเซลล์ที่มี textfields จะเลื่อนขึ้นเหนือคีย์บอร์ดเมื่อใดก็ตามที่ textfields กลายเป็นผู้ตอบกลับคนแรก ไม่จำเป็นต้องใช้รหัสเพิ่มเติม
แซมโฮ

3
ใช่ แต่โดยเฉพาะอย่างยิ่งบน iPad เราต้องการวิธีการที่ไม่เกี่ยวข้องกับ UITableViewController
Bob Spryn

13
ในการชี้แจงมันไม่ใช่คำตอบที่สมเหตุสมผลที่จะบอกว่าทุกครั้งที่คุณใช้ tableview จะต้องเป็นแบบเต็มหน้าจอโดยเฉพาะบน iPad มีตัวอย่างแอพที่ยอดเยี่ยมมากมายที่ไม่ทำเช่นนั้น ตัวอย่างเช่นแอปเปิลจำนวนมากของตัวเองรวมถึงแอพผู้ติดต่อบน iPad
Bob Spryn

32
มันจะไม่ทำงานหากคุณแทนที่ [super viewWillAppear: YES] นอกจากนั้นควรใช้งานได้
Rambatino

18
หากคุณแทนที่ viewWillAppear: (BOOL) เคลื่อนไหวอย่าลืมเรียก [super viewWillAppear: animated]; :)
Médéric Petit

93

ฟังก์ชั่นที่ทำการเลื่อนอาจง่ายกว่ามาก:

- (void) textFieldDidBeginEditing:(UITextField *)textField {
    UITableViewCell *cell;

    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
    // Load resources for iOS 6.1 or earlier
        cell = (UITableViewCell *) textField.superview.superview;

    } else {
        // Load resources for iOS 7 or later
        cell = (UITableViewCell *) textField.superview.superview.superview; 
       // TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Cell!
    }
    [tView scrollToRowAtIndexPath:[tView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

แค่นั้นแหละ. ไม่มีการคำนวณเลย


2
แล้วทำไมไม่ได้ล่ะ?! เพียงแทนที่ UITableViewScrollPositionTop ด้วย UITableViewScrollPositionMiddle คุณเพียงแค่ต้องขาย UITableView เพื่อปรับพื้นที่ที่มองเห็นได้แน่นอน
Mihai Damian

3
ดูเหมือนจะไม่ทำงานถ้า UITableViewController ได้รับการดูแลของการปรับขนาดมุมมองตารางเมื่อแป้นพิมพ์จะแสดง: ควบคุมลดขนาดที่มองเห็นได้ด้วยcontentInsetซึ่งเห็นได้ชัดว่าจะไม่นำเข้าบัญชีเมื่อขอหรือvisibleRows indexPathsForVisibleRows
Julian D.

16
ไม่ทำงานสำหรับมุมมองตารางสองสามแถวสุดท้าย แป้นพิมพ์จะยังคลุมเครือทุกแถวที่ไม่สามารถเลื่อนเหนือแป้นพิมพ์ได้
Alex Zavatone

3
ในการทำให้พฤติกรรมการเลื่อนอัตโนมัติทำงานบนสองสามแถวสุดท้ายของตารางให้ตรวจสอบเมื่อแถวเหล่านี้เริ่มแก้ไขและเพิ่มส่วนท้ายท้ายตารางมุมมองพร้อมมุมมองที่ว่างเปล่าของความสูงที่แน่นอน สิ่งนี้จะทำให้ tableview เลื่อนเซลล์ไปยังตำแหน่งที่ถูกต้อง
Sammio2

10
การไปยังเซลล์ผ่านสายโทรศัพท์ไปที่ superview นั้นไม่น่าเชื่อถือเว้นแต่คุณจะแน่ใจว่าคุณไปถึงเซลล์จริง ดูstackoverflow.com/a/17757851/1371070และstackoverflow.com/a/17758021/1371070
Cezar

70

ฉันทำสิ่งที่คล้ายกันมากโดยทั่วไปไม่จำเป็นต้องคำนวณสิ่งที่เฉพาะเจาะจงสำหรับรหัสของคุณ เพียงตรวจสอบหมายเหตุในรหัส:

ใน MyUIViewController.h

@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
{
     UITableView *myTableView;
     UITextField *actifText;
}

@property (nonatomic, retain) IBOutlet UITableView *myTableView;
@property (nonatomic, retain) IBOutlet UITextField *actifText;

- (IBAction)textFieldDidBeginEditing:(UITextField *)textField;
- (IBAction)textFieldDidEndEditing:(UITextField *)textField;

-(void) keyboardWillHide:(NSNotification *)note;
-(void) keyboardWillShow:(NSNotification *)note;

@end

ใน MyUIViewController.m

@implementation MyUIViewController

@synthesize myTableView;
@synthesize actifText;

- (void)viewDidLoad 
{
    // Register notification when the keyboard will be show
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillShow:)
                                          name:UIKeyboardWillShowNotification
                                          object:nil];

    // Register notification when the keyboard will be hide
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillHide:)
                                          name:UIKeyboardWillHideNotification
                                          object:nil];
}

// To be link with your TextField event "Editing Did Begin"
//  memoryze the current TextField
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
    self.actifText = textField;
}

// To be link with your TextField event "Editing Did End"
//  release current TextField
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
    self.actifText = nil;
}

-(void) keyboardWillShow:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    // Start animation
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Reduce size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height -= keyboardBounds.size.height;
    else 
        frame.size.height -= keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    // Scroll the table view to see the TextField just above the keyboard
    if (self.actifText)
      {
        CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];
        [self.myTableView scrollRectToVisible:textFieldRect animated:NO];
      }

    [UIView commitAnimations];
}

-(void) keyboardWillHide:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Increase size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height += keyboardBounds.size.height;
    else 
        frame.size.height += keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    [UIView commitAnimations];
}

@end

รุ่น Swift 1.2+:

class ViewController: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var activeText: UITextField!
    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("keyboardWillShow:"),
            name: UIKeyboardWillShowNotification,
            object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: Selector("keyboardWillHide:"),
            name: UIKeyboardWillHideNotification,
            object: nil)
    }

    func textFieldDidBeginEditing(textField: UITextField) {
        activeText = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        activeText = nil
    }

    func keyboardWillShow(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            var frame = tableView.frame
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(0.3)
            frame.size.height -= keyboardSize.height
            tableView.frame = frame
            if activeText != nil {
                let rect = tableView.convertRect(activeText.bounds, fromView: activeText)
                tableView.scrollRectToVisible(rect, animated: false)
            }
            UIView.commitAnimations()
        }
    }

    func keyboardWillHide(note: NSNotification) {
        if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            var frame = tableView.frame
            UIView.beginAnimations(nil, context: nil)
            UIView.setAnimationBeginsFromCurrentState(true)
            UIView.setAnimationDuration(0.3)
            frame.size.height += keyboardSize.height
            tableView.frame = frame
            UIView.commitAnimations()
        }
    }
}

การใช้การแจ้งเตือนและการเพิ่มความสูงของแป้นพิมพ์ในขณะที่ผสมผสานการวางแนวอุปกรณ์นั้นยอดเยี่ยมมากขอบคุณมาก! ส่วนการเลื่อนไม่ทำงานสำหรับฉันด้วยเหตุผลบางอย่างดังนั้นฉันจึงต้องใช้สิ่งนี้:[tableView scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionMiddle animated: YES];
taber

7
นี่คือคำตอบที่ดีที่สุดที่นี่ฉันคิดว่า สะอาดมาก. มีเพียงสองสิ่ง: 1) viewDidLoad ของคุณไม่ได้เรียกใช้ [super viewDidLoad] และ 2) ฉันต้องมีคณิตศาสตร์ tabbar บางอย่างในบรรทัด frame.size.height สมบูรณ์แบบเป็นอย่างอื่น! ขอบคุณ
toxaq

3
นี่คือการปรับเปลี่ยน toxaq อธิบาย: MyAppDelegate *appDelegate = (MyAppDelegate*)[[UIApplication sharedApplication] delegate]; CGFloat tabBarHeight = appDelegate.tabBarController.tabBar.frame.size.height; จากนั้นลบ tabBarHeight จากความสูงของแป้นพิมพ์ทุกที่ที่คุณใช้ความสูงของแป้นพิมพ์
Steve N

1
หากผู้ใช้แตะที่ textfield มันทำงานได้อย่างสมบูรณ์ แต่ถ้าผู้ใช้แตะที่ textfield อื่นโดยไม่ต้องกดปุ่ม return ก็จะลดขนาดของ tableview
Bhavin Ramani

1
@BhavinRamani เห็นด้วย ฉันได้เพิ่มคุณสมบัติบูลีนที่เรียบง่ายเพื่อให้จำได้ว่าแป้นพิมพ์กำลังแสดงอยู่หรือไม่และข้ามการเรียกใช้โค้ดอีกครั้งเมื่อไม่จำเป็น
เฮนรี่สกปรก

46

โซลูชันที่ง่ายที่สุดสำหรับSwift 3ซึ่งอิงกับBartłomiejSemańczyk solution :

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(CreateEditRitualViewController.keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(CreateEditRitualViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

// MARK: Keyboard Notifications

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2, animations: {
        // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
    })
}

รายละเอียดเล็กน้อย ... การใช้Notificationแทนที่จะNSNotificationเป็น "Swift 3-y" มากกว่า:
Nicolas Miari

สิ่งนี้จะช่วยในการจัดวางตำแหน่งใหม่ถ้ามี navbar - ล้อมรอบ UIView.animate ถ้าปล่อยให้ - ถ้าปล่อยให้ frame = self.navigationController? .navigationBar.frame {let y = frame.size.height + frame.origin.y}
Sean Dev

เมื่อการหมุนเกิดขึ้นมีข้อผิดพลาดในการโหลดและบางเซลล์จะหายไปเมื่อเลื่อนดูภาพบนโต๊ะ
jothikenpachi

ทางออกที่ดีขอบคุณ! หมายเหตุ - ไม่จำเป็นต้องทำ removeObserver อีกต่อไป
Nick McConnell

44

ฉันมีปัญหาเดียวกัน แต่สังเกตว่ามันจะปรากฏในมุมมองเดียวเท่านั้น ดังนั้นฉันจึงเริ่มมองหาความแตกต่างในตัวควบคุม

ฉันพบว่าพฤติกรรมการเลื่อนถูกตั้งค่าไว้ใน- (void)viewWillAppear:(BOOL)animatedอินสแตนซ์พิเศษ

ดังนั้นอย่าลืมนำไปใช้เช่นนี้:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // your code
}

และไม่สำคัญว่าคุณจะใช้UIViewControllerหรือUITableViewController; ตรวจสอบโดยการวางUITableViewเป็นของ subview self.view UIViewControllerในส่วน มันเป็นพฤติกรรมเดียวกัน มุมมองไม่อนุญาตให้เลื่อนหากการโทร[super viewWillAppear:animated];ขาดหายไป


1
มันใช้งานได้ดีมาก ฉันสงสัยว่าทำไมผู้คนถึงบอกว่า UITableView จะทำเพื่อฉันและสิ่งนี้ก็แก้ไขได้ ขอบคุณ!
olivaresF

5
ฉันมีปัญหานี้เช่นกันคำตอบนี้ควรทำให้ดีที่สุด!
Amiel Martin

ฉันเสียเวลามากในการพยายามคิดออกด้วยตัวเอง ... ขอบคุณ;)
budidino

+1 เริ่มร้องไห้นิดหน่อยฉันมีบรรทัดนั้น แต่ก็ต้องการ [tableViewController viewWillAppear: animated]; เพราะฉันกำลังเพิ่ม UITableViewController เข้ากับ UIViewController ไม่มีน้ำตาอีกแล้ว :)
ลิน lamarre

41

ฉันอาจจะพลาดสิ่งนี้เพราะฉันไม่ได้อ่านโพสต์ทั้งหมดที่นี่ แต่สิ่งที่ฉันคิดขึ้นมานั้นดูเรียบง่ายที่หลอกลวง ฉันไม่ได้ใส่สิ่งนี้ผ่านนักเขียนทดสอบในทุกสถานการณ์ แต่ดูเหมือนว่ามันจะใช้ได้ดี

เพียงปรับเนื้อหาเริ่มจากมุมมองของตารางโดยความสูงของแป้นพิมพ์แล้วเลื่อนเซลล์ไปที่ด้านล่าง:

- (void)keyboardWasShown:(NSNotification *)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    self.myTableView.contentInset = contentInsets;
    self.myTableView.scrollIndicatorInsets = contentInsets;

    [self.myTableView scrollToRowAtIndexPath:self.currentField.indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

และแน่นอนว่า

- (void)keyboardWasHidden:(NSNotification *)aNotification
{
    [UIView animateWithDuration:.3 animations:^(void) 
    {
        self.myTableView.contentInset = UIEdgeInsetsZero;
        self.myTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
    }];
}

มันง่ายเกินไปหรือไม่ ฉันพลาดอะไรไปรึเปล่า? จนถึงตอนนี้มันใช้งานได้ดีสำหรับฉัน แต่อย่างที่ฉันพูดฉันไม่ได้ใส่มันผ่านนักเขียน ...


IMO นี่คือทางออกที่ดีที่สุด สิ่งเดียวที่ฉันเปลี่ยนไปคือระยะเวลาฮาร์ดโค้ดของคุณไปที่[aNotification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue]
Andy

มันง่ายมาก แต่ปัญหาหนึ่งที่ฉันพบคือมันจะไม่ทำให้เคลื่อนไหวเปลี่ยนแปลงcontentInsetและเปลี่ยนแปลงขอบเขตการเลื่อนอย่างรวดเร็ว
Geek

หนึ่งนี้ทำงานได้ดีที่สุดสำหรับฉัน แต่ปัญหาไม่กี่ 1) ฉันไม่รู้ว่าคุณจะหา "currentField.indexPath" ได้จากที่ใดดังนั้นฉันจึงต้องบันทึก indexPath.row เป็นแท็กของฟิลด์และสร้าง indexPath ในภายหลัง 2) ไม่ทำงานกับแถวที่ด้านบนของตาราง แต่จะเลื่อนออกจากหน้าจอ ต้องเพิ่มโค้ดบางส่วนเพื่อเลื่อนดูเฉพาะถ้า indexPath ปัจจุบันของฟิลด์มากกว่าสิ่งที่พอดีบนหน้าจอ 3) ต้องใช้ kbSize กว้าง (แทนความสูง) บน iPad ถ้าเป็นแนวนอน
Travis M.

ขออภัยเราคุ้นเคยกับโค้ดของเราจนบางครั้งเราลืมใช่มั้ย currentField เป็นฟิลด์ข้อความปัจจุบันที่ฉันทำงานด้วยและ indexPath เป็นส่วนเสริมที่ฉันเพิ่มเข้ากับคลาสที่เพิ่ม NSIndexPath เพียงเพื่อให้ฉันรู้ว่านี่คือเซลล์ใด
mickm

นี่คือวิธีที่จะไปไม่ใช่การย้ายเฟรมรอบ ๆ เพียงแค่ปรับเปลี่ยนคุณสมบัติของตาราง
Nextorlg

35

ฉันคิดว่าฉันคิดวิธีแก้ปัญหาเพื่อให้ตรงกับพฤติกรรมของแอพของ Apple

ก่อนอื่นใน viewWillAppear ของคุณ: สมัครรับการแจ้งเตือนคีย์บอร์ดเพื่อให้คุณรู้ว่าเมื่อใดที่คีย์บอร์ดจะแสดงและซ่อนและระบบจะบอกขนาดของคีย์บอร์ด แต่อย่าลืมยกเลิกการลงทะเบียนใน viewWillDisappear:

[[NSNotificationCenter defaultCenter]
    addObserver:self
       selector:@selector(keyboardWillShow:)
           name:UIKeyboardWillShowNotification
         object:nil];
[[NSNotificationCenter defaultCenter]
    addObserver:self
       selector:@selector(keyboardWillHide:)
           name:UIKeyboardWillHideNotification
         object:nil];

ใช้วิธีการที่คล้ายกับด้านล่างเพื่อให้คุณปรับขนาดของ tableView เพื่อให้ตรงกับพื้นที่ที่มองเห็นได้เมื่อคีย์บอร์ดแสดง ที่นี่ฉันกำลังติดตามสถานะของแป้นพิมพ์แยกจากกันเพื่อให้ฉันสามารถเลือกเมื่อต้องการตั้งค่า tableView กลับไปที่ความสูงเต็มรูปแบบด้วยตนเองเนื่องจากคุณได้รับการแจ้งเตือนเหล่านี้ในทุก ๆ การเปลี่ยนแปลงฟิลด์ อย่าลืมที่จะใช้คีย์บอร์ด WillHide: และเลือกตำแหน่งที่เหมาะสมเพื่อแก้ไขขนาดมุมมองตารางของคุณ

-(void) keyboardWillShow:(NSNotification *)note
{
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &keyboardBounds];
    keyboardHeight = keyboardBounds.size.height;
    if (keyboardIsShowing == NO)
    {
        keyboardIsShowing = YES;
        CGRect frame = self.view.frame;
        frame.size.height -= keyboardHeight;

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationBeginsFromCurrentState:YES];
        [UIView setAnimationDuration:0.3f];
        self.view.frame = frame;
        [UIView commitAnimations];
    }
}

ตอนนี้เป็นบิตเลื่อนเราทำงานออกขนาดไม่กี่ก่อนจากนั้นเราเห็นว่าเราอยู่ที่ไหนในพื้นที่ที่มองเห็นและตั้งค่า rect ที่เราต้องการเลื่อนไปเป็นมุมมองครึ่งหนึ่งด้านบนหรือด้านล่างตรงกลางของฟิลด์ข้อความตาม ที่มันอยู่ในมุมมอง ในกรณีนี้เรามีอาร์เรย์ของ UITextFields และ enum ที่คอยติดตามพวกเขาดังนั้นการคูณ rowHeight ด้วยหมายเลขแถวทำให้เรามีออฟเซ็ตจริงของเฟรมภายในมุมมองด้านนอกนี้

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGRect frame = textField.frame;
    CGFloat rowHeight = self.tableView.rowHeight;
    if (textField == textFields[CELL_FIELD_ONE])
    {
        frame.origin.y += rowHeight * CELL_FIELD_ONE;
    }
    else if (textField == textFields[CELL_FIELD_TWO])
    {
        frame.origin.y += rowHeight * CELL_FIELD_TWO;
    }
    else if (textField == textFields[CELL_FIELD_THREE])
    {
        frame.origin.y += rowHeight * CELL_FIELD_THREE;
    }
    else if (textField == textFields[CELL_FIELD_FOUR])
    {
        frame.origin.y += rowHeight * CELL_FIELD_FOUR;
    }
    CGFloat viewHeight = self.tableView.frame.size.height;
    CGFloat halfHeight = viewHeight / 2;
    CGFloat midpoint = frame.origin.y + (textField.frame.size.height / 2);
    if (midpoint < halfHeight)
    {
        frame.origin.y = 0;
        frame.size.height = midpoint;
    }
    else
    {
        frame.origin.y = midpoint;
        frame.size.height = midpoint;
    }
    [self.tableView scrollRectToVisible:frame animated:YES];
}

ดูเหมือนว่าจะทำงานค่อนข้างดี


ทางออกที่ดี ขอบคุณสำหรับการโพสต์
Alex Reynolds

2
UIKeyboardBoundsUserInfoKeyเลิกใช้แล้วตั้งแต่ iOS 3.2 ดูโซลูชันของฉันด้านล่างที่ใช้งานได้กับ iOS ทุกรุ่นในปัจจุบัน≥ 3.0 / @ iPhoneDev
Ortwin Gentz

นี่ซับซ้อนกว่าที่มันจำเป็นต้องใช้ คำตอบของ @ user91083 นั้นเรียบง่ายและใช้งานได้
Richard Brightwell

1
มีปัญหาเล็กน้อยในการแก้ปัญหานี้ keyboardWillShow ถูกเรียกว่า AFTER textFieldDidBeginEditing ดังนั้นเมื่อเราต้องการเลื่อนไปยังเซลล์บางเฟรมของ tableView ยังไม่เปลี่ยนดังนั้นมันจะไม่ทำงาน
HiveHicks

35

หากคุณสามารถใช้งานUITableViewControllerคุณจะได้รับฟังก์ชั่นฟรี UITableViewอย่างไรก็ตามบางครั้งนี้ไม่ได้เป็นตัวเลือกโดยเฉพาะถ้าคุณจำเป็นต้องหลายมุมมองไม่ใช่แค่

โซลูชันบางอย่างที่นำเสนอที่นี่ไม่ทำงานบน iOS ≥4บางอย่างไม่ทำงานบน iPad หรือในโหมดแนวนอนบางอย่างไม่ทำงานสำหรับแป้นพิมพ์บลูทู ธ (ที่เราไม่ต้องการเลื่อน) บางคนไม่ ทำงานเมื่อสลับระหว่างช่องข้อความหลายช่อง ดังนั้นหากคุณเลือกวิธีการแก้ปัญหาใด ๆ ให้แน่ใจว่าได้ทดสอบกรณีเหล่านี้ นี้เป็นวิธีการที่เราใช้ ที่ใช้ในInAppSettingsKit :

- (void)_keyboardWillShow:(NSNotification*)notification {
    if (self.navigationController.topViewController == self) {
        NSDictionary* userInfo = [notification userInfo];

        // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0
        NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];
        if (!keyboardFrameValue) {
            keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];
        }

        // Reduce the tableView height by the part of the keyboard that actually covers the tableView
        CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
        if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
            windowRect = IASKCGRectSwap(windowRect);
        }
        CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
        if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
            viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);
        }
        CGRect frame = _tableView.frame;
        frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
        _tableView.frame = frame;
        [UIView commitAnimations];

        UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;
        NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];

        // iOS 3 sends hide and show notifications right after each other
        // when switching between textFields, so cancel -scrollToOldPosition requests
        [NSObject cancelPreviousPerformRequestsWithTarget:self];

        [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
    }
}

- (void) scrollToOldPosition {
  [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)_keyboardWillHide:(NSNotification*)notification {
    if (self.navigationController.topViewController == self) {
        NSDictionary* userInfo = [notification userInfo];

        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
        [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
        _tableView.frame = self.view.bounds;
        [UIView commitAnimations];

        [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];
    }
}   

นี่คือรหัสเต็มของคลาสใน InAppSettingsKit ในการทดสอบให้ใช้บานหน้าต่างย่อย "รายการที่สมบูรณ์" ซึ่งคุณสามารถทดสอบสถานการณ์ที่กล่าวถึงข้างต้น


ฉันไม่ทราบว่ามีประโยชน์ในการใช้สตริงแทนค่าคงที่หรือไม่เพราะถ้า Apple มาถึงแนวคิดที่จะเปลี่ยน String ภายในด้วยเหตุผลบางอย่างโซลูชันของคุณไม่ทำงานอีกต่อไป เช่นเดียวกันคุณไม่ได้รับคำเตือนเมื่อเลิกใช้งานฉันคิดว่า

@ iPortable: มันไม่เหมาะฉันรู้ คุณช่วยแนะนำวิธีแก้ปัญหาที่ดีกว่าสำหรับทุกเวอร์ชั่น≥3.0ได้หรือไม่?
Ortwin Gentz

1
ใช้งานได้อย่างมีเสน่ห์ แต่ไม่ใช่สำหรับ UIInterfaceOrientationPortraitUpsideDown จากนั้นการคำนวณการลดความสูงจะต้องกลับหัวเช่นกัน: CGFloat reductionHeight = keyboardRect.size.height - (CGRectGetMinY (viewRectAbsolute) - CGRectGetMinY (windowRect));
Klaas

นี่เป็นภาพที่เห็นได้ชัดเจนมากบน iPad และ Simulator (4.3) เห็นได้ชัดเกินไปที่จะใช้ :(
Bob Spryn

ฉันชอบที่โซลูชันนี้จะบัญชีแถบเครื่องมือที่ด้านล่างของหน้าจอ
pdemarest

24

ทางออกที่ง่ายที่สุดสำหรับSwift :

override func viewDidLoad() {
    super.viewDidLoad()

    searchBar?.becomeFirstResponder()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillHide(_:)), name: UIKeyboardDidHideNotification, object: nil)
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue.size.height {
            tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    UIView.animateWithDuration(0.2, animations: { self.table_create_issue.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) })
    // For some reason adding inset in keyboardWillShow is animated by itself but removing is not, that's why we have to use animateWithDuration here
    }

ทำงานอย่างสมบูรณ์แบบคำนวณขั้นต่ำที่จำเป็น ฉันได้เพิ่มโค้ดที่คืนค่าการแทรกตารางกลับเพื่อให้คำตอบนี้เสร็จสิ้น
Vitalii

ทางออกที่ดีที่สุดขอบคุณ ฉันโพสต์ Swift 3 เวอร์ชั่นไว้ที่นี่แล้ว: stackoverflow.com/a/41040630/1064438
squall2022

โซลูชั่นที่สมบูรณ์แบบสุดที่เคยเห็นฉันพยายามคนอื่น แต่มีปัญหาบางอย่าง โซลูชันของคุณสมบูรณ์แบบสำหรับ iOS 10.2
Wangdu Lin

8

ฉันหวังว่าพวกคุณจะได้รับการแก้ไขอ่านทั้งหมด แต่ฉันพบวิธีแก้ปัญหาของฉันดังนี้ ฉันคาดหวังว่าคุณมีเซลล์UITextFieldอยู่แล้ว ดังนั้นในการเตรียมเก็บดัชนีแถวไว้ในแท็กของฟิลด์ข้อความ

cell.textField.tag = IndexPath.row;

สร้างactiveTextFieldอินสแตนซ์ของUITextFieldด้วยขอบเขตทั่วโลกดังต่อไปนี้:

@interface EditViewController (){

    UITextField *activeTextField;

}

ดังนั้นตอนนี้คุณเพียงแค่คัดลอกวางรหัสของฉันในตอนท้าย และอย่าลืมเพิ่มด้วยUITextFieldDelegate

#pragma mark - TextField Delegation

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{

    activeTextField = textField;

    return YES;
}

- (void)textFieldDidEndEditing:(UITextField *)textField{

    activeTextField = nil;

}

ลงทะเบียนคีย์บอร์ด notifications

#pragma mark - Keyboard Activity

- (void)registerForKeyboardNotifications

{

    [[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(keyboardWasShown:)

                                             name:UIKeyboardDidShowNotification object:nil];



    [[NSNotificationCenter defaultCenter] addObserver:self

                                         selector:@selector(keyboardWillBeHidden:)

                                             name:UIKeyboardWillHideNotification object:nil];



}

จับแป้นพิมพ์Notifications:

เรียกว่าเมื่อUIKeyboardDidShowNotificationถูกส่ง

- (void)keyboardWasShown:(NSNotification*)aNotification

{

    NSDictionary* info = [aNotification userInfo];

    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);

    [self.tableView setContentInset:contentInsets];

    [self.tableView setScrollIndicatorInsets:contentInsets];

    NSIndexPath *currentRowIndex = [NSIndexPath indexPathForRow:activeTextField.tag inSection:0];

    [self.tableView scrollToRowAtIndexPath:currentRowIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];

}

เรียกว่าเมื่อUIKeyboardWillHideNotificationถูกส่ง

- (void)keyboardWillBeHidden:(NSNotification*)aNotification

{

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;

    [self.tableView setContentInset:contentInsets];

    [self.tableView setScrollIndicatorInsets:contentInsets];

}

ตอนนี้มีสิ่งหนึ่งเหลืออยู่เรียกregisterForKeyboardNotificationsใช้ViewDidLoadเมธอดเป็นวิธีดังนี้:

- (void)viewDidLoad {

    [super viewDidLoad];

    // Registering keyboard notification

    [self registerForKeyboardNotifications];

    // Your codes here...

}

คุณทำเสร็จแล้วหวังว่าtextFieldsจะไม่ถูกซ่อนโดยคีย์บอร์ดอีกต่อไป


6

การรวมและการเติมช่องว่างจากหลายคำตอบ (โดยเฉพาะอย่างยิ่ง Ortwin Gentz ​​ผู้ใช้ 98013) และโพสต์อื่นซึ่งจะทำงานนอกกรอบสำหรับ SDK 4.3 บน iPad ในโหมดแนวตั้งหรือแนวนอน:

@implementation UIView (FindFirstResponder)
- (UIResponder *)findFirstResponder
{
  if (self.isFirstResponder) {        
    return self;     
  }

  for (UIView *subView in self.subviews) {
    UIResponder *firstResponder = [subView findFirstResponder];
    if (firstResponder != nil) {
      return firstResponder;
    }
  }

  return nil;
}
@end

@implementation MyViewController

- (UIResponder *)currentFirstResponder {
  return [self.view findFirstResponder];
}

- (IBAction)editingEnded:sender {
  [sender resignFirstResponder];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
  [textField resignFirstResponder];
  return NO;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField {
  UITableViewCell *cell = (UITableViewCell*) [[textField superview] superview];
  [_tableView scrollToRowAtIndexPath:[_tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)keyboardWillShow:(NSNotification*)notification {
  if ([self currentFirstResponder] != nil) {
    NSDictionary* userInfo = [notification userInfo];

    // we don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0
    NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];
    if (!keyboardFrameValue) {
      keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];
    }

    // Reduce the tableView height by the part of the keyboard that actually covers the tableView
    CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
    CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
    CGRect frame = _tableView.frame;
    if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {
      windowRect = CGRectMake(windowRect.origin.y, windowRect.origin.x, windowRect.size.height, windowRect.size.width);
      viewRectAbsolute = CGRectMake(viewRectAbsolute.origin.y, viewRectAbsolute.origin.x, viewRectAbsolute.size.height, viewRectAbsolute.size.width);
    }
    frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    _tableView.frame = frame;
    [UIView commitAnimations];

    UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;
    NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];

    // iOS 3 sends hide and show notifications right after each other
    // when switching between textFields, so cancel -scrollToOldPosition requests
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    _topmostRowBeforeKeyboardWasShown = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];
    [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
  }
}

- (void) scrollToOldPosition {
  [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

- (void)keyboardWillHide:(NSNotification*)notification {
  if ([self currentFirstResponder] != nil) {

    NSDictionary* userInfo = [notification userInfo];

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    _tableView.frame = self.view.bounds;
    [UIView commitAnimations];

    [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];
  }
}   

@end

ฉันใช้รหัสนี้ใน iOS 4.x ได้ดี แต่ใน iOS5 มันล้มเหลวใน scrollToOldPosition เพราะ _topmostRowBeforeKeyboardWasShown ได้รับการปลดปล่อยในเวลานั้น ไม่แน่ใจว่าวิธีแก้ปัญหาคืออะไร อาจจำดัชนีแทนวัตถุได้
Thomas Tempelmann

5

หากคุณใช้ uitableview เพื่อวาง textfields ของคุณ ( จาก Jeff Lamarche ) คุณสามารถเลื่อน tableview โดยใช้วิธีมอบหมายเช่นนั้น

(หมายเหตุ: ฟิลด์ข้อความของฉันถูกเก็บไว้ในอาร์เรย์ที่มีดัชนีเดียวกันกับแถวในมุมมองตาราง)

- (void) textFieldDidBeginEditing:(UITextField *)textField
    {

        int index;
        for(UITextField *aField in textFields){

            if (textField == aField){
                index = [textFields indexOfObject:aField]-1;
            }
        }

         if(index >= 0) 
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];

        [super textFieldDidBeginEditing:textField];
    }

คุณไม่ได้อัปเดตเฟรม tableView จากนั้นแถบเลื่อนและพฤติกรรมการเลื่อนจะผิดเมื่อมีการแสดงแป้นพิมพ์ ดูวิธีแก้ปัญหาของฉัน
Ortwin Gentz

5

การแจ้งเตือนของแป้นพิมพ์ทำงานได้ แต่รหัสตัวอย่างของ Apple สำหรับสิ่งนั้นสมมติว่ามุมมองเลื่อนเป็นมุมมองรูทของหน้าต่าง นี่ไม่ใช่กรณีปกติ คุณต้องชดเชยแถบแท็บ ฯลฯ เพื่อให้ได้ออฟเซ็ตที่ถูกต้อง

มันง่ายกว่าฟังดู นี่คือรหัสที่ฉันใช้ใน UITableViewController มันมีสองตัวแปรอินสแตนซ์ hiddenRect และ keyboardShown

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification {
    if (keyboardShown)
        return;

    NSDictionary* info = [aNotification userInfo];

    // Get the frame of the keyboard.
    NSValue *centerValue = [info objectForKey:UIKeyboardCenterEndUserInfoKey];
    NSValue *boundsValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
    CGPoint keyboardCenter = [centerValue CGPointValue];
    CGRect keyboardBounds = [boundsValue CGRectValue];
    CGPoint keyboardOrigin = CGPointMake(keyboardCenter.x - keyboardBounds.size.width / 2.0,
                                         keyboardCenter.y - keyboardBounds.size.height / 2.0);
    CGRect keyboardScreenFrame = { keyboardOrigin, keyboardBounds.size };


    // Resize the scroll view.
    UIScrollView *scrollView = (UIScrollView *) self.tableView;
    CGRect viewFrame = scrollView.frame;
    CGRect keyboardFrame = [scrollView.superview convertRect:keyboardScreenFrame fromView:nil];
    hiddenRect = CGRectIntersection(viewFrame, keyboardFrame);

    CGRect remainder, slice;
    CGRectDivide(viewFrame, &slice, &remainder, CGRectGetHeight(hiddenRect), CGRectMaxYEdge);
    scrollView.frame = remainder;

    // Scroll the active text field into view.
    CGRect textFieldRect = [/* selected cell */ frame];
    [scrollView scrollRectToVisible:textFieldRect animated:YES];

    keyboardShown = YES;
}


// Called when the UIKeyboardDidHideNotification is sent
- (void)keyboardWasHidden:(NSNotification*)aNotification
{
    // Reset the height of the scroll view to its original value
    UIScrollView *scrollView = (UIScrollView *) self.tableView;
    CGRect viewFrame = [scrollView frame];
    scrollView.frame = CGRectUnion(viewFrame, hiddenRect);

    keyboardShown = NO;
}

UIKeyboardCenterEndUserInfoKeyและUIKeyboardBoundsUserInfoKeyเลิกใช้แล้วใน iOS 3.2 ดูโซลูชันของฉันด้านล่างที่ใช้งานได้กับ iOS ทุกรุ่นในปัจจุบัน≥ 3.0
Ortwin Gentz

5

หากคุณใช้Three20ให้ใช้autoresizesForKeyboardคุณสมบัติ เพียงตั้งค่าใน-initWithNibName:bundleวิธีการของตัวควบคุมมุมมองของคุณ

self.autoresizesForKeyboard = YES

สิ่งนี้จะดูแล:

  1. ฟังการแจ้งเตือนของคีย์บอร์ดและปรับกรอบของมุมมองตาราง
  2. เลื่อนไปที่การตอบกลับแรก

เสร็จแล้ว


Three20 อยู่ที่นี่อะไร คุณสามารถระบุได้ไหม
Mubin Mall

5

แนวทางของฉัน:

ฉันแรก subclass UITextField และเพิ่มคุณสมบัติ indexPath ใน cellFor ... วิธีฉันมอบคุณสมบัติ indexPath

จากนั้นฉันจะเพิ่มรหัสต่อไปนี้:

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:textField.indexPath];

CGPoint cellPoint = [cell convertPoint:textField.center toView:self.tableView];
[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, cellPoint.y-50);}];

เป็น textFieldShould / WillBegin ... ฯลฯ

เมื่อคีย์บอร์ดหายไปคุณจะต้องย้อนกลับด้วย:

[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, 0);}];

4

โซลูชันที่มีลำธารมากขึ้น มันแทรกลงในวิธีการมอบหมาย UITextField ดังนั้นจึงไม่จำเป็นต้องยุ่งกับการแจ้งเตือน w / UIKeyboard

หมายเหตุการใช้งาน:

kSettingsRowHeight - ความสูงของ UITableViewCell

offsetTarget และ offsetThreshold ถูกปิดใช้งาน kSettingsRowHeight หากคุณใช้ความสูงของแถวที่แตกต่างกันให้ตั้งค่าเหล่านั้นให้เป็นคุณสมบัติ y ของจุด [alt: คำนวณออฟเซ็ตแถวในวิธีอื่น]

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
CGFloat offsetTarget    = 113.0f; // 3rd row
CGFloat offsetThreshold = 248.0f; // 6th row (i.e. 2nd-to-last row)

CGPoint point = [self.tableView convertPoint:CGPointZero fromView:textField];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGRect frame = self.tableView.frame;
if (point.y > offsetThreshold) {
    self.tableView.frame = CGRectMake(0.0f,
                      offsetTarget - point.y + kSettingsRowHeight,
                      frame.size.width,
                      frame.size.height);
} else if (point.y > offsetTarget) {
    self.tableView.frame = CGRectMake(0.0f,
                      offsetTarget - point.y,
                      frame.size.width,
                      frame.size.height);
} else {
    self.tableView.frame = CGRectMake(0.0f,
                      0.0f,
                      frame.size.width,
                      frame.size.height);
}

[UIView commitAnimations];

return YES;

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];

[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.2];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

CGRect frame = self.tableView.frame;
self.tableView.frame = CGRectMake(0.0f,
                  0.0f,
                  frame.size.width,
                  frame.size.height);

[UIView commitAnimations];

return YES;

}


4

ใช้UITextField's delegateวิธีการ:

รวดเร็ว

func textFieldShouldBeginEditing(textField: UITextField) -> bool {
  let txtFieldPosition = textField.convertPoint(textField.bounds.origin, toView: yourTableViewHere)
  let indexPath = yourTablViewHere.indexPathForRowAtPoint(txtFieldPosition)
  if indexPath != nil {
     yourTablViewHere.scrollToRowAtIndexPath(indexPath!, atScrollPosition: .Top, animated: true)
  }
  return true
}

Objective-C

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
  CGPoint txtFieldPosition = [textField convertPoint:CGPointZero toView: yourTablViewHere];
  NSLog(@"Begin txtFieldPosition : %@",NSStringFromCGPoint(txtFieldPosition));
  NSIndexPath *indexPath = [yourTablViewHere indexPathForRowAtPoint:txtFieldPosition];

  if (indexPath != nil) {
     [yourTablViewHere scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
  }
  return YES;
}

สวัสดีฉันมีปัญหาขอให้เรื่องนี้ทำงานกับสวิฟท์ UITextField ของฉันเชื่อมต่อกับ UITableViewCell ถ้าฉันใช้รหัสนี้ใน UIViewController ของฉันฉันไม่สามารถเข้าถึง UITextFields ความคิดใด ๆ
Vetuka

4

โซลูชันที่สมบูรณ์แบบ Swift 4.2

ฉันได้สร้างGIST ด้วยชุดโปรโตคอลที่ทำให้การทำงานง่ายขึ้นด้วยการเพิ่มพื้นที่พิเศษเมื่อแป้นพิมพ์ถูกแสดงซ่อนหรือเปลี่ยนแปลง

คุณสมบัติ :

  • ทำงานได้อย่างถูกต้องกับการเปลี่ยนแปลงเฟรมของแป้นพิมพ์ (เช่นการเปลี่ยนแปลงความสูงของคีย์บอร์ดเช่น emojii →แป้นพิมพ์ปกติ)
  • TabBar & ToolBar สนับสนุนตัวอย่าง UITableView (ในตัวอย่างอื่น ๆ ที่คุณได้รับ insets ที่ไม่ถูกต้อง)
  • ระยะเวลาของภาพเคลื่อนไหวแบบไดนามิก (ไม่ใช่รหัสตายตัว)
  • วิธีการที่มุ่งเน้นโปรโตคอลที่สามารถแก้ไขได้ง่ายสำหรับคุณวัตถุประสงค์

การใช้

ตัวอย่างการใช้งานขั้นพื้นฐานในตัวควบคุมมุมมองที่มีมุมมองเลื่อนบางส่วน (ดูตารางได้รับการสนับสนุนแน่นอน)

class SomeViewController: UIViewController {
  @IBOutlet weak var scrollView: UIScrollView!

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    addKeyboardFrameChangesObserver()
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    removeKeyboardFrameChangesObserver()
  }
}

extension SomeViewController: ModifableInsetsOnKeyboardFrameChanges {
  var scrollViewToModify: UIScrollView { return scrollView }
}

แกนหลัก: เฟรมสังเกตการณ์การเปลี่ยนแปลง

โปรโตคอลKeyboardChangeFrameObserverจะดำเนินการเหตุการณ์ทุกครั้งที่มีการเปลี่ยนแปลงเฟรมแป้นพิมพ์ (รวมถึงการแสดงการซ่อนการเปลี่ยนเฟรม)

  1. โทรaddKeyboardFrameChangesObserver()ที่viewWillAppear()หรือวิธีการที่คล้ายกัน
  2. โทรremoveKeyboardFrameChangesObserver()ที่viewWillDisappear()หรือวิธีการที่คล้ายกัน

การใช้งาน: มุมมองเลื่อน

ModifableInsetsOnKeyboardFrameChangesโปรโตคอลเพิ่มUIScrollViewการสนับสนุนให้กับโปรโตคอลหลัก มันจะเปลี่ยนสิ่งที่แทรกอยู่ของมุมมองเลื่อนเมื่อมีการเปลี่ยนเฟรมแป้น

ชั้นเรียนของคุณจำเป็นต้องตั้งค่ามุมมองเลื่อนส่วนที่ใส่เข้าไปจะเพิ่มขึ้น / ลดลงจากการเปลี่ยนแปลงเฟรมของแป้นพิมพ์

var scrollViewToModify: UIScrollView { get }

3

เนื่องจากคุณมี textfields ในตารางวิธีที่ดีที่สุดคือการปรับขนาดตาราง - คุณต้องตั้งค่า tableView.frame ให้มีความสูงน้อยตามขนาดของแป้นพิมพ์ (ฉันคิดว่าประมาณ 165 พิกเซล) จากนั้นขยายอีกครั้งเมื่อ คีย์บอร์ดถูกยกเลิก

คุณยังสามารถเลือกปิดใช้งานการโต้ตอบผู้ใช้สำหรับ tableView ในเวลานั้นเช่นกันหากคุณไม่ต้องการให้ผู้ใช้เลื่อน


ฉันสองสิ่งนี้และลงทะเบียน UIKeyboardWillShowNotification เพื่อค้นหาขนาดของแป้นพิมพ์แบบไดนามิก
benzado

จำนวนที่ส่งคืนโดยวัตถุแจ้งเตือนไม่ทำงาน หรืออย่างน้อยก็ไม่ได้อยู่ใน 2.2 จำนวนที่ส่งคืนนั้นไม่ถูกต้องและฉันต้องเขียนโค้ดค่า 165 เพื่อปรับความสูงอย่างถูกต้อง (มันถูกปิดโดยห้าถึงสิบพิกเซล)
Kendall Helmstetter Gelner

2

มันทำงานได้อย่างสมบูรณ์แบบและบน iPad ด้วย

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{

    if(textField == textfield1){
            [accountName1TextField becomeFirstResponder];
        }else if(textField == textfield2){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield3 becomeFirstResponder];

        }else if(textField == textfield3){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield4 becomeFirstResponder];

        }else if(textField == textfield4){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield5 becomeFirstResponder];

        }else if(textField == textfield5){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield6 becomeFirstResponder];

        }else if(textField == textfield6){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:4 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield7 becomeFirstResponder];

        }else if(textField == textfield7){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield8 becomeFirstResponder];

        }else if(textField == textfield8){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:6 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textfield9 becomeFirstResponder];

        }else if(textField == textfield9){
            [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:7 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
            [textField resignFirstResponder];
        }

เหตุใดคุณจึงใช้ iffing และใช้กรณีพิเศษสำหรับแต่ละฟิลด์ข้อความ ระบุแต่ละฟิลด์ข้อความจาก NSIndexPath ของเซลล์และเปลี่ยนสิ่งที่น่ารังเกียจหากคำสั่งเป็นรหัส 2 บรรทัด คุณต้องการการเรียก cellForRowAtIndexPath จริงๆแล้วรับ textField จากเซลล์
Alex Zavatone

ที่จริงแล้วการพิจารณาว่าสถานการณ์นี้เลวร้ายอย่างไม่น่าเชื่อใน iOS ฉันคิดว่ามันเป็นเรื่องดีที่จะเขียนโค้ด "แก้ตัวไม่ได้อย่างสมบูรณ์และไร้สาระ" สำหรับสถานการณ์นี้
Fattie

พิจารณาคำตอบนี้เมื่อ 6 ปีที่แล้ว
WrightsCS

2

ฉันลองใช้วิธีการเกือบเหมือนกันและคิดรหัสที่เรียบง่ายและเล็กลงสำหรับรหัสเดียวกัน ฉันสร้าง IBOutlet iTextView และเชื่อมโยงกับ UITextView ใน IB

 -(void)keyboardWillShow:(NSNotification *)notification
    {
        NSLog(@"Keyboard");
        CGRect keyFrame = [[[notification userInfo]objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];

        [UIView beginAnimations:@"resize view" context:nil];
        [UIView setAnimationCurve:1];
        [UIView setAnimationDuration:1.0];
        CGRect frame = iTableView.frame;
        frame.size.height = frame.size.height -  keyFrame.size.height;
        iTableView.frame = frame;
        [iTableView scrollRectToVisible:frame animated:YES];
        [UIView commitAnimations];

    }

2

ดังนั้นหลังจากเวลาทำงานเหนื่อย ๆ พยายามใช้วิธีแก้ปัญหาปัจจุบัน (และล้มเหลวอย่างที่สุด) ในที่สุดฉันก็มีสิ่งที่ทำงานได้ดีและปรับปรุงพวกเขาให้ใช้บล็อกแอนิเมชั่นใหม่ คำตอบของฉันขึ้นอยู่กับคำตอบของ Ortwinทั้งหมด

ดังนั้นไม่ว่าด้วยเหตุผลใดรหัสข้างต้นก็ไม่ได้ผลสำหรับฉัน การตั้งค่าของฉันดูเหมือนจะค่อนข้างคล้ายกับคนอื่น ๆ แต่อาจเป็นเพราะฉันอยู่บน iPad หรือ 4.3 ... ไม่มีความคิด มันกำลังทำการคำนวณทางคณิตศาสตร์ที่แปลกประหลาดและถ่ายภาพมุมมองโต๊ะของฉันออกจากหน้าจอ

ดูผลลัพธ์สุดท้ายของโซลูชันของฉัน: http://screencast.com/t/hjBCuRrPC (โปรดละเว้นรูปภาพ :-P)

ดังนั้นฉันจึงไปกับส่วนสำคัญของสิ่งที่ Ortwin กำลังทำอยู่ แต่เปลี่ยนวิธีการทำคณิตศาสตร์บางอย่างเพื่อเพิ่มจุดเริ่มต้นของฉัน & ขนาดความสูงของมุมมองตารางของฉันด้วยความสูงของแป้นพิมพ์ เมื่อฉันลบความสูงของหน้าต่างจากผลลัพธ์นั้นมันจะบอกฉันว่าฉันได้แยกกันมากแค่ไหน หากมันมากกว่า 0 (aka มีการทับซ้อนกันบ้าง) ฉันแสดงภาพเคลื่อนไหวของความสูงของเฟรม

นอกจากนี้ยังมีปัญหาการวาดใหม่ที่แก้ไขได้โดย 1) รอให้เลื่อนไปที่เซลล์จนกว่าจะมีการเคลื่อนไหวและ 2) ใช้ตัวเลือก UIViewAnimationOptionBeginFromCurrentState เมื่อซ่อนแป้นพิมพ์

สิ่งที่ควรทราบ

  • _topmostRowBeforeKeyboardWasShown & _originalFrame เป็นตัวแปรอินสแตนซ์ที่ประกาศในส่วนหัว
  • self.guestEntryTableView คือ tableView ของฉัน (ฉันอยู่ในไฟล์ภายนอก)
  • IASKCGRectSwap เป็นวิธีของ Ortwin สำหรับการพลิกพิกัดของเฟรม
  • ฉันอัปเดตความสูงของ tableView เฉพาะหากอย่างน้อย 50px ของมันจะแสดงขึ้นมา
  • เนื่องจากฉันไม่ได้อยู่ใน UIViewController ฉันไม่มีมุมมองตัวเองดังนั้นฉันแค่กลับ tableView กลับไปที่เฟรมดั้งเดิม

อีกครั้งฉันคงไม่ได้อยู่ใกล้คำตอบนี้ถ้าฉันออร์วินไม่ได้ให้ความสำคัญกับมัน นี่คือรหัส:

- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
    self.activeTextField = textField;

    if ([self.guestEntryTableView indexPathsForVisibleRows].count) {
        _topmostRowBeforeKeyboardWasShown = (NSIndexPath*)[[self.guestEntryTableView indexPathsForVisibleRows] objectAtIndex:0];
    } else {
        // this should never happen
        _topmostRowBeforeKeyboardWasShown = [NSIndexPath indexPathForRow:0 inSection:0];
        [textField resignFirstResponder];
    }
}

- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
    self.activeTextField = nil;
}

- (void)keyboardWillShow:(NSNotification*)notification {
    NSDictionary* userInfo = [notification userInfo];

    NSValue* keyboardFrameValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];

    // Reduce the tableView height by the part of the keyboard that actually covers the tableView
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
    CGRect viewRectAbsolute = [self.guestEntryTableView convertRect:self.guestEntryTableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
    CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
    if (UIInterfaceOrientationLandscapeLeft == orientation ||UIInterfaceOrientationLandscapeRight == orientation ) {
        windowRect = IASKCGRectSwap(windowRect);
        viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);
        keyboardFrame = IASKCGRectSwap(keyboardFrame);
    }

    // fix the coordinates of our rect to have a top left origin 0,0
    viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation, windowRect.size.width, windowRect.size.height);

    CGRect frame = self.guestEntryTableView.frame;
    _originalFrame = self.guestEntryTableView.frame;

    int remainder = (viewRectAbsolute.origin.y + viewRectAbsolute.size.height + keyboardFrame.size.height) - windowRect.size.height;

    if (remainder > 0 && !(remainder > frame.size.height + 50)) {
        frame.size.height = frame.size.height - remainder;
        float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        [UIView animateWithDuration: duration
                        animations:^{
                            self.guestEntryTableView.frame = frame;
                        }
                        completion:^(BOOL finished){
                            UITableViewCell *textFieldCell = (UITableViewCell*) [[self.activeTextField superview] superview];
                            NSIndexPath *textFieldIndexPath = [self.guestEntryTableView indexPathForCell:textFieldCell];
                            [self.guestEntryTableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
                        }];
    }

}

- (void)keyboardWillHide:(NSNotification*)notification {
    NSDictionary* userInfo = [notification userInfo];
    float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration: duration
                          delay: 0.0
                        options: (UIViewAnimationOptionBeginFromCurrentState)
                     animations:^{
                         self.guestEntryTableView.frame = _originalFrame;
                     }
                     completion:^(BOOL finished){
                         [self.guestEntryTableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];
                     }];

}   

#pragma mark CGRect Utility function
CGRect IASKCGRectSwap(CGRect rect) {
    CGRect newRect;
    newRect.origin.x = rect.origin.y;
    newRect.origin.y = rect.origin.x;
    newRect.size.width = rect.size.height;
    newRect.size.height = rect.size.width;
    return newRect;
}

CGRect FixOriginRotation(CGRect rect, UIInterfaceOrientation orientation, int parentWidth, int parentHeight) {
    CGRect newRect;
    switch(orientation)
    {
        case UIInterfaceOrientationLandscapeLeft:
            newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), rect.origin.y, rect.size.width, rect.size.height);
            break;
        case UIInterfaceOrientationLandscapeRight:
            newRect = CGRectMake(rect.origin.x, parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
            break;
        case UIInterfaceOrientationPortrait:
            newRect = rect;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);
            break;
    }
    return newRect;
}

เพิ่มฟังก์ชัน FixOriginRotation ของฉันซึ่งแก้ไขระบบพิกัดของมุมมองก่อนที่คุณจะอัพเดตเฟรมเป็นต้นฉันคิดว่านี่เป็นส่วนหนึ่งของสาเหตุที่ฉันมีปัญหาในตอนแรก ไม่ทราบว่าระบบพิกัดหน้าต่างหน้าต่างหมุนด้วยอุปกรณ์!
Bob Spryn

2

โซลูตรอนนี้ใช้งานได้สำหรับฉันโปรดสังเกตบรรทัด

[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];

คุณสามารถเปลี่ยนค่า 160 เพื่อให้ตรงกับที่ทำงานกับคุณ

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
                        bkgndRect.size.height += kbSize.height;
     [activeField.superview setFrame:bkgndRect];
     [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
   activeField = textField;
}
-(void)textFieldDidEndEditing:(UITextField *)textField
 {
     activeField = nil;
 }
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    tableView.contentInset = contentInsets;
    tableView.scrollIndicatorInsets = contentInsets;
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect bkgndRect = activeField.superview.frame;
    //bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES];
}

2

หัวข้อสนทนาที่น่าสนใจมากฉันยังประสบปัญหาเดียวกันอาจแย่ลงเพราะ

  1. ฉันใช้เซลล์ที่กำหนดเองและฟิลด์ข้อความก็อยู่ข้างในนั้น
  2. ฉันต้องใช้ UIViewController เพื่อตอบสนองความต้องการของฉันดังนั้นจึงไม่สามารถใช้ประโยชน์จาก UITableViewController
  3. ฉันมีเกณฑ์ตัวกรอง / การเรียงลำดับในเซลล์ตารางของฉันนั่นคือเซลล์ ur ทำการเปลี่ยนแปลงและติดตาม indexpath และทั้งหมดจะไม่ช่วย

ดังนั้นอ่านกระทู้ที่นี่และนำเวอร์ชั่นของฉันไปใช้ซึ่งช่วยฉันในการผลักดันเนื้อหาของฉันใน iPad ในโหมดแนวนอน นี่คือรหัส (นี่ไม่ใช่ข้อผิดพลาดที่พิสูจน์ได้และทั้งหมด แต่มันแก้ไขปัญหาของฉัน) ก่อนอื่นคุณต้องมีตัวแทนในคลาสเซลล์ที่กำหนดเองของคุณซึ่งเมื่อเริ่มการแก้ไขส่ง textfield ไปที่ viewcontroller ของคุณและตั้ง activefield = theTextField

// นำไปใช้เพื่อจัดการโหมดภูมิทัศน์เท่านั้น

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbValue = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGRect aRect = myTable.frame;

    CGSize kbSize = CGSizeMake(kbValue.height, kbValue.width);

    aRect.size.height -= kbSize.height+50;
// This will the exact rect in which your textfield is present
        CGRect rect =  [myTable convertRect:activeField.bounds fromView:activeField];
// Scroll up only if required
    if (!CGRectContainsPoint(aRect, rect.origin) ) {


            [myTable setContentOffset:CGPointMake(0.0, rect.origin.y) animated:YES];

    }


}

// เรียกว่าเมื่อ UIKeyboardWillHideNotification ถูกส่ง

- (void)keyboardWillHide:(NSNotification*)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    myTable.contentInset = contentInsets;
    myTable.scrollIndicatorInsets = contentInsets;
    NSDictionary* info = [aNotification userInfo];
    CGSize kbValue = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGSize kbSize = CGSizeMake(kbValue.height, kbValue.width);
    CGRect bkgndRect = activeField.superview.frame;
    bkgndRect.size.height += kbSize.height;
    [activeField.superview setFrame:bkgndRect];
    [myTable setContentOffset:CGPointMake(0.0, 10.0) animated:YES];
}

-anoop4real


2

ฉันเพิ่งแก้ไขปัญหาดังกล่าวด้วยตัวเองหลังจากที่ฉันอ้างถึงคำตอบจำนวนมากที่พบผ่าน Google และ Stack Overflow

ครั้งแรกโปรดมั่นใจได้ว่าคุณได้ตั้งค่า IBOutlet ของ UIScrollView ของคุณแล้วโปรดใช้มองใกล้ที่แอปเปิ้ลหมอ: การจัดการแป้นพิมพ์ สุดท้ายหากคุณสามารถเลื่อนพื้นหลังได้ แต่แป้นพิมพ์ยังคงครอบคลุมพื้นที่ข้อความโปรดดูรหัสชิ้นนี้:

// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;

if (aRect.size.height < activeField.frame.origin.y+activeField.frame.size.height) {

    CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y+activeField.frame.size.height-aRect.size.height);

    [scrollView setContentOffset:scrollPoint animated:YES];

ความแตกต่างที่สำคัญระหว่างงานชิ้นนี้กับของ Apple นั้นอยู่ในเงื่อนไขที่ว่า ฉันเชื่อว่าการคำนวณระยะทางและเงื่อนไขการเลื่อนของแอปเปิ้ลว่าฟิลด์ข้อความที่ครอบคลุมด้วยแป้นพิมพ์ไม่ถูกต้องหรือไม่

แจ้งให้เราทราบหากใช้งานได้


2

ตัวอย่างใน Swift โดยใช้จุดที่แน่นอนของฟิลด์ข้อความจากรับ indexPath ของ UITextField ใน UITableViewCell ด้วย Swift :

func textFieldDidBeginEditing(textField: UITextField) {
    let pointInTable = textField.convertPoint(textField.bounds.origin, toView: self.accountsTableView)
    let textFieldIndexPath = self.accountsTableView.indexPathForRowAtPoint(pointInTable)
    accountsTableView.scrollToRowAtIndexPath(textFieldIndexPath!, atScrollPosition: .Top, animated: true)
}

1

อีกวิธีง่าย ๆ (ใช้ได้กับส่วนเดียวเท่านั้น)

//cellForRowAtIndexPath
UItextField *tf;
[cell addSubview:tf];
tf.tag = indexPath.row;
tf.delegate = self;

//textFieldDidBeginEditing:(UITextField *)text
[[self.tableView scrollToRowsAtIndexPath:[NSIndexPath indexPathForRow:text.tag in section:SECTIONINTEGER] animated:YES];

1

หาก UITableView ของคุณได้รับการจัดการโดย subclass ของ UITableViewController และไม่ใช่ UITableView และผู้รับมอบสิทธิ์ฟิลด์ข้อความคือ UITableViewController มันควรจัดการการเลื่อนทั้งหมดโดยอัตโนมัติ - ความคิดเห็นอื่น ๆ เหล่านี้ยากที่จะนำไปใช้ในทางปฏิบัติ

สำหรับตัวอย่างที่ดีโปรดดูโครงการรหัสตัวอย่างของ apple: TaggedLocations

คุณสามารถเห็นว่ามันเลื่อนโดยอัตโนมัติ แต่ดูเหมือนจะไม่มีรหัสใด ๆ ที่ทำสิ่งนี้ โปรเจ็กต์นี้มีเซลล์มุมมองตารางแบบกำหนดเองด้วยดังนั้นหากคุณสร้างแอปพลิเคชันของคุณเป็นแนวทางคุณควรได้ผลลัพธ์ที่ต้องการ


1

นี่คือวิธีที่ฉันทำผลงานนี้ซึ่งเป็นส่วนผสมของคำตอบของ Sam Ho และ Marcel W และการแก้ไขข้อผิดพลาดบางอย่างของฉันที่ทำกับรหัสเส็งเคร็งของฉัน ฉันใช้ UITableViewController ตารางจะปรับขนาดอย่างถูกต้องในขณะที่แสดงแป้นพิมพ์

1) ในviewDidLoadฉันเพิ่ม:

self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

2) ผมลืมที่จะเรียกsuperเทียบเท่าและviewWillAppear awakeFromNibฉันเพิ่มสิ่งเหล่านี้กลับเข้ามา


1

UITableViewControllerการเลื่อนอัตโนมัติหรือไม่ ความแตกต่างเมื่อเทียบกับการใช้UIViewControllerคือว่าคุณต้องสร้าง Navbar-Buttonitems โปรแกรมโดยใช้เมื่อใช้NavigationControllerTableViewController

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.